共计 5491 个字符,预计需要花费 14 分钟才能阅读完成。
问题
最近在测试集群发现了一个现象: 将某个 node 的 kubelet 短暂的停掉之后,其上的 Pod 马上会被驱逐,印象之中,停掉 kubelet 后,该 node 会变为NotReady
状态,随后controller-manger
会经过一段时间才开始驱逐其上的 Pod。还有个参数专门来控制这个时间:
–pod-eviction-timeout The grace period for deleting pods on failed nodes. (default 5m0s)
该参数默认值为 5min, 也就是说当 node NotReady 之后,最少也得五分钟之后其上的 Pod 才会被驱逐。但是现实情况明显不符合预期。
分析
Kubernetes 虽然迭代了十几个版本,但是每个迭代社区活跃度仍然很高,保持着每个版本大约30个关于拓展性增强和稳定性提升的新特性。选择升级很大一方面原因是引入很多社区开发的新特性来丰富集群的功能与提升集群稳定性。新特性开发也是遵循偏差策略,跨大版本升级很可能导致在部分配置未加载的情况下启用新特性,这就给集群带来稳定性风险,因此需要梳理影响 Pod 生命周期的一些特性,尤其关注控制器相关的功能。
这里注意到在 v1.13 版本引入的 TaintBasedEvictions 特性用于更细粒度的管理 Pod 的驱逐条件。
- 在 v1.13基于条件版本之前,驱逐是基于 NodeController 的统一时间驱逐,节点 NotReady 超过默认5分钟后,节点上的 Pod 才会被驱逐;
- 在 v1.16 默认开启 TaintBasedEvictions 后,节点 NotReady 的驱逐将会根据每个 Pod 自身配置的 TolerationSeconds 来差异化的处理。
旧版本集群创建的 Pod 默认没有设置 TolerationSeconds,一旦升级完毕 TaintBasedEvictions 被开启,节点变成 NotReady 后 5 秒就会驱逐节点上的 Pod。对于短暂的网络波动、kubelet 重启等情况都会影响集群中业务的稳定性。
TaintBasedEvictions 对应的控制器是按照 pod 定义中的 tolerationSeconds 决定 Pod 的驱逐时间,也就是说只要正确设置 Pod 中的 tolerationSeconds 就可以避免出现 Pod 的非预期驱逐。
在v1.16 版本社区默认开启的 DefaultTolerationSeconds 准入控制器基于 k8s-apiserver 输入参数 default-not-ready-toleration-seconds 和 default-unreachable-toleration-seconds 为 Pod 设置默认的容忍度,以容忍 notready:NoExecute 和 unreachable:NoExecute 污点。
新建 Pod 在请求发送后会经过 DefaultTolerationSeconds 准入控制器给 pod 加上默认的 tolerations。但是这个逻辑如何对集群中已经创建的 Pod 生效呢?查看该准入控制器发现除了支持 create 操作,update 操作也会更新 pod 定义触发 DefaultTolerationSeconds 插件去设置 tolerations。因此我们通过给集群中已经运行的 Pod 打 label 就可以达成目的。
这样说来,所有的 Pod 都需要设置一个 toleration 才对,查阅相关资料后发现,社区已经有了一个DefaultTolerationSeconds dmisson controller
自动地帮助我们设置 toleration,每次创建更新 Pod, 在请求发送到 apiserve r之后会自动设置 5min 的默认 toleration。
文档上显示 DefaultTolerationSeconds admission controller
默认开启,但是为什么我的环境上面没有生效,仔细看了一下文档,是因为自己使用了一个deprecated的参数:--admission-control
。
使用这个参数的话必须显式指定所有要开启的 admisson controller plugin 列表。该参数在v1.10被废弃,由两个新的参数--enable-admission-plugins
和--disable-admission-plugins
替换,这两个参数如果不指定的话会有默认值,其中DefaultTolerationSeconds
就属于--enable-admission-plugins
参数的默认值之一,也就是会默认开启该plugin。
解决方案
1 关闭 kcm 的 Taint BasedEvictions 特性
2 开启 enable-admission-plugins
升级前:
- hyperkube
- kube-apiserver
- --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook
- --advertise-address=169.254.128.19
- --allow-privileged=true
- --audit-log-maxage=7
- --audit-log-maxbackup=10
- --audit-log-maxsize=100
- --audit-log-path=/var/log/kubernetes/kubernetes.audit
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --authorization-mode=RBAC,Node
- --basic-auth-file=/etc/kubernetes/basic_auth.csv
- --bind-address=0.0.0.0
- --client-ca-file=/etc/kubernetes/files/apiserver/cluster.crt
- --cloud-config=/etc/kubernetes/qcloud.conf
- --cloud-provider=qcloud
- --enable-aggregator-routing=true
- --enable-bootstrap-token-auth=true
- --etcd-cafile=/etc/kubernetes/etcd/secrets/etcd-ca.crt
- --etcd-certfile=/etc/kubernetes/etcd/secrets/etcd-client.crt
- --etcd-keyfile=/etc/kubernetes/etcd/secrets/etcd-client.key
- --etcd-prefix=/cls-fdjyn83c
- --etcd-servers-overrides=/events#http://etcd-27.kube-system.svc.cluster.local:2379
- --etcd-servers=https://etcd-26.kube-system.svc.cluster.local:2379
- --external-hostname=cls-fdjyn83c.ccs.tencent-cloud.com
- --kubelet-client-certificate=/etc/kubernetes/files/apiserver/apiserver.crt
- --kubelet-client-key=/etc/kubernetes/files/apiserver/apiserver.key
- --kubelet-preferred-address-types=InternalIP,ExternalIP
- --max-mutating-requests-inflight=1000
- --max-requests-inflight=3000
- --proxy-client-cert-file=/etc/kubernetes/files/apiserver/apiserver.crt
- --proxy-client-key-file=/etc/kubernetes/files/apiserver/apiserver.key
- --requestheader-client-ca-file=/etc/kubernetes/files/apiserver/cluster.crt
- --requestheader-extra-headers-prefix=X-Remote-Extra-
- --requestheader-group-headers=X-Remote-Group
- --requestheader-username-headers=X-Remote-User
- --secure-port=60002
- --service-account-key-file=/etc/kubernetes/files/apiserver/service-account.key
- --service-cluster-ip-range=10.3.255.0/24
- --tls-cert-file=/etc/kubernetes/files/apiserver/apiserver.crt
- --tls-private-key-file=/etc/kubernetes/files/apiserver/apiserver.key
- --token-auth-file=/etc/kubernetes/known_tokens.csv
---
- command:
- hyperkube
- kube-controller-manager
- --allocate-node-cidrs=false
- --allow-untagged-cloud=true
- --authentication-kubeconfig=/etc/kubernetes/files/controller-manager/kubeconfig.controller-manager
- --authorization-kubeconfig=/etc/kubernetes/files/controller-manager/kubeconfig.controller-manager
- --cloud-config=/etc/kubernetes/qcloud.conf
- --cloud-provider=qcloud
- --cluster-cidr=10.0.0.0/14
- --cluster-name=cls-fdjyn83c
- --cluster-signing-cert-file=/etc/kubernetes/files/controller-manager/cluster.crt
- --cluster-signing-key-file=/etc/kubernetes/files/controller-manager/cluster.key
- --configure-cloud-routes=false
- --horizontal-pod-autoscaler-use-rest-clients=true
- --kube-api-burst=200
- --kube-api-qps=150
- --kubeconfig=/etc/kubernetes/files/controller-manager/kubeconfig.controller-manager
- --node-cidr-mask-size=24
- --root-ca-file=/etc/kubernetes/files/controller-manager/cluster.crt
- --service-account-private-key-file=/etc/kubernetes/files/controller-manager/service-account.key
- --service-cluster-ip-range=10.3.255.0/24
- --terminated-pod-gc-threshold=50
- --use-service-account-credentials=true
升级后:
- command:
- hyperkube
- kube-apiserver
- --cloud-provider=qcloud
## 这里配置
- --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook
- --enable-aggregator-routing=true
- --enable-bootstrap-token-auth=true
- --etcd-cafile=/etc/kubernetes/etcd/secrets/etcd-ca.crt
...