• 如何从Kubernetes集群中安全移除节点

安全移除Kubernetes节点的核心流程:隔离(cordon)→ 驱逐(drain)→ 删除(delete)→ 清理(reset),通过四步标准化操作,确保工作负载平滑迁移且集群状态无损。

blog-thumb

在 Kubernetes 集群的生命周期中,节点维护是不可避免的操作。常见场景包括:

  • 硬件升级或更换

  • 缩减集群规模以优化资源利用率

  • 故障节点替换

  • 系统迁移或环境重构

不当的节点移除可能导致

⚠️ 服务中断 ⚠️ 数据丢失 ⚠️ 资源泄漏 ⚠️ 集群状态异常

本指南将详细介绍安全移除节点的全流程,确保操作平滑无感知。

1、预检准备

1.1 环境检查

kubectl get nodes                 # 查看所有节点状态
kubectl describe node <节点名称>   # 检查目标节点详情

确认节点状态为 Ready 且无异常事件(如内存压力、磁盘压力)。

1.2 资源评估

kubectl get pods -o wide --all-namespaces | grep <节点名称>
  • 识别关键工作负载(如数据库、有状态服务)

  • 检查Pod Disruption Budget(PDB)是否允许驱逐

    kubectl get pdb --all-namespaces
    

1.3 维护窗口规划

  • 选择业务低峰期操作

  • 通知相关团队服务可能短暂中断

2、节点移除四步流程

2.1 步骤1:标记为不可调度(隔离节点)

kubectl cordon <节点名称>

原理:将节点标记为SchedulingDisabled,阻止新Pod调度到该节点,但现有Pod继续运行。

验证

kubectl get nodes | grep <节点名称>

输出应显示 STATUSReady,SchedulingDisabled

2.2 步骤2:驱逐工作负载(核心步骤)

kubectl drain <节点名称> \
  --ignore-daemonsets \      # 忽略DaemonSet管理的Pod
  --delete-emptydir-data \   # 删除emptyDir临时数据
  --force \                  # 强制删除无响应Pod
  --timeout=300s             # 超时设置(建议5-10分钟)
  --pod-selector="!controller-revision-hash" # 选择性排除特定Pod

关键注意事项

  1. DaemonSet处理Flannel/Calico 等网络插件通常通过 DaemonSet 运行,需确保其他节点有副本。

  2. 有状态服务

    StatefulSet 需确认存储卷能自动迁移(如使用云存储)

    kubectl get pv -o wide | grep <节点名称>
    
  3. 本地存储

    使用 local 卷的 Pod 需手动迁移并删除重建

驱逐过程监控

watch kubectl get pods -o wide | grep <节点名称>  # 实时观察Pod迁移状态

2.3 步骤3:正式删除节点

kubectl delete node <节点名称>

效果:从 API Server 中移除节点对象,kube-controller-manager 停止监控该节点。

2.4 步骤4:节点级清理(在目标服务器执行)

sudo kubeadm reset           # 重置kubeadm安装
sudo rm -rf \
  /etc/kubernetes \         # 删除配置
  /var/lib/kubelet \        # 清理容器运行时数据
  /var/lib/etcd \           # etcd数据(如果是控制节点)
  ~/.kube/config            # 客户端配置

sudo iptables -F            # 重置iptables规则
sudo ipvsadm --clear        # 清理IPVS规则(如使用IPVS模式)
sudo systemctl stop kubelet docker containerd  # 停止服务

3、环境验证

3.1 集群状态检查

kubectl get nodes                 # 确认节点已消失
kubectl get pods -A -o wide       # 检查所有Pod运行位置

3.2 服务健康验证

kubectl get svc                  # 检查服务Endpoint
kubectl top nodes                # 确认资源负载均衡
curl -I <服务IP>:<端口>           # 实际访问测试

4、特殊场景处理

4.1 场景1:节点已宕机无法连接

kubectl delete node <节点名称> --force --grace-period=0

后续操作

  1. 物理重启节点

  2. 手动清理残留进程:

    sudo pkill -9 kubelet docker containerd
    

4.2 场景2:驱逐过程卡住

排查步骤

  1. 检查阻塞Pod:

    kubectl describe pod <Pod名称> | grep -A 10 Events
    
  2. 强制删除:

    kubectl delete pod <Pod名称> --grace-period=0 --force
    
  3. 绕过保护机制(谨慎使用):

    kubectl drain <节点名称> --disable-eviction
    

4.3 场景3:关键Pod无法迁移

解决方案

  1. 修改Deployment/StatefulSet配置:

    kubectl edit deploy/<名称>  # 手动调整节点亲和性
    
  2. 临时副本扩容:

    kubectl scale deploy/<名称> --replicas=+1
    

5、最佳实践与风险防控

  1. 维护窗口期

    • 避免业务高峰时段操作
    • 设置维护模式(如通过Cluster API)
  2. 有状态服务保护

    # 示例:PodDisruptionBudget
    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: zk-pdb
    spec:
      minAvailable: 2   # 保证最少可用副本数
      selector:
        matchLabels:
          app: zookeeper
    
  3. 自动化工具

    • 使用cluster-autoscaler自动缩容
    • 通过Argo CD/GitOps管理节点生命周期
  4. 监控告警

    操作后检查:

    • 节点不可用告警
    • Pod未就绪事件
    • 资源利用率突变

6、结语

安全移除Kubernetes节点是集群运维的核心技能。通过cordon→drain→delete的标准流程,配合完善的预检和验证,可确保服务零中断。

关键要点

  1. 始终优先驱逐(drain)而非直接删除。

  2. 特别关注有状态服务和本地存储

  3. 操作后验证集群整体健康状态

最后建议:在生产环境操作前,务必在测试集群验证流程。保留操作日志和快照(如etcd备份),为可能的回滚做好准备。

通过遵循本指南,您将能够高效安全地管理Kubernetes节点生命周期,确保集群稳定运行。