欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

节点不可用时快速迁移 Pods

程序员文章站 2022-04-25 07:56:50
...

本文永久链接: https://www.xtplayer.cn/kubernetes/fast-migration-pod-when-node-unavailable/

当节点宕机或者节点网络异常时,我们希望该节点上的 Pod 能够快速迁移到其他节点,并提供服务。但是测试发现节点 Down 掉以后,Pod 并不会立即迁移到其他节点。使用不同的 Kubernetes 版本测试,在默认配置下,需要等待将近 6 到 10 分钟节点上的 Pod 才会开始迁移。

这个现象与 Kubelet 的状态更新机制密切相关,下面我们来分析下 Kubelet 状态更新的基本流程。

  • kubelet

    kubelet 自身会定期更新状态到 apiserver,通过参数 --node-status-update-frequency 配置上报频率,默认 10s 上报一次。

  • kube-controller-manager

    1. kube-controller-manager 会定时去检查 kubelet 的状态,可通过 --node-monitor-period 自定义这个时间 ,默认是 5s
    2. 当 node 失联一段时间后,kubernetes 判定 node 为 notready 状态,这段时长可通过 --node-monitor-grace-period 参数配置,默认 40s
    3. 当 node 状态为 notready 一段时间后,kubernetes 判定 node 为 unhealthy 状态,这段时长可通过 --node-startup-grace-period 参数配置,默认 1m0s
    4. 当 node 状态为 unhealthy 一段时间后,kubernetes 开始删除原 node 上的 Pod,这段时长可通过 --pod-eviction-timeout 参数配置,默认 5m0s
  • kube-apiserver (Kubernetes v1.13 版本及以后版本)

    ​Kubernetes v1.13 及以后版本默认开启了 基于污点的驱逐,默认 300 秒。节点不同状态时会自动添加不同的污点,因而 Pod 的驱逐时间将受到节点状态的影响。

    1. default-not-ready-toleration-seconds: 表示 notReady:NoExecute 容忍的时间。notReady:NoExecute 默认添加到所有 Pod(默认 300 秒)。

    2. default-unreachable-toleration-seconds: 表示 unreachable:NoExecute 容忍的时间。unreachable:NoExecute 默认添加到所有 Pod(默认 300 秒)。

Kubernetes 小于 v1.13

在 Kubernetes 小于 v1.13 版本之前,默认没有启用基于污点的驱逐,因此 Pod 最终迁移的时间由 node-monitor-periodnode-monitor-grace-periodnode-startup-grace-periodpod-eviction-timeout 几个参数同时决定。

rke 配置示例

services:
kube-controller:
<其他参数已省略>
extra_args:
node-monitor-period: "5s" # (默认 5s)
node-monitor-grace-period: "40s" # Node Notready (默认 40s)
node-startup-grace-period: "1m0s" # Node Unhealthy (默认 1m0s)
pod-eviction-timeout: "5m0s" # 开始驱逐 Pod (默认 5m0s)

Kubernetes 大于等于 v1.13 小于 v1.18

基于污点的驱逐

  1. 在 kubernetes 1.13 之前,基于污点的驱逐(TaintBasedEvictions)处于 Alpha 阶段,默认是禁用状态(TaintBasedEvictions=false)。所以在 kubernetes 1.13 之前的版本中只需要配置 kube-controller 的参数即可控制节点不可用时 Pod 的迁移时间。

  2. 从 kubernetes 1.13 开始,基于污点的驱逐(TaintBasedEvictions)处于 Beta 阶段,默认是被开启状态(TaintBasedEvictions=true)。当修改 kube-controller 参数后手动停止一个节点,发现 Pod 还是需要等很久才能被迁移。

  3. 在 基于污点的驱逐(TaintBasedEvictions)开启的状态下,node-startup-grace-periodpod-eviction-timeout 参数配置的时间不再生效。相应的我们可以在 Pod 的 yaml 配置文件中看到如下的参数:

    tolerations:
    - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
    - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  4. 因为 kubernetes 节点控制器根据 kubelet 的不同状态,将自动为节点添加不同的 污点。当节点具有 node.kubernetes.io/not-ready 或者 node.kubernetes.io/unreachable 污点时,将会等待 tolerationSeconds 所配置的时长。tolerations 是由 API SERVER 控制生成,从 Kubernetes v1.13 开始可以通过以下参数来配置 tolerationSeconds 时间值。

    • kube-apiserver (Kubernetes v1.13 版本及以后)

      1. default-not-ready-toleration-seconds: 表示 notReady:NoExecute 容忍的时间。notReady:NoExecute 默认添加到所有 Pod。默认 300 秒)

      2. default-unreachable-toleration-seconds: 表示 unreachable:NoExecute 容忍的时间。unreachable:NoExecute 默认添加到所有 Pod。(默认 300 秒)

      注意: notReadyunreachable 两个污点匹配到一个就会触发驱逐,notReady 的时间可以适当设置长一点。

节点污点

从 kubernetes 1.6 开始,kubernetes 的节点控制器根据 kubelet 的不同状态,将自动为节点添加不同的污点

这类污点有:

  • node.kubernetes.io/not-ready: 节点未就绪。对应着 NodeCondition ReadyFalse 的情况。
  • node.kubernetes.io/unreachable: 节点不可触达。对应着 NodeCondition ReadyUnknown 的情况。
  • node.kubernetes.io/out-of-disk:节点磁盘空间已满。
  • node.kubernetes.io/memory-pressure:节点内存吃紧。
  • node.kubernetes.io/disk-pressure:节点磁盘吃紧。
  • node.kubernetes.io/network-unavailable:节点网络不可用。
  • node.kubernetes.io/unschedulable:节点不可调度。
  • node.cloudprovider.kubernetes.io/uninitialized:如果 kubelet 是由 “外部” 云服务商启动的,该污点用来标识某个节点当前为不可用的状态。在 “云控制器”(cloud-controller-manager)初始化这个节点以后,kubelet 将此污点移除。

rke 配置示例

在 Kubernetes 大于等于 v1.13 小于 v1.18 的版本中,基于污点的驱逐(TaintBasedEvictions)处于 Beta 阶段,可选择以下两种方式来配置。

  • 禁用 基于污点的驱逐

    services:
    kube-controller:
    <其他参数已省略>
    extra_args:
    node-monitor-period: "5s" # (默认 5s)
    node-monitor-grace-period: "40s" # Node Notready (默认 40s)
    node-startup-grace-period: "1m0s" # Node Unhealthy (默认 1m0s)
    pod-eviction-timeout: "5m0s" # 开始驱逐 Pod (默认 5m0s)
    feature-gates: "TaintBasedEvictions=false" # 禁用 基于污点的驱逐
  • 启用 基于污点的驱逐

    services:
    kube-api:
    <其他参数已省略>
    extra_args:
    default-not-ready-toleration-seconds: '60' # 默认 300 秒
    default-unreachable-toleration-seconds: '30' # 默认 300 秒
    kube-controller:
    <其他参数已省略>
    extra_args:
    node-monitor-period: "5s" # (默认 5s)
    node-monitor-grace-period: "40s" # Node Notready (默认 40s)

    Kubernetes 大于等于 v1.18

在 Kubernetes 1.18 及以上版本中,TaintBasedEvictions 默认设置为 true 并且不能修改。如果强制在 rke 配置中指定 TaintBasedEvictions=false,如下配置:

services:
kube-controller:
extra_args:
feature-gates: "TaintBasedEvictions=false"

那么 kube-controller-manager 将无法正常运行,日志中会看到如下的错误提示:

Error: invalid argument "TaintBasedEvictions=false" for "--feature-gates" flag: cannot set feature gate TaintBasedEvictions to false, feature is locked to true

rke 配置示例

services:
kube-api:
<其他参数已省略>
extra_args:
default-not-ready-toleration-seconds: '60' # 默认 300 秒
default-unreachable-toleration-seconds: '30' # 默认 300 秒
kube-controller:
<其他参数已省略>
extra_args:
node-monitor-period: "5s"
node-monitor-grace-period: "30s" # Unavailable