Z.S.K.'s Records

cilium在kubernetes中的生产实践六(cilium排错指南)之api-rate-limit

在前东家的时候其实就有意将cilium强大的链路追踪能力集成到生产环境中,各种因素导致没有很大信心落地, 经过深入调研(也就把官网docs翻了四五遍)及测试, 终于有机会在生产kubernetes集群中(目前一个集群规模不算很大,2w+核心,持续增长)使用cilium做为cni,同时替换kube-proxy, 到现在已经有一段时间了,也算是有生产经验可以跟大家聊一聊这个工具,使用体验总结一句话: 轻松愉悦.
分享一下整个落地过程,同时也总结下方方面面, 工作之余尽量更新.
此篇归属于: cilium在kubernetes中的生产实践六(cilium排错指南)

总体分为以下几块内容:
cilium在kubernetes中的生产实践一(cilium介绍)
cilium在kubernetes中的生产实践二(cilium部署)
cilium在kubernetes中的生产实践三(cilium网络模型之关键配置)
cilium在kubernetes中的生产实践四(cilium网络模型之生产实践)
cilium在kubernetes中的生产实践五(cilium网络策略)
cilium在kubernetes中的生产实践六(cilium排错指南)
cilium在kubernetes中的生产实践七(cilium中的bpf hook)

问题现象

业务高峰期创建的pod数可能上万+, 某天就出现了在大量pod创建失败的情况, 这些pod处于ContainerCreating状态, 第一感觉以为是节点上运行的pod数超过指定的max-pods(默认pod数最大110)导致的失败,简单排查后发现不是, 找到这类pod所在的节点, 发现kubelet有类似如下日志:

1
RunPodSandbox from runtime service failed: rpc error: code = Unknown desc = failed to set up sandbox container "a89f1f10c0655325f909ba937ce1b5d8db70fbc0a9fa67daed62dca3de5a8f73" network for pod "es-white-list-cronjob-1616127480-nbczk": networkPlugin cni failed to set up pod "es-white-list-cronjob-1616127480-nbczk_caibin1" network: Unable to create endpoint: response status code does not match any response statuses defined for this endpoint in the swagger spec (status 429): {}

问题排查

从上述日志看有几个关键字: networkPlugin cni, ‘create endpoint (status 429)’.
很显然, kubelet反应的这个报错是cni返回的, 而集群中的cni为cilium
所以查看节点上的cilium agent ds, 发现有如下报错:

1
2
3
4
5
6
level=warning msg="Not processing API request. Wait duration for maximum parallel requests exceeds maximum" error="context deadline exceeded" maxWaitDuration=15s name=endpoint-create parallelRequests=3 subsys=rate uuid=efabe2d6-886a-11eb-832b-3cecef001f42
level=info msg="API call has been processed" error="timed out while waiting to be served with 3 parallel requests: context deadline exceeded" name=endpoint-create processingDuration=0s subsys=rate totalDuration=15.000634348s uuid=efabe2d6-886a-11eb-832b-3cecef001f42 waitDurationTotal=0s
level=info msg="API call has been processed" error="request would have to wait 18.736302926s to be served (maximum wait duration: 622.727216ms)" name=endpoint-create processingDuration=0s subsys=rate totalDuration=16.396271422s uuid=ee181d17-886a-11eb-832b-3cecef001f42 waitDurationTotal=14.377272784s
level=info msg="API call has been processed" error="request would have to wait 16.717671024s to be served (maximum wait duration: 18.52909ms)" name=endpoint-create processingDuration=0s subsys=rate totalDuration=17.000479009s uuid=edbbea7f-886a-11eb-832b-3cecef001f42 waitDurationTotal=14.98147091s
level=info msg="Processing API request with rate limiter" maxWaitDuration=15s name=endpoint-create parallelRequests=3 subsys=rate uuid=ee181d17-886a-11eb-832b-3cecef001f42
level=info msg="regenerating all endpoints" reason="one or more identities created or deleted" subsys=endpoint-manager

因此可以确认是cilium agent的问题, cilium的功能是以subsys区分的, 上述日志中提及subsys=rate,
同时kubelet中还存在endpoint (status 429)的报错.
status 429的一般用于表示请求太多,这与subsys=rate刚好对应上了
所以,问题出在cilium的rate配置, 作者对cilium中的rate部分并没有特别的进行配置, 所以直接去官方文档查看:

默认的rate配置如下, 这里简单说明:

API Call Limit Burst Max Parallel Min Parallel Max Wait Duration Auto Adjust Estimated Processing Duration
PUT /endpoint/{id} 0.5/s 4 4 15s True 2s
DELETE /endpoint/{id} 4 4 True 200ms
GET /endpoint/{id}/* 4/s 4 4 2 10s True 200ms
PATCH /endpoint/{id}* 0.5/s 4 4 15s True 1s
GET /endpoint 1/s 4 2 2 True 300ms

还有一张CURD的对应关系表:

API Call Config Name
PUT /endpoint/{id} endpoint-create
DELETE /endpoint/{id} endpoint-delete
GET /endpoint/{id}/* endpoint-get
PATCH /endpoint/{id}* endponit-patch
GET /endpoint endpoint-list

上述的报错可以跟默认配置对应上,包括Max Wait Duration
然后报错的是create endpoint出现的429, create endpoint属于是PUT endpoint一类,默认配置表中只有0.5/s且并发数只有4, 相对于作者的场景还是小了一些, 所以需要进行调整

问题解决

调整cilium agent中的configamp, 添加如下的配置项

1
2
3
4
api-rate-limit: "endpoint-create=rate-limit:8/s,rate-burst:16,parallel-requests:8"
# rate-limit:8/s 表示每秒允许8个请求
# rate-burst:16 表示可以突发的请求数
# parallel-requests 并发请求数

然后再重启cilium agent ds后,问题解决

问题延伸

有一个问题: 为什么是create endpoint出现了429而不是其它的比如create pod or create ip之类的出现问题?
首先, 一个node上的cni可分配的IP段为一个C段网络,即255个ip地址,node上默认最大的pod数量为110, 当node上的pod数量要超过110时,那么新的pod在kube-scheduler中进行调度时会在pre-schedule阶段将这个node排除掉, 所以可以排除是创建pod或者是获取ip问题.
每个节点的Cilium代理本质上是事件驱动的。当新的工作负载被调度到节点上时,CNI插件被调用,该节点继而对Cilium代理进行API调用以分配IP地址并创建Cilium端点.

问题总结

cilium本身是基于事件驱动的,Cilium agent 执行的工作量在很大程度上取决于它接收外部事件的速率。为了限制Cilium代理消耗的资源, cilium限制了API调用的速率和允许的并行执行数.

参考文章:

转载请注明原作者: 周淑科(https://izsk.me)

 wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?