想象一下这样的场景:凌晨两点,你收到告警通知,生产环境中的某个Kubernetes节点出现硬件故障需要紧急维护。此时如何在不影响线上服务的情况下安全地将该节点下线?这正是每个Kubernetes运维工程师必须掌握的核心技能。
在开始任何节点维护操作前,完善的准备工作能避免80%的意外状况。首先需要确认节点状态:
bash复制kubectl get nodes
kubectl describe node <node-name>
重点关注以下指标:
重要提示:始终在维护前创建集群状态的快照,包括所有运行中的Pod和节点配置。可以使用
kubectl get all --all-namespaces -o yaml > cluster-snapshot.yaml保存当前状态。
风险评估矩阵应包含:
| 风险类型 | 评估指标 | 缓解措施 |
|---|---|---|
| 服务中断 | Pod副本数、PDB配置 | 确保有足够冗余 |
| 数据丢失 | 存储类型(emptyDir/PVC) | 备份关键数据 |
| 资源不足 | 集群剩余资源 | 预留缓冲资源 |
当我们需要对节点进行维护时,第一步就是使用kubectl cordon将其标记为不可调度。这个看似简单的命令背后,Kubernetes调度器会执行以下动作:
spec.unschedulable字段设为true典型应用场景包括:
对于复杂的生产环境,单纯的cordon可能不够。我们可以结合以下策略:
bash复制# 同时添加NoSchedule污点
kubectl taint nodes <node-name> dedicated=maintenance:NoSchedule
这种组合方式提供了双重保障:
kubectl drain是节点维护中最关键的步骤,它将:
基本命令格式:
bash复制kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
不同类型的Pod需要特别处理:
DaemonSet Pods
--ignore-daemonsets显式声明--force参数有本地存储的Pod
--delete-emptydir-data删除临时数据受PDB保护的Pod
为了最小化服务影响,建议采用分批次驱逐策略:
可以使用以下命令实现分批驱逐:
bash复制# 先驱逐特定标签的Pod
kubectl drain <node-name> --pod-selector='app=non-critical'
维护完成后,使用kubectl uncordon恢复节点时需要注意:
bash复制kubectl get node <node-name> -o wide
对于大型集群,建议采用渐进式恢复:
bash复制kubectl uncordon <node-name>
bash复制kubectl taint nodes <node-name> dedicated-
让我们通过一个实际案例来串联所有操作。假设需要对节点进行内核升级:
bash复制# 1. 预检查
kubectl get pods -o wide | grep <node-name>
# 2. 隔离节点
kubectl cordon <node-name>
# 3. 安全驱逐
kubectl drain <node-name> \
--ignore-daemonsets \
--grace-period=900 \
--timeout=10m
# 4. 执行维护(SSH到节点)
sudo apt update && sudo apt upgrade linux-image-generic
# 5. 重启节点
sudo reboot
# 6. 等待节点重新加入集群
watch kubectl get nodes
# 7. 恢复调度
kubectl uncordon <node-name>
# 8. 验证服务
kubectl get pods -o wide | grep <node-name>
当需要维护多个节点时,应考虑:
对于频繁的维护操作,可以建立自动化流程:
bash复制#!/bin/bash
NODE=$1
# 安全隔离和驱逐
kubectl cordon $NODE
kubectl drain $NODE --ignore-daemonsets --delete-emptydir-data
# 执行维护脚本
ssh $NODE 'sudo /opt/maintenance/standard.sh'
# 健康检查
ssh $NODE 'kubectl node-health-check'
# 恢复服务
kubectl uncordon $NODE
在维护过程中,应实时监控:
配置关键告警:
遇到问题时,按照以下步骤排查:
bash复制kubectl describe node <node-name>
bash复制kubectl get events --field-selector involvedObject.name=<pod-name>
bash复制kubectl describe nodes | grep Allocatable -A 5
bash复制kubectl run -it --rm debug --image=busybox --restart=Never -- ping <target>
常见问题处理:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| Drain卡住 | PDB限制 | 临时调整PDB或使用--force |
| Pod无法重调度 | 资源不足 | 扩容集群或清理资源 |
| 节点无法恢复 | 内核问题 | 回滚系统更新 |