前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一次ServiceAccount导致的apiserver雪崩案例分析

一次ServiceAccount导致的apiserver雪崩案例分析

原创
作者头像
shawwang
修改2021-10-25 16:10:58
修改2021-10-25 16:10:58
1.1K0
举报
文章被收录于专栏:腾讯云容器服务团队的专栏

背景

某业务使用k8s1.12版本的集群,集群内有上千个node,某天在master有一波突发请求后,突然变为不可用状态,集群内大量组件访问master超时,业务重启master组件后仍未恢复。

排查过程

首先排查了kube-apiserver的日志,发现有大量创建TokenReview的请求日志打印,且都是30s超时,怀疑是该请求将kube-apiserver限速打满,从而影响到了其他正常请求。

观察kube-apiserver监控发现,apiserver的apiserver_current_inflight_requests{requestKind="mutating"}指标确实已经达到了业务设置的max-mutating-requests-inflight,触发了限速。

刚开始怀疑因为触发mutating限速,导致了大量client重试,触发了雪崩,之前也遇到过类似的问题,调大限速值即可恢复。于是决定先调大mutating值观察,调整max-mutating-requests-inflight之后,观察一段时间发现,业务仍有超时,查看日志发现还是有很多Create TokenReview超时,看来只有查清楚TokenReview的创建来源,才能找到根本原因。

TokenReview是一个虚拟资源,只有在有Token相关的鉴权请求时才会创建,因此当务之急是查清楚是哪个组件在频繁的请求鉴权。由于当前的日志找不到更多的有效信息,想查清楚请求来源,只有寄希望于kube-apiserver排查请求的终极杀器——审计。在配置好相关审计规则后,我们就可以很方便的统计到请求来源和详细信息。

观察一段时间后,发现TokenReview的请求来源基本都来自于kubelet,而且请求比较均匀,并没有明显的聚集性,看起来都是一些正常的请求,这就排除了是由于某个节点的突发请求导致。

什么情况下kubelet会向kube-apiserver请求创建TokenReview呢?通过查看K8s源码发现,在客户端通过ServiceAccount认证方式请求kubelet时,kubelet会通过创建TokenReview的方式(webhook方式)请求apiserver进行鉴权,TokenReview创建时,会调用kube-apiserver内置的Authenticator进行认证,如果是Token认证,则依次校验basic auth, bearertoken,ServiceAccount token,bootstrap token等(顺序可参考BuildAuthenticator函数的构建流程),其中,ServiceAccount token的Authenticator会从ServiceAccountTokenGetter通过loopback client来获取secret,该操作在K8s-1.12是不走缓存的,并且lookback client限速qps 50,burst 100(SecureServingInfo.NewClientConfig, K8s-1.17之前),在雪崩的时候很容易触发限速,造成max-mutating-requests-inflight被打满,从而影响其他写操作。(注:kube-apiserver的token认证默认会增加本地cache,缓存10s。 kubelet通过webhook的方式进行token认证,同样有本地缓存(默认2分钟)。请求失败会通过backoff的方式重试。但在集群有上千节点的情况下且缓存失效的情况下,触发雪崩后很难自动恢复)。

搞清楚了问题原因,那么如何能够快速恢复呢?查看K8s代码发现,当前版本的lookback client的限速配置是hardcode在代码里的,没有配置可以修改。如果要改的话只能再出一个K8s版本,改动相对较大。

换个思路看下,如果把使用该ServiceAccount请求kubelet的源头揪出来,是不是也能解决这个问题呢?排查审计日志发现,请求的用户基本是同一个ServiceAccount,system:serviceaccount:metrics-server。到这里所有问题都可以解释的通了,metrics-server需要通过kubelet来获取部分监控数据,因此会请求每个节点的kubelet,在集群规模较大的情况下,很容易触发kube-apiserver的loopback client的限速。

解决方案

查清楚了原因和源头,问题就很容易解决了,将metrics-server的鉴权方式改为使用证书鉴权,或者static token的方式鉴权,即可临时解决该问题。

另外,K8s-1.17已经移除了loopback client的限速,K8s-1.14以后ServiceAccountTokenGetter会先从informer获取数据,失败后再通过loopback client请求apiserver,因此通过升级集群master版本,才可以从根本上解决这个问题。

附录

K8s社区相关讨论:

https://github.com/kubernetes/kubernetes/issues/71811

https://github.com/kubernetes/kubernetes/pull/71816

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 排查过程
  • 解决方案
  • 附录
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档