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-apiserverkube-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'