Kubelet 状态更新机制

当 Kubernetes 中 Node 节点出现状态异常的情况下,节点上的 Pod 会被重新调度到其他节点上去,但是有的时候我们会发现节点 Down 掉以后,Pod 并不会立即触发重新调度,这实际上就是和 Kubelet 的状态更新机制密切相关的,Kubernetes 提供了一些参数配置来触发重新调度到node时间,下面我们来分析下 Kubelet 状态更新的基本流程。

默认情况下,正常的行为如下:

  • kubelet定期向apiserver发送其状态,发送周期由--node-status-update-frequency参数指定,默认值是10s
  • Kubernetes Controller Manager定期的检查kubelet状态,该参数由–-node-monitor-period参数指定,默认值5s
  • Kubernetes Controller Managerkubelet状态更新有一个容忍值,如果kubelet在这个容忍值内更新状态,那么Kubernetes Controller Manager认为kubelet状态有效.容忍值参数由--node-monitor-grace-period指定,默认值为40s
    Kubernetes Controller Managerkubelet异步工作,这意味着延迟可能包含网络延迟,API Server延迟,etcd延迟,节点负载等引起的延迟,所以如果设置--node-status-update-frequency参数为5秒时,那么当etcd无法将数据提交到仲裁节点时,它可能会在etcd中等待6-7秒甚至更长才能被呈现

失败

  • kubelet将尝试发送nodeStatusUpdateRetry ,当前nodeStatusUpdateRetry在kubelet.go.中设置为5
  • kubelet将使用 tryUpdateNodeStatus方法发送状态.kubelet使用golang的http.Client()方法,但是没指定超时时长,因此当在apiserver过载时TCP连接会造成一些问题.
  • 因此,这里尝试使用nodeStatusUpdateRetry 乘以 --node-status-update-frequency的值设置node状态.
  • 在同时Kubernetes Controller Manager每隔--node-monitor-period设置的时间检查nodeStatusUpdateRetry设置的次数,经过--node-monitor-grace-period设定的时间将认为node不健康,通过在 kube-apiserver组件中设置--default-not-ready-toleration-seconds & --default-unreachable-toleration-seconds 这两个默认的容忍参数。Kubernetes 会自动为每个 pod 添加一个默认容忍配置,默认容忍限制为60s。在添加这两个参数后需要重新部署所有 Pod 以确保将容忍添加到所有 Pod 中。除了使用kube-apiserver的参数使其对所有 pod 进行全局更改之外你还可以指定为 pod 设置忍驱逐时间 详情请看点击
  • 同时Kube-Proxy watch API server,一旦pod被删除,那么集群中所有kube-proxy将更新其节点上的iptables规则,移除相应的endpoint,这使得请求无法被发送到故障节点的pod

针对不同案例的建议

社区默认的配置(参数所属组件)

参数 组件
--node-status-update-frequency 10s kubelet
--node-monitor-period 5s controller manager
--node-monitor-grace-period 40s controller manager

快速更新和快速响应

参数 组件
--node-status-update-frequency 4s kubelet
--node-monitor-period 2s controller manager
--node-monitor-grace-period 20s controller manager

如果--node-status-update-frequency设置为4s(默认为10s)。 --node-monitor-period设置为2s(默认为5s)。--node-monitor-grace-period设置20s(默认为40s)。--default-not-ready-toleration-seconds & --default-unreachable-toleration-seconds 设置为30(默认为 300 秒)。请注意,这两个值应该是表示秒数的整数。

在这种情况下,Pod 将在 50s 后被驱逐,因为节点将在 20s 后被视为Down掉了,--default-not-ready-toleration-seconds 或者 --default-unreachable-toleration-seconds 在 30s 之后开始删除Pod。但是,这种情况会给 etcd 产生很大的开销,因为每个节点都会每 2s 更新一次状态。

如果环境有1000个节点,那么每分钟将有15000次节点更新操作,这可能需要大型 etcd 容器甚至是 etcd 的专用节点。

如果我们计算尝试次数,则除法将给出5,但实际上每次尝试的 nodeStatusUpdateRetry 尝试将从3到5。 由于所有组件的延迟,尝试总次数将在15到25之间变化。

中等更新和平均响应

参数 组件
--node-status-update-frequency 20s kubelet
--node-monitor-period 5s controller manager
--node-monitor-grace-period 2m controller manager

我们设置--node-status-update-frequency设置为20s。--node-monitor-grace-period设置为2m,并将 --default-not-ready-toleration-seconds--default-unreachable-toleration-seconds设置为60s。这种场景下会 20s 更新一次 node 状态,Kubernetes Controller Managerkubelet检测,在2分钟内进行 6 * 5 = 30 次尝试如果没有更新节点状态。1m后它将驱逐所有 pod。那么将在一分钟后驱逐所有pod总共耗时3分钟。

此处情况适用于中等环境,因为1000个节点每分钟需要对etcd进行3000次更新。

低更新和慢响应

参数 组件
--node-status-update-frequency 1m kubelet
--node-monitor-period 5s controller manager
--node-monitor-grace-period 5m controller manager

如果--node-status-update-frequency设置为1m。 --node-monitor-grace-period设置为5m,并将 --default-not-ready-toleration-seconds--default-unreachable-toleration-seconds设置为60s。在这种情况下kubelet将在每分钟上报状态,5分钟内kubelet没有更新节点状态Kubernetes Controller Manager将节点设置为不健康,在一分钟后开始驱逐所有pod总共耗时6分钟。

计算公式

--node-monitor-grace-period + --default-not-ready-toleration-seconds--default-unreachable-toleration-seconds = 驱逐时间

可以有不同的组合,例如快速更新和慢反应以满足特定情况。
原文链接: https://github.com/kubernetes-sigs/kubespray/blob/master/docs/kubernetes-reliability.md


Kubelet 状态更新机制
https://system51.github.io/2019/08/26/Kubelet-Status/
作者
Mr.Ye
发布于
2019年8月26日
许可协议