脚本能自动回滚Kubernetes版本吗?

wen 实用脚本 1

本文目录导读:

脚本能自动回滚Kubernetes版本吗?

  1. 脚本回滚的核心前提
  2. 脚本实现的关键步骤(以 kubeadm 和二进制部署为例)
  3. 风险与注意事项
  4. 更推荐的自动化方案

脚本可以实现自动回滚 Kubernetes 版本,但需要满足一定的前提条件并设计合理的执行逻辑。

脚本可以完成 控制平面组件(如 kube-apiserver, kube-controller-manager, kube-scheduler)的版本回滚,以及 节点上 kubelet 和 kube-proxy 的版本回滚,需要特别注意的是,Kubernetes 不支持跨大版本的回滚(例如从 v1.28 直接回滚到 v1.26),只允许回滚到相邻的小版本(如从 v1.28.x 回滚到 v1.28.y 或 v1.27.z)。

以下是一个脚本实现回滚的核心思路和关键步骤。

脚本回滚的核心前提

  • 使用 kubeadm 部署:如果集群是通过 kubeadm 安装的,回滚相对简单,因为 kubeadm 本身支持版本管理。
  • 控制平面高可用:如果是多主节点集群,需要逐个节点回滚,确保集群始终可用。
  • 备份关键数据:回滚前必须备份 etcd 数据库(或确保有快照),因为回滚可能导致 API 版本不兼容。
  • 应用兼容性:回滚后,可能需要适配旧的 API 版本或资源字段(Deployment 的 apiVersion: apps/v1 不能回滚到 extensions/v1beta1)。

脚本实现的关键步骤(以 kubeadm 和二进制部署为例)

下面的脚本逻辑展示了核心操作流程(伪代码 + 关键命令,需要根据实际环境调整):

#!/bin/bash
set -euo pipefail
# ===== 用户配置 =====
TARGET_VERSION="v1.27.3"   # 目标回滚版本(必须是相邻版本)
CONTROL_PLANE_NODES=("master1" "master2" "master3")
WORKER_NODES=("node1" "node2")
ETCD_SNAPSHOT_PATH="/backup/etcd-snapshot.db"
# ===== 前提检查 =====
echo "[Step 1] 检查集群当前版本和运行状态..."
CURRENT_VERSION=$(kubectl version --short | grep Server | awk '{print $3}')
echo "当前版本: $CURRENT_VERSION, 目标版本: $TARGET_VERSION"
# 简单地检查版本差异(实际应严格判断是否相邻版本)
if [[ "$CURRENT_VERSION" == "v1.28."* && "$TARGET_VERSION" != "v1.27."* ]]; then
    echo "错误:只支持回滚到相邻的次版本(如 1.28 -> 1.27)"
    exit 1
fi
# ===== 1. 备份 etcd(关键步骤)=====
echo "[Step 2] 备份 etcd 快照..."
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
  --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
  snapshot save "$ETCD_SNAPSHOT_PATH"
# ===== 2. 回滚控制平面组件(以第一个 Master 为例)=====
rollback_control_plane() {
    local node=$1
    echo "[Step 3] 回滚节点 $node 的控制平面..."
    # 排水节点(排空 Pod)
    kubectl drain "$node" --ignore-daemonsets --delete-emptydir-data
    # 使用 kubeadm 升级回滚(kubeadm 的 'upgrade' 命令可以降级)
    # 注意:kubeadm 没有直接的 'rollback' 命令,这里模拟回滚操作
    # 方法1:卸载当前版本,安装旧版本(适用于二进制部署)
    # apt-get install -y kubelet=$TARGET_VERSION kubeadm=$TARGET_VERSION kubectl=$TARGET_VERSION --allow-downgrades
    # 方法2:如果是使用 kubeadm upgrade plan 升级的,可以重新执行 upgrade apply
    # 到旧版本(kubeadm 1.27 支持降级)
    kubeadm upgrade apply "$TARGET_VERSION" --yes --force
    # 重启 kubelet
    systemctl daemon-reload
    systemctl restart kubelet
    # 取消节点排水
    kubectl uncordon "$node"
}
for node in "${CONTROL_PLANE_NODES[@]}"; do
    rollback_control_plane "$node"
done
# ===== 3. 回滚工作节点 kubelet =====
rollback_worker() {
    local node=$1
    echo "[Step 4] 回滚节点 $node 的工作组件..."
    kubectl drain "$node" --ignore-daemonsets --delete-emptydir-data
    # 回滚 kubelet 和 kube-proxy
    # apt-get install -y kubelet=$TARGET_VERSION kubectl=$TARGET_VERSION --allow-downgrades
    systemctl daemon-reload
    systemctl restart kubelet
    # 注意:kube-proxy 通常以 DaemonSet 运行,需要更新镜像版本
    kubectl set image daemonset/kube-proxy -n kube-system \
      kube-proxy=registry.k8s.io/kube-proxy:v${TARGET_VERSION#v}
    kubectl uncordon "$node"
}
for node in "${WORKER_NODES[@]}"; do
    rollback_worker "$node"
done
# ===== 4. 验证 =====
echo "[Step 5] 等待集群就绪并验证版本..."
kubectl wait --for=condition=Ready node --all --timeout=300s
kubectl get nodes -o wide
# 检查所有组件版本
kubectl get componentstatuses  # 已废弃,但旧版可用
echo "回滚完成,当前版本:"
kubectl version --short

风险与注意事项

  1. API 兼容性:如果回滚后使用了在新版本中才引入的 API(certificates.k8s.io/v1),旧版本将无法识别,回滚前需要确保所有资源清单都兼容旧版本。
  2. etcd 数据格式:etcd 在升级后可能采用新版本的数据存储格式(例如从 v3 到 v3.1),回滚后可能会遇到数据读取错误。强烈建议在回滚 etcd 之前,使用 etcdctl snapshot restore 恢复到旧版本的 etcd 实例上。
  3. kubeadm 的限制kubeadm upgrade apply 在 1.27 版本后才支持降级操作,如果版本更旧,可能需要手动卸载/重装,风险较大。
  4. Coredns 等插件:这些插件可能会在升级时自动更新配置,回滚后需要检查并手动修正其镜像版本和配置(如 kubectl edit deployment coredns -n kube-system)。
  5. 存储与网络插件:CNI(如 Calico)、CSI(如 Rook/Ceph)可能强依赖特定 Kubernetes 版本,回滚前确认插件版本兼容性。

更推荐的自动化方案

如果一定要自动化回滚,更推荐使用 GitOps 工具(如 ArgoCD, Flux)集群管理工具(如 Rancher, OpenShift) 中的版本管理功能,而不是纯脚本:

  • ArgoCD:可以通过回滚 Application 的 Git 提交历史,实现应用级别的回滚(但不是集群版本回滚)。
  • Carvel ytt/kapp:可以管理 manifest 版本。
  • Velero:如果回滚的是整个集群状态(包括 etcd),用 Velero 恢复备份更可靠(它会自动处理 etcd 快照并重启组件)。
  • 可以 用脚本回滚 Kubernetes 版本,但 仅限相邻版本,且必须配合 etcd 备份和排水操作。
  • 不建议 在生产环境使用脚本直接回滚,除非经过严格测试并配合完善的监控与回退验证,更稳妥的方式是 使用 Velero 恢复 etcd 快照基于基础设施即代码(如 Terraform)重新部署旧版本集群
  • 如果脚本用于测试/开发环境,上述逻辑基本足够;生产环境建议优先使用 Velero + etcd 快照恢复,而非直接二进制回滚

抱歉,评论功能暂时关闭!