
背景
apiserver 启动时会签发 loopback 证书,用于访问自身的 api,社区版本该证书有效期为 1 年,tke 在新版本支持了 5 年有效期,当证书过期时,apiserver 请求自身时会失效,但不会立即触发问题,需要满足一定条件,一旦触发会影响正常的客户端请求,如负载创建,滚动更新等。
触发时该问题时,请求会显示 certificate expired 错误。
$ kubectl create ns test Error from server: Get "https://[::1]:60002/api/v1/namespaces/teg-test1/resourcequotas": x509: certificate has expired or is not yet valid: current time 2023-11-14T11:59:42+08:00 is after 2023-11-14T03:13:32Z
k8s 社区 关于证书更新设置为1年的讨论 ,主要原因是社区一个版本支持周期为 9 个月。
触发该问题需要同时满足以下3个条件
1.证书过期,此时 apiserver 对自身发起的请求会失败。
2.客户端的请求会引发 apiserver 查询其他资源,此时可能对自身发起请求,如 pod 资源创建时需要检查是否满足 resource quota。
a. 每次 pod 创建时需要检查 resource quota,此时会先从缓存中获取,如果没有的话,会重新发起list请求,apiserver 需要访问自身,此时会因为证书过期失败,导致 pod 创建请求失败。
b. 同理,针对 limit range 资源,每次 pod 创建进行 admit 时也会检查,当informer,或者缓存中没有时也会触发
直接 list apiserver 自身。
3.apiserver 对自身请求资源的长连接因为网络不稳定等原因中断,如 informer,此时 apiserver 无法从缓存获取新数据,会重新发起请求。
请求所有有其他依赖的资源时都会失败,典型的如 pod 资源依赖 resource quota,问题触发时会导致集群负载无法创建,滚动更新,扩容,暂时不影响存量 pod,但是控制面会处于不可用状态,如果业务依赖控制面则会直接影响业务。
适用集群类型:TKE 标准集群、TKE 标准集群(Master 自维护)
操作方式:升级集群的 k8s 小版本或者大版本,证书变为 5 年有效期,集群一般会在5年时间升级或重启 apiserver,风险大大降低。
证书有效期与版本
|
版本 |
判断标准 |
|
1.32 以上 |
所有小版本都是100 年 |
|
1.28以上 |
所有小版本都是5年 |
|
v1.26.1-tke.x |
从tke.2起是5年,之前是1年 |
|
v1.24.4-tke.x |
从tke.10起是5年,之前是1年 |
|
v1.22.5-tke.x |
从tke.20起是5年,之前是1年 |
|
v1.20.6-tke.x |
从tke.39起是5年,之前是1年 |
|
v1.18.4-tke.x |
从tke.49起是5年,之前是1年 |
|
v1.16.3-tke.x |
从tke.42起是5年,之前是1年 |
|
v1.14.3-tke.x |
从tke.33起是5年,之前是1年 |
实施解决方案前请注意:
建议业务低峰期进行操作,操作前观察 master 负载,高负载时请勿操作!
适用集群类型 TKE 标准集群(Master 自维护)
操作方式:检测 apiserver 版本,确认是1年过期还是 5 年过期,当 apiserver 进程启动时间接近过期时间时,需要重启 apiserver 进程。
注意:建议每个控制面节点间隔 5 分钟进行 apiserver 重启,请勿同步重启。
重启方法 (下面方法二选一)
1. 根据运行时docker/containerd重启容器
# docker场景
# 1. 执行重启
docker ps | grep k8s_kube-apiserver | awk '{print $1}' | xargs -I {} docker restart {}
# 2. 检查容器是否恢复,运行时间是刚启动
docker ps | grep apiserver
# containerd
# 1. 执行重启
crictl ps | grep kube-apiserver | awk '{print $1}' | xargs -I {} crictl rm -f {}
# 2. 检查容器是否恢复,运行时间是刚启动
crictl ps | grep kube-apiserver
2.apiserver的静态pod文件/etc/kubernetes/manifests/kube-apiserver.yaml从目录中移出然后移入,完成后需要检查pod是否重启
mv /etc/kubernetes/manifests/kube-apiserver.yaml /etc/
mv /etc/kube-apiserver.yaml /etc/kubernetes/manifests/
# 检查apiserver pod创建时间 kubectl -n kube-system get pod | grep
kube-apiserver
# 如果没有重启,执行以下命令重启
kubelet systemctl restart kubelet