k8s1.21版本token过期:BoundServiceAccountTokenVolume问题
记录一下生产问题:k8s1.21版本token过期
一、问题现象:
1、容器网络问题:
- 使用了calico CNI, 当calico-node pod 运行了超过365天未重启,会导致节点上容器网络故障。
- Fabric CNI 无此问题
2、容器运行问题:
- 如容器需要连接apiserver 获取k8s 集群内信息,当该Pod运行了超过365天未重启,会导致该容器连接apiserver 报错
3、监控数据收集问题:
- node-exporter / kube-state-metrics / prometheus-operator /prometheus-k8s-0|1 等pod ,它需要连接apiserver 或者 使用了config-reloader 或者 使用了rbac-proxy 等,都会出现指标收集相关问题。
二、原因分析:
基本确认是k8s版本迭代引起的,为了提供更安全的token机制,从v1.21版本开始,BoundServiceAccountTokenVolume 特性进入beta版本,并默认启用。
- BoundServiceAccountTokenVolume 功能已升级为测试版,并默认启用。
- 这会将提供给容器的令牌更改为**/var/run/secrets/kubernetes.io/serviceaccount/token**有时间限制、自动刷新,并在删除包含的 pod 时失效。
- 客户端应定期从磁盘重新加载令牌(建议每分钟一次),以确保他们继续使用有效的令牌。k8s.io/client-go版本 v11.0.0+ 和 v0.15.0+ 自动重新加载令牌。
- 默认情况下,注入的令牌具有延长的生命周期,因此即使在提供新的刷新令牌后它们仍然有效。该指标serviceaccount_stale_tokens_total可用于监控依赖于延长生命周期的工作负载,并且即使在向容器提供刷新的令牌后仍继续使用令牌。如果该指标表明现有工作负载不依赖于延长的生命周期,则可以kube-apiserver通过从 开始将注入的令牌生命周期缩短至 1 小时**--service-account-extend-token-expiration=false**。 ( #95667 , @zshihang ) [SIG API 机制、身份验证、集群生命周期和测试]
如何验证
排查集群中使用的插件版本。
- 若用户集群中有使用2.23.34及以下版本Prometheus 插件,则需升级至2.23.34以上版本。
- 若用户集群中有使用1.15.0及以下版本npd插件,则需升级至最新版本。通过kubectl连接集群,并通过kubectl get --raw "/metrics" | grep stale查询,可以看到一个名serviceaccount_stale_tokens_total的指标。如果该值大于0,则表示当前集群可能存在某些负载正在使用过低的client-go版本情况,此时请您排查自己部署的应用中是否有该情况出现。如果存在,则尽快将client-go版本升级至社区指定的版本之上(至少不低于k8s 集群的两个大版本,如部署在1.26集群上的应用需要使用1.19版本以上的Kubernetes依赖库)。
kubectl get --raw "/metrics" | grep stale
#HELP serviceaccount_stale_tokens_total [ALPHA] Cumulative stale projected service account tokens used
#TYPE serviceaccount_stale_tokens_total counter serviceaccount_stale_tokens_total 7
三、解决方案
1、已部署集群:
如果不想使用该特性,可以按照下面提供的方法[4],对kube-apiserver和kube-controller-manager组件添加feature gate禁用即可,但需要将已启动的容器进行重启。
--feature-gates=BoundServiceAccountTokenVolume=false
- '--authorization-mode=Node,RBAC'
- '--etcd-cafile=/etc/etcd/ssl/ca.pem'
- '--etcd-certfile=/etc/etcd/ssl/client.pem'
- '--etcd-keyfile=/etc/etcd/ssl/client-key.pem'
- '--etcd-servers=https://10.10.43.12:2379'
- **'--feature-gates=BoundServiceAccountTokenVolume=false'**
2、未部署Portal的情况下,在部署机修改
vi /opt/BOC_k8s_noarch/playbooks/service_roles/kubelet_service/templates/kube-apiserver.yaml.j2
#添加 - '--feature-gates=BoundServiceAccountTokenVolume=false'
vi /opt/BOC_k8s_noarch/playbooks/service_roles/kubelet_service/templates/kube-controller-manager.yaml.j2
#添加 - '--feature-gates=BoundServiceAccountTokenVolume=false'
k8s集群在worker 所在节点修改:
cd /opt/deploy/worker/workspace/paas_auto_deploy_visualization_v0.1/playbooks/service_roles/kubelet_service/templates vi kube-apiserver.yaml.j2 vi kube-controller-manager.yaml.j2
#添加 - '--feature-gates=BoundServiceAccountTokenVolume=false'