加入收藏 | 设为首页 | 会员中心 | 我要投稿 常州站长网 (https://www.0519zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 移动互联 > 评测 > 正文

容器云平台API Server卡顿问题排查

发布时间:2019-07-02 12:44:32 所属栏目:评测 来源:aoxiang
导读:副标题#e# 58云计算平台是58集团架构线基于Kubernetes + Docker技术为集团内部服务开发的一套业务实例管理平台,它具有简单,轻量的特点及高效利用物理资源,更快的部署和统一规范的标准化运行环境,通过云平台,使得服务标准化,上线流程规范化,资源利用

总的来说,TGW做负载均衡时候,由于心跳检测模块和其中两个Resource Server间连接不通,导致误将所有请求都转发到其中一个API Server,而一个特定的API Server使用v2版本etcd客户端就只会往一个固定的etcd服务端发请求,这样整个负载均衡策略就失效了。

2.2.2 etcd存取数据缓慢

namespace未做划分:

从2.1中查看API Server 的日志可以看出,很多get请求Pod对象信息,比如:“Get /api/v1/namespaces/default/pods?...” 这些都是从default namespace下获取Pod信息,这就说明线上并没有对Pod的namespace做划分。

Kubernetes是通过namespace对容器资源进行隔离,默认情况下,如果未指定namespace的话,创建的容器都被划分到default namespace下,因为这个原因也给后面往etcd中存储容器元数据信息也留下了坑。所有的Kuberentes的元数据都存储在etcd的/registry目录下,整体如下图所示:

容器云平台API Server卡顿问题排查

Kubernetes中Pod的信息存储在/registry/pods/#{命名空间}/#{具体实例名}的目录结构中,正因为如果不指定namespace的话,就会存储到default的namespace中,也就是/registry/pods/default目录下保存了线上全部Pod对象信息。

也就是说大量get请求Pod对象信息,由于未做namespace划分,每次都会去访问default子目录,每次请求相当于都要做全局搜索,随着集群的增多,Pod不断的存入到该子目录中,搜索性能也会变得越来越差。

查询结果未加入缓存:

从2.1中查看API Server 的日志看到很多Get/List操作,那么可以仔细看看相关方法的执行流程,下面是List方法执行过程中调用的中间函数:

  1.  
  2. unc (c *Cacher) GetToList(ctx context.Context, key string, resourceVersion string, pred SelectionPredicate, listObj runtime.Object) error { 
  3. if resourceVersion == "" { 
  4. return c.storage.GetToList(ctx, key, resourceVersion, pred, listObj)//直接查询etcd 
  5. listRV, err := ParseListResourceVersion(resourceVersion) 
  6. ... 
  7. obj, exists, readResourceVersion, err := c.watchCache.WaitUntilFreshAndGet(listRV, key, trace)//从缓存中获取 
  8. ... 
  9. return nil 
  10. }  

可以看到,GetToList方法中传入的有个resourceVersion 参数,如果设置了就会从缓存中获取,如果不设置就会去etcd中查询。这个也是一个关键点,有关resourceVersion 的相关使用如下:

  • 不设置:通过API Server从etcd读取。
  • 设置成0:从API Server的cache读取,减轻API Server和etcd压力。例如Kubelet经常通过此方法Get Node对象,Kubernetes Infomer第一次启动时List也通过此方法获得对象。
  • 大于0:读取对象指定版本。

线上管理平台通过http接口去查询Pod信息时候是没有设置resourceVersion,所以每次通过Get/List方法获取资源时候都会查询etcd,如此一来经常大量高频率的查询etcd会导致其压力较大,开启缓存策略不仅可以减轻访问etcd压力而且还可以加快查询速度。

总结以上两点:所有的请求都发往一个固定的API Server,导致该API Server节点负载较高,同时该API Server又会将查询请求固定的发给某个etcd节点,然而请求结果并没有在API Server端做缓存,每次都会直接查询etcd,在从etcd中获取Pod信息又是从default这个大的子目录中全局搜索,每次请求都比较费时,这样导致某一个固定的etcd一直处理大量的费时的请求,最终将该etcd资源耗尽,负载过高,因而查询结果不能及时返回给API Server,导致创建Pod时候拿不到相关的信息,Pod创建工作无法进行,所以最终表象是集群部署长时间卡顿。

3、解决方案

切换负载均衡方案:临时切换为DNS轮询方式,保证每个API Server节点的流量均衡。同时跟进TGW对于某些网段的RS和TGW服务不能探测心跳及后续改进。

将Kubernetes中Pod按多个namespace划分,目前线上所有的Pod都划分到默认的default的namespace下,每次读取Pod信息都是从etcd检索整个namespace,比较损耗etcd性能,目前已经将Pod的namespace进行细分,加快了读取Pod信息速度同时减少了etcd性能损耗。

etcd v3版本客户端会对Endpoints定期打乱,后续我们会升级到v3版本,这样同一个API Server的请求就不会一直落到某一个etcd上,这样即使负载均衡策略失效也能做到对etcd请求的分摊。

查询Kubernetes资源信息时带入resourceVersion开启缓存机制,减轻对etcd的访问压力。

4、总结

从API Server卡顿问题排查过程来看,潜在的问题是长期存在的,只是积累到一定量后,问题的影响才会凸显。这就要求我们平时对Kubernetes相关组件的性能指标,日志等要保持时刻敏感,要对Kubernetes各种默认策略及参数非常熟悉,同时对于重要功能模块做到源码层面了解,这样才能规避潜在风险和出问题后能快速定位,保证生产环境稳定健康的运行。

【编辑推荐】

  1. 甲骨文推出新的云基础设施代理 令Kubernetes开发人员的生活更轻松
  2. 探讨Kubernetes的不同部署策略
  3. Kubernetes 网络、监控技术全面解读
  4. Kubernetes使用时需要注意的坑点
  5. 未来的Kubernetes将效仿Facebook的做法
【责任编辑:未丽燕 TEL:(010)68476606】
点赞 0

(编辑:常州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读