集群升级

集群升级

Kubernetes 集群升级需要谨慎规划,本节介绍安全的升级策略。

升级原则

版本兼容性

支持的版本差异:
  - 控制平面:最多跨 1 个次版本
  - kubelet:比 API Server 低 2 个次版本内
  - kubectl:比 API Server 高/低 1 个次版本内

示例:
  如果 API Server 是 1.28.x
  - kubelet 可以是:1.26.x, 1.27.x, 1.28.x
  - kubectl 可以是:1.27.x, 1.28.x, 1.29.x

升级路径:
  1.27.x → 1.28.x → 1.29.x (✅ 正确)
  1.27.x → 1.29.x (❌ 错误,跨度太大)

升级顺序

1. 备份集群
   ↓
2. 查看 Release Notes
   ↓
3. 测试环境验证
   ↓
4. 升级控制平面
   ↓
5. 升级 Worker 节点
   ↓
6. 升级组件(CNI、CSI、Ingress等)
   ↓
7. 验证集群功能
   ↓
8. 监控观察

升级前准备

检查集群状态

# 1. 检查节点状态
kubectl get nodes
# 所有节点应为 Ready

# 2. 检查 Pod 状态
kubectl get pods --all-namespaces | grep -v Running
# 应该没有异常 Pod

# 3. 检查组件健康
kubectl get componentstatuses

# 4. 检查 API Server 健康
kubectl get --raw /healthz

# 5. 检查证书有效期
kubeadm certs check-expiration

# 6. 查看当前版本
kubectl version --short
kubeadm version

备份关键数据

# 1. 备份 etcd
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-pre-upgrade-$(date +%Y%m%d).db

# 2. 备份配置文件
cp -r /etc/kubernetes /backup/kubernetes-config-$(date +%Y%m%d)

# 3. 备份证书
cp -r /etc/kubernetes/pki /backup/pki-$(date +%Y%m%d)

# 4. 使用 Velero 备份应用
velero backup create pre-upgrade-backup --wait

查看变更日志

# 查看 Kubernetes Release Notes
https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.29.md

# 重点关注:
# - API 弃用
# - 功能变更
# - 已知问题
# - 升级注意事项

升级控制平面

使用 kubeadm 升级(推荐)

第一个控制平面节点

# 1. 查看可升级版本
apt update
apt-cache madison kubeadm

# 2. 升级 kubeadm
apt-mark unhold kubeadm
apt-get update && apt-get install -y kubeadm=1.29.0-00
apt-mark hold kubeadm

# 3. 验证升级计划
kubeadm upgrade plan

# 输出示例:
# Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
# COMPONENT   CURRENT       TARGET
# kubelet     4 x v1.28.0   v1.29.0
# 
# Upgrade to the latest stable version:
# COMPONENT                 CURRENT   TARGET
# kube-apiserver            v1.28.0   v1.29.0
# kube-controller-manager   v1.28.0   v1.29.0
# kube-scheduler            v1.28.0   v1.29.0
# kube-proxy                v1.28.0   v1.29.0
# CoreDNS                   v1.10.1   v1.11.1
# etcd                      3.5.9-0   3.5.10-0

# 4. 执行升级
sudo kubeadm upgrade apply v1.29.0

# 5. 驱逐 Pod(如果节点上有 Pod)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

# 6. 升级 kubelet 和 kubectl
apt-mark unhold kubelet kubectl
apt-get update && apt-get install -y kubelet=1.29.0-00 kubectl=1.29.0-00
apt-mark hold kubelet kubectl

# 7. 重启 kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet

# 8. 恢复调度
kubectl uncordon <node-name>

# 9. 验证
kubectl get nodes
kubectl version

其他控制平面节点

# 1. 升级 kubeadm
apt-mark unhold kubeadm
apt-get update && apt-get install -y kubeadm=1.29.0-00
apt-mark hold kubeadm

# 2. 升级节点
sudo kubeadm upgrade node

# 3. 驱逐 Pod
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

# 4. 升级 kubelet 和 kubectl
apt-mark unhold kubelet kubectl
apt-get update && apt-get install -y kubelet=1.29.0-00 kubectl=1.29.0-00
apt-mark hold kubelet kubectl

# 5. 重启 kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet

# 6. 恢复调度
kubectl uncordon <node-name>

升级 Worker 节点

滚动升级策略

# 一次升级一个节点(推荐)

# 1. 选择第一个 Worker 节点
NODE_NAME=worker-1

# 2. 驱逐 Pod
kubectl drain $NODE_NAME --ignore-daemonsets --delete-emptydir-data

# 3. SSH 到该节点
ssh $NODE_NAME

# 4. 升级 kubeadm
apt-mark unhold kubeadm
apt-get update && apt-get install -y kubeadm=1.29.0-00
apt-mark hold kubeadm

# 5. 升级 kubelet 配置
sudo kubeadm upgrade node

# 6. 升级 kubelet 和 kubectl
apt-mark unhold kubelet kubectl
apt-get update && apt-get install -y kubelet=1.29.0-00 kubectl=1.29.0-00
apt-mark hold kubelet kubectl

# 7. 重启 kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet

# 8. 退出节点
exit

# 9. 恢复调度
kubectl uncordon $NODE_NAME

# 10. 验证节点状态
kubectl get node $NODE_NAME

# 11. 等待并观察(5-10分钟)
kubectl get pods --all-namespaces -o wide | grep $NODE_NAME

# 12. 重复以上步骤升级其他 Worker 节点

批量升级(风险较高)

# 适用于开发/测试环境
# 生产环境不推荐

# 同时升级多个节点
for node in worker-1 worker-2 worker-3; do
  kubectl drain $node --ignore-daemonsets --delete-emptydir-data &
done

# 等待所有节点被驱逐
wait

# 批量升级(使用 Ansible 或类似工具)
ansible workers -m shell -a "apt-get update && apt-get install -y kubeadm=1.29.0-00 kubelet=1.29.0-00"

# 批量重启
ansible workers -m service -a "name=kubelet state=restarted"

# 恢复所有节点
for node in worker-1 worker-2 worker-3; do
  kubectl uncordon $node
done

升级组件

CNI 插件升级

Calico

# 1. 下载新版本 manifest
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml

# 2. 应用升级
kubectl apply -f calico.yaml

# 3. 验证
kubectl get pods -n kube-system -l k8s-app=calico-node

Flannel

kubectl apply -f https://github.com/flannel-io/flannel/releases/download/v0.24.0/kube-flannel.yml

Ingress Controller 升级

# Nginx Ingress Controller
helm repo update
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --version 4.9.0

# 验证
kubectl get pods -n ingress-nginx

监控组件升级

# Prometheus Stack
helm repo update
helm upgrade prometheus prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --version 55.0.0

# 验证
kubectl get pods -n monitoring

升级验证

功能测试清单

# 1. 集群基础功能
kubectl get nodes
kubectl get pods --all-namespaces
kubectl get svc --all-namespaces

# 2. DNS 测试
kubectl run test-dns --rm -it --image=busybox -- nslookup kubernetes.default

# 3. 创建测试 Pod
kubectl run test-pod --image=nginx --restart=Never
kubectl get pod test-pod
kubectl delete pod test-pod

# 4. 网络测试
kubectl run test-1 --image=nginx
kubectl run test-2 --image=busybox --rm -it -- wget -O- http://test-1

# 5. 存储测试
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
EOF

kubectl get pvc test-pvc
kubectl delete pvc test-pvc

# 6. API 测试
kubectl api-versions
kubectl api-resources

# 7. 日志和监控
kubectl logs -n kube-system -l component=kube-apiserver
kubectl top nodes
kubectl top pods --all-namespaces

应用测试

# 1. 访问应用
curl http://myapp.example.com/health

# 2. 负载测试(可选)
ab -n 1000 -c 10 http://myapp.example.com/

# 3. 检查应用日志
kubectl logs -l app=myapp --tail=100

# 4. 检查监控指标
# 访问 Grafana Dashboard

# 5. 检查告警
# 访问 Alertmanager

回滚策略

控制平面回滚

# 如果升级后发现问题,需要回滚

# 1. 恢复 etcd 备份
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-pre-upgrade.db

# 2. 降级 kubeadm
apt-mark unhold kubeadm
apt-get install -y kubeadm=1.28.0-00
apt-mark hold kubeadm

# 3. 降级 kubelet
apt-mark unhold kubelet kubectl
apt-get install -y kubelet=1.28.0-00 kubectl=1.28.0-00
apt-mark hold kubelet kubectl

# 4. 重启服务
systemctl restart kubelet

# 5. 验证
kubectl version
kubectl get nodes

Worker 节点回滚

# 每个 Worker 节点执行

# 1. 驱逐 Pod
kubectl drain <node-name> --ignore-daemonsets

# 2. 降级软件包
apt-mark unhold kubeadm kubelet kubectl
apt-get install -y kubeadm=1.28.0-00 kubelet=1.28.0-00 kubectl=1.28.0-00
apt-mark hold kubeadm kubelet kubectl

# 3. 重启 kubelet
systemctl restart kubelet

# 4. 恢复调度
kubectl uncordon <node-name>

常见问题

问题 1:API 弃用导致应用失败

# 症状:升级后某些资源无法创建
# The API version "extensions/v1beta1" is deprecated

# 解决:
# 1. 查找使用旧 API 的资源
kubectl get all --all-namespaces -o yaml | grep "apiVersion: extensions"

# 2. 更新 API 版本
# extensions/v1beta1 → apps/v1
# 更新 Deployment、DaemonSet 等

# 3. 使用工具自动转换
kubectl convert -f old-deployment.yaml --output-version apps/v1

问题 2:证书过期

# 症状:升级后 API Server 无法访问
# x509: certificate has expired

# 解决:
# 1. 检查证书
kubeadm certs check-expiration

# 2. 更新证书
kubeadm certs renew all

# 3. 重启控制平面组件
systemctl restart kubelet

问题 3:节点 NotReady

# 症状:升级后节点状态异常

# 排查:
# 1. 查看 kubelet 日志
journalctl -u kubelet -f

# 2. 检查网络插件
kubectl get pods -n kube-system -l k8s-app=calico-node

# 3. 重启 kubelet
systemctl restart kubelet

# 4. 如果问题持续,考虑回滚

升级最佳实践

1. 充分测试

# 在测试环境完整测试升级流程
# 包括:
- 升级步骤
- 应用兼容性
- 性能测试
- 回滚流程

2. 分批升级

# 生产环境分批升级
Day 1: 升级 1 个控制平面节点
Day 2: 升级其他控制平面节点
Day 3: 升级 20% Worker 节点
Day 4: 升级 40% Worker 节点
Day 5: 升级剩余 Worker 节点

3. 监控告警

# 升级期间加强监控
- API Server 延迟
- Pod 重启次数
- 错误日志
- 应用性能指标

4. 变更窗口

# 选择业务低峰期
- 避开促销活动
- 提前通知用户
- 准备回滚方案
- 安排值班人员

5. 文档记录

# 记录升级过程
- 升级时间
- 版本变化
- 遇到的问题
- 解决方案
- 验证结果

自动化升级

使用 Terraform

resource "google_container_cluster" "primary" {
  name     = "my-cluster"
  location = "us-central1"
  
  # 自动升级配置
  maintenance_policy {
    daily_maintenance_window {
      start_time = "03:00"
    }
  }
  
  # 版本管理
  min_master_version = "1.29.0"
  
  # 节点池自动升级
  node_pool {
    management {
      auto_upgrade = true
      auto_repair  = true
    }
  }
}

使用 Cluster API

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: my-cluster
spec:
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: KubeadmControlPlane
    name: my-cluster-control-plane
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
metadata:
  name: my-cluster-control-plane
spec:
  version: v1.29.0
  rolloutStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1

小结

本节介绍了集群升级:

升级原则:版本兼容性、升级顺序
升级准备:检查状态、备份数据、查看变更
控制平面升级:kubeadm 升级流程
Worker 升级:滚动升级、批量升级
组件升级:CNI、Ingress、监控组件
升级验证:功能测试、应用测试
回滚策略:控制平面回滚、Worker 回滚
常见问题:API 弃用、证书过期
最佳实践:测试、分批、监控、文档

下一节:灾备和运维。