K8s drain和cordon的区别

Kubernetes中Drain和Cordon的区别

Cordon(封锁节点)

作用

  • 标记节点为不可调度
  • 新的Pod不会被调度到该节点
  • 现有Pod不受影响,继续正常运行

使用场景

1
2
3
4
5
# 封锁节点
kubectl cordon node-name

# 解除封锁
kubectl uncordon node-name

实际效果

1
2
3
4
节点状态变化:
- 调度状态:可调度 → 不可调度
- 现有Pod:继续运行
- 新Pod:不会调度到此节点

Drain(排空节点)

作用

  • 首先执行Cordon操作(封锁节点)
  • 优雅地驱逐节点上的所有Pod
  • 等待Pod在其他节点上重新启动
  • 节点变为空节点

使用场景

1
2
3
4
5
6
7
8
9
10
11
# 排空节点(默认行为)
kubectl drain node-name

# 排空节点并忽略DaemonSet
kubectl drain node-name --ignore-daemonsets

# 强制删除(不等待优雅终止)
kubectl drain node-name --force

# 设置优雅终止时间
kubectl drill node-name --timeout=300s

详细对比

特性 Cordon Drain
调度影响 ✓ 封锁调度 ✓ 封锁调度
Pod驱逐 ✗ 不驱逐 ✓ 驱逐所有Pod
节点状态 有Pod运行 空节点(除DaemonSet)
使用场景 临时维护 节点下线/升级
对服务影响 无直接影响 短暂中断后恢复

实际操作示例

Cordon操作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 查看节点状态
kubectl get nodes

# 2. 封锁节点
kubectl cordon worker-node-1
node/worker-node-1 cordoned

# 3. 验证节点状态
kubectl get node worker-node-1 -o jsonpath='{.spec.unschedulable}'
# 输出: true

# 4. 节点上Pod继续运行
kubectl get pods -o wide | grep worker-node-1
# Pod仍在运行

Drain操作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. 排空节点
kubectl drain worker-node-1 --ignore-daemonsets

# 输出示例:
# evicting pod "my-app-7d5b8c4f8c-2m9xl"
# evicting pod "nginx-deployment-6d5f78c54d-8q2wv"
# pod/nginx-deployment-6d5f78c54d-8q2wv evicted
# pod/my-app-7d5b8c4f8c-2m9xl evicted
# node/worker-node-1 drained

# 2. 验证节点状态
kubectl get pods -o wide | grep worker-node-1
# 无业务Pod(可能还有DaemonSet)

# 3. 节点已封锁
kubectl get node worker-node-1 -o jsonpath='{.spec.unschedulable}'
# 输出: true

保护的Pod类型

Drain不会删除的Pod

  1. DaemonSet管理的Pod
  2. Mirror Pod(由kubelet管理)
  3. 静态Pod

处理DaemonSet

1
2
3
4
5
# 忽略DaemonSet Pod
kubectl drain node-name --ignore-daemonsets

# 或者先删除DaemonSet Pod
kubectl delete daemonset my-daemonset -n kube-system

使用场景对比

Cordon适用场景

1
2
3
4
5
6
7
8
9
# 1. 临时维护
# 2. 节点性能问题调查
# 3. 网络问题排查
# 4. 不想让新Pod调度到节点

场景示例:
- 节点磁盘空间告警,但不想影响现有服务
- 需要临时调试节点网络配置
- 节点硬件监控异常

Drain适用场景

1
2
3
4
5
6
7
8
9
10
# 1. 节点硬件维护
# 2. 系统升级
# 3. 节点退役
# 4. 安全补丁更新

场景示例:
- 服务器内存升级
- 操作系统版本升级
- 节点需要重启
- 节点准备退役

恢复操作

恢复Cordon节点

1
kubectl uncordon node-name

恢复Drain节点

1
2
3
4
5
6
# 1. 完成维护后解除封锁
kubectl uncordon node-name

# 2. 验证节点可调度
kubectl get node node-name -o jsonpath='{.spec.unschedulable}'
# 输出: false(或无输出)

注意事项

Drain的注意事项

1
2
3
4
5
6
7
8
9
10
11
# 1. 优雅终止时间
kubectl drain node-name --grace-period=30

# 2. 超时设置
kubectl drain node-name --timeout=300s

# 3. 强制删除(谨慎使用)
kubectl drain node-name --force

# 4. 忽略特定Pod
kubectl drain node-name --ignore-daemonsets --delete-emptydir-data

最佳实践

1
2
3
4
5
6
7
8
9
# 1. 先Cordon再Drain
kubectl cordon node-name
kubectl drain node-name --ignore-daemonsets

# 2. 检查Pod迁移情况
kubectl get pods -o wide | grep new-node

# 3. 维护完成后Uncordon
kubectl uncordon node-name

总结

操作 主要目的 影响范围 适用场景
Cordon 阻止新调度 调度器 临时维护、问题排查
Drain 完全清空节点 所有Pod 节点维护、升级、退役

简单记忆

  • Cordon = “请勿入内”(现有住户可以继续住)
  • Drain = “请搬走”(所有住户都要搬走,房子要装修)