k8s 不允许 pod 调度到某个 node 上
cordon、drain 和 delete 三个命令都会使 node 停止被调度,后期创建的 pod 不会继续被调度到该节点上,但操作的暴力程度却不一样。
cordon 停止调度(不可调度,临时从 K8S 集群隔离)
- 影响最小,只会将 node 标识为 SchedulingDisabled 不可调度状态。
- 之后 K8S 再创建的 pod 资源,不会被调度到该节点。
- 旧有的 pod 不会受到影响,仍正常对外提供服务。
- 禁止调度命令"kubectl cordon node_name"。
- 恢复调度命令"kubectl uncordon node_name"。(恢复到 K8S 集群中,变回可调度状态)
drain 驱逐节点(先不可调度,然后排干)
- 首先,驱逐 Node 上的 pod 资源到其他节点重新创建。
- 接着,将节点调为 SchedulingDisabled 不可调度状态。
- 禁止调度命令"kubectl drain node_name –force –ignore-daemonsets –delete-local-data"
- 恢复调度命令"kubectl uncordon node_name"。(恢复到 K8S 集群中,变回可调度状态)
- drain 方式是安全驱逐 pod,会等到 pod 容器应用程序优雅停止后再删除该 pod。
- drain 驱逐流程:先在 Node 节点删除 pod,然后再在其他 Node 节点创建该 pod。所以为了确保 drain 驱逐 pod 过程中不中断服务(即做到"无感知"地平滑驱逐),必须保证要驱逐的 pod 副本数大于 1,并且采用了"反亲和策略"将这些 pod 调度到不同的 Node 节点上了!也就是说,在"多个 pod 副本 + 反亲和策略"的场景下,drain 驱逐过程对容器服务是没有影响的。
需要注意:
- 对节点执行维护操作之前(例如:内核升级,硬件维护等),您可以使用 kubectl drain 安全驱逐节点上面所有的 pod。
- drain 安全驱逐方式将会允许 pod 里面的容器遵循指定的 PodDisruptionBudgets 执行优雅中止。也就是说,drain 安全驱逐可以做到:优雅地终止 pod 里的容器进程。
- kubectl drain 返回成功表明所有的 pod(除了排除的那些)已经被安全驱逐(遵循期望优雅的中止期,并且没有违反任何应用程序级别的中断预算)。
- 然后,通过对物理机断电或者在云平台上删除节点所在的虚拟机,都能安全的将节点移除。
一般线上 K8S 的 PDB(PodDisruptionBudgets)配置的也是符合 Pod 驱逐的理想情况的,即 maxUnavailable 设置为 0,maxSurge 设置为 1:
默认情况下,kubectl drain 会忽略那些不能杀死的系统类型的 pod。drain 命令中需要添加三个参数:–force、–ignore-daemonsets、–delete-local-data
- –force 当一些 pod 不是经 ReplicationController, ReplicaSet, Job, DaemonSet 或者 StatefulSet 管理的时候就需要用–force 来强制执行 (例如:kube-proxy)
- –ignore-daemonsets 无视 DaemonSet 管理下的 Pod。即–ignore-daemonsets 往往需要指定的,这是因为 deamonset 会忽略 unschedulable 标签 (使用 kubectl drain 时会自动给节点打上不可调度标签),因此 deamonset 控制器控制的 pod 被删除后可能马上又在此节点上启动起来,这样就会成为死循环。因此这里忽略 daemonset。
- –delete-local-data 如果有 mount local volumn 的 pod,会强制杀掉该 pod。
drain 禁止调度的操作步骤:
# *确定要排空的节点的名称*
kubectl get nodes
# *查看pod*
kubectl get po
# *命令node节点开始释放所有pod,并且不接收新的pod进程*
kubectl drain [node-name] --force --ignore-daemonsets --delete-local-data
# *此时可以对该node节点进行平滑维护,后续需要恢复到k8s集群中:*
kubectl uncordon [node-name]
推荐使用姿势
通常情况下,如果要对 K8S 集群中的一台 Node 节点进行平滑维护,如升级或调整配置。正确的操作:
- cordon 临时从 K8S 集群隔离出来,标识为 SchedulingDisabled 不可调度状态。
- drain 排干该节点上的 pod 资源到其他 node 节点上。
- 对该节点展开平滑维护操作,如升级或调整配置。
- uncordon 恢复,重新回到 K8S 集群,变回可调度状态。
同时注意:为了确保 drain 驱逐 pod 的时候,容器应用服务不中断,必须满足:
- 要驱逐的 pod 副本数量必须大于 1
- 要配置"反亲和策略",确保被驱逐的 pod 被调度到不同的 Node 节点上
- deployment 采用滚动更新,设置 maxUnavailable 为 0,maxSurge 为 1