codecamp

Kubernetes 安全地清空一个节点

安全地清空一个节点

本页展示了如何在确保 PodDisruptionBudget 的前提下,安全地清空一个节点。

在开始之前

您的 Kubernetes 服务器必须是 1.5 版或更高版本。 要检查版本,请输入 ​kubectl version​。

此任务假定你已经满足了以下先决条件:

  • 使用的 Kubernetes 版本 >= 1.5。
  • 以下两项,具备其一:
    1. 在节点清空期间,不要求应用程序具有高可用性
    2. 你已经了解了 PodDisruptionBudget 的概念, 并为需要它的应用程序配置了 PodDisruptionBudget。

(可选) 配置干扰预算

为了确保你的负载在维护期间仍然可用,你可以配置一个 ​PodDisruptionBudget​。 如果可用性对于正在清空的该节点上运行或可能在该节点上运行的任何应用程序很重要, 首先 配置一个 ​PodDisruptionBudgets ​并继续遵循本指南。

使用 kubectl drain 从服务中删除一个节点

在对节点执行维护(例如内核升级、硬件维护等)之前, 可以使用 ​kubectl drain​ 从节点安全地逐出所有 Pods。 安全的驱逐过程允许 Pod 的容器 体面地终止, 并确保满足指定的 PodDisruptionBudgets。

Note: 默认情况下, ​kubectl drain​ 将忽略节点上不能杀死的特定系统 Pod; 有关更多细节,请参阅 kubectl drain 文档。

kubectl drain​ 的成功返回,表明所有的 Pods(除了上一段中描述的被排除的那些), 已经被安全地逐出(考虑到期望的终止宽限期和你定义的 PodDisruptionBudget)。 然后就可以安全地关闭节点, 比如关闭物理机器的电源,如果它运行在云平台上,则删除它的虚拟机。

首先,确定想要清空的节点的名称。可以用以下命令列出集群中的所有节点:

kubectl get nodes

接下来,告诉 Kubernetes 清空节点:

kubectl drain <node name>

一旦它返回(没有报错), 你就可以下线此节点(或者等价地,如果在云平台上,删除支持该节点的虚拟机)。 如果要在维护操作期间将节点留在集群中,则需要运行:

kubectl uncordon <node name>

然后告诉 Kubernetes,它可以继续在此节点上调度新的 Pods。

并行清空多个节点 

kubectl drain​ 命令一次只能发送给一个节点。 但是,你可以在不同的终端或后台为不同的节点并行地运行多个 ​kubectl drain​ 命令。 同时运行的多个 drain 命令仍然遵循你指定的 PodDisruptionBudget 。

例如,如果你有一个三副本的 StatefulSet, 并设置了一个 ​PodDisruptionBudget​,指定 ​minAvailable: 2​。 如果所有的三个 Pod 均就绪,并且你并行地发出多个 drain 命令, 那么 ​kubectl drain​ 只会从 StatefulSet 中逐出一个 Pod, 因为 Kubernetes 会遵守 PodDisruptionBudget 并确保在任何时候只有一个 Pod 不可用 (最多不可用 Pod 个数的计算方法:​replicas - minAvailable​)。 任何会导致就绪副本数量低于指定预算的清空操作都将被阻止。

驱逐 API

如果你不喜欢使用 ​kubectl drain​ (比如避免调用外部命令,或者更细化地控制 pod 驱逐过程), 你也可以用驱逐 API 通过编程的方式达到驱逐的效果。


Kubernetes 声明网络策略
Kubernetes 开发云控制器管理器
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

Kubernetes 管理集群

Kubernetes Service

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }