Kubernetes(K8s)集群的生命周期管理是运维工作的核心。当我们需要对某个节点进行硬件升级、操作系统补丁或内核更新时,必须确保该节点上的应用Pod能够安全、平滑地迁移到其他健康节点上,从而实现零服务中断(Zero Downtime)。
K8s 提供了强大的工具集来实现这一目标,核心是 kubectl cordon 和 kubectl drain。
什么是节点维护模式?
节点维护模式通过两个核心步骤实现平滑迁移:
- Cordon(封锁/隔离): 阻止新的 Pod 被调度到该节点上。
- Drain(驱逐/排空): 强制驱逐该节点上所有现存的、非系统级的 Pod,并等待这些 Pod 在其他可用节点上重新启动。
关键前提条件:确保服务高可用
为了确保驱逐 Pod 时服务不中断,您的应用部署必须满足以下条件:
- 副本数量充足: 应用应通过 Deployment 或 StatefulSet 管理,并且至少配置两个或更多副本。
- PodDisruptionBudget (PDB): 这是实现零中断的关键。PDB 定义了在任何给定时间,有多少 Pod 可以同时不可用。kubectl drain 会严格遵循 PDB 的限制。
示例:配置 PDB
假设我们有一个 Deployment 包含 5 个副本,我们希望至少保证 4 个副本始终运行:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 80% # 确保至少80%的Pod可用
selector:
matchLabels:
app: my-app
核心步骤:节点维护操作指南
我们将以节点 k8s-worker-01 为例,进行维护操作。
步骤 1:标记节点为不可调度 (Cordon)
首先,通过 cordon 命令告诉 K8s 调度器,不要再将新的 Pod 调度到此节点上。
# 检查当前节点状态
kubectl get nodes
# 标记节点为不可调度
kubectl cordon k8s-worker-01
# 验证状态。节点状态应显示为 'SchedulingDisabled'
kubectl get nodes
步骤 2:安全地驱逐所有用户 Pod (Drain)
接下来,使用 drain 命令,驱逐该节点上的所有 Pod。drain 命令会尊重 PDB 的配置,确保应用平稳迁移。
重要参数解释:
- –ignore-daemonsets: 忽略 DaemonSet 管理的 Pod。DaemonSet 通常是运行在每个节点上的系统工具(如网络插件、监控代理),它们即使被驱逐也会立即在同一节点上重新创建,因此通常应忽略。
- –delete-emptydir-data (或 –delete-local-data): 用于删除使用 emptyDir 卷的 Pod。如果该数据不重要,可以使用此参数。
# 执行驱逐操作
# 注意:如果您的 Pod 使用了 local storage,并且您不希望丢失这些数据,请谨慎使用 --delete-local-data
kubectl drain k8s-worker-01 --ignore-daemonsets
# 如果需要处理使用空目录卷的 Pod,可以加上此参数
# kubectl drain k8s-worker-01 --ignore-daemonsets --delete-local-data
在执行 drain 过程中,kubectl 会输出正在驱逐的 Pod 列表。如果因为 PDB 限制而无法继续驱逐,操作会暂停,直到其他节点上的 Pod 准备就绪。
步骤 3:执行节点维护(硬件升级)
当 drain 命令成功完成后(所有用户 Pod 均已迁移),节点上将只剩下系统级的 DaemonSet Pod。此时,您可以安全地执行所需的硬件升级或维护操作。
步骤 4:重新标记节点为可调度 (Uncordon)
维护完成后,您需要将节点重新投入使用,允许 K8s 调度器将新的 Pod 调度到该节点上。
# 重新标记节点为可调度
kubectl uncordon k8s-worker-01
# 验证状态。节点状态应恢复正常
kubectl get nodes
至此,节点维护操作完成,整个过程应用服务没有中断。
汤不热吧