在前东家的时候其实就有意将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 | 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 |
因此可以确认是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 | api-rate-limit: "endpoint-create=rate-limit:8/s,rate-burst:16,parallel-requests:8" |
然后再重启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://docs.cilium.io/en/v1.12/configuration/api-rate-limiting/
- https://github.com/cilium/cilium/issues/15394
- https://cloud.google.com/kubernetes-engine/distributed-cloud/bare-metal/docs/troubleshooting/networking?hl=zh-cn#dataplane_v2_cilium
- https://izsk.me/2023/04/01/cilium-on-kubernetes-introduction/
- https://izsk.me/2023/06/03/cilium-on-kubernetes-install/
- https://izsk.me/2023/09/26/cilium-on-kubernetes-network-models-config/