节点上有 Pod 时删除 Node 的行为与最佳实践
结论
可以删除,但不建议直接删。 kubectl delete node 本身不会因为节点上有 Pod 而失败,但直接删除会导致 Pod 无法优雅退出。
直接 delete node 会发生什么
- Node 对象从 etcd 中移除 — API 调用成功,不会报错。
- 节点上的 Pod 不会被自动驱逐 — Pod 对象仍留在 etcd 中,状态可能卡在
Running,但实际上已脱离管理。 - 控制器重建 Pod — 如果 Pod 属于 Deployment/StatefulSet 等控制器,控制器检测到副本数不足,会在其他可用节点上重新调度创建新 Pod。
- 原节点进程可能仍在跑 — 如果物理节点本身没关机,kubelet 和容器进程可能继续运行,只是不再与 API Server 关联,变成"孤儿"容器。
推荐的标准操作
# 1. 先驱逐节点上的所有 Pod(会自动 cordon + evict)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# 2. 确认节点上已无业务 Pod
kubectl get pods -A --field-selector spec.nodeName=<node-name>
# 3. 再删除节点
kubectl delete node <node-name>
drain 的作用是优雅地驱逐 Pod,让 Pod 按照终止流程(preStop hook → SIGTERM → 宽限期 → SIGKILL)正常退出,同时控制器在其他节点拉起新副本,保证服务不中断。
操作对比
| 操作 | 有 Pod 时能否执行 | Pod 会怎样 |
|---|---|---|
kubectl delete node |
能 | 不驱逐,可能残留/变孤儿 |
kubectl drain + delete node |
能(推荐) | 优雅驱逐后迁移到其他节点 |
注意事项
- 生产环境务必先 drain 再 delete,直接删 node 可能导致服务中断、数据丢失(emptyDir)或残留进程占用资源。
drain会自动cordon节点(标记为不可调度),然后逐个驱逐 Pod。--ignore-daemonsets:DaemonSet 管理的 Pod 不受 drain 影响(每个节点都必须跑),需要加此参数否则会报错。--delete-emptydir-data:使用 emptyDir 卷的 Pod,drain 时会丢失数据,需要显式确认。- 对于 StatefulSet,drain 会按顺序逐个驱逐,保证有状态服务的稳定性。
浙公网安备 33010602011771号