记一次 Service Endpoints 与容器网络的碰撞

fa59016e966922395323f61b4ca8ee99.gif

本文转自 Edwardesire,原文:https://edwardesire.com/posts/crash-into-endpoints-between-cni-in-k8s/,版权归原作者所有。欢迎投稿,投稿请添加微信好友:cloud-native-yang

问题描述

服务的部署形式是三副本,每个 pod 包含 2 个容器。一个容器 A 通过 k8s lease 资源选主。一个容器 B 通过 service 对外提供服务,通过 readinessProbe 暴露容器的就绪状态。

但是通过 cluster IP 访问服务超时,直接访问后端 endpoints 可以通。

排查原因

首先判断问题的范围。这个情况只发生在新搭建的集群(k8s v1.17.4)上,新集群的唯一变化是上线新的容器网络插件。

99e714f2f7acc904294d97218373d346.png

通过 cluster ip 访问不了容器服务

36bcd43ca3a523a57b6722be0b8bc61a.png

通过 endpoint ip 可以服务容器服务

f382465ec744b69f8b20fed087eb9340.pngebea0a5d6326a0259d340b375e5028fa.png

通过 cni 插件的日志可以判断功能正常:能够收到 service 的 endpoints 事件

18ebb8e0fee6886acea56c8d53fc50ed.png

再比较不同 endpoints 的差异,无法访问的 enpoints 有选主的标签。最终确定原因是 cni 插件为了降低选主的 endpoints 频繁变更带来的损耗,过滤掉了这些 endpoints。

底层逻辑:K8s 选主实现

client-go 中的 leaderelection 支持 5 种类型的资源锁:

const (
    LeaderElectionRecordAnnotationKey = "control-plane.alpha.kubernetes.io/leader"
    EndpointsResourceLock             = "endpoints"
    ConfigMapsResourceLock            = "configmaps"
    LeasesResourceLock                = "leases"
    EndpointsLeasesResourceLock       = "endpointsleases"
    ConfigMapsLeasesResourceLock      = "configmapsleases"
)

这 5 种资源锁也是随着时间发展不断完善的。早期版本的 client-go 只支持使用 Endpoints 和 ConfigMaps 作为资源锁。由于 Endpoints 和 ConfigMaps 本身需要被集群内多个组件监听,使用这两种类型资源作为选主锁会显着增加监听他们的组件的事件数量。 如 Kube-Proxy。这个问题在社区也被多次讨论。

  • master leader election shouldn’t consume O(nodes) watch bandwidth[1]

  • Leader election causes a lot of endpoint updates[2]

为了解决这个问题,社区新增了 Leases 类型的资源锁。

  • Add Lease implementation to leaderelection package[3]

很明显,用一个专门的类型做资源锁比复用 Endpoints 和 ConfigMaps 是一个更理想的方案。在社区的讨论中,也是推荐使用 Lease Object 替代 Endpoints 和 ConfigMaps 做选主。

It was a mitigation, not the fix. The real fix is to switch leader  election to be based on Lease object instead of Endpoints or ConfiMap.  So basically #80289[4]

而对于之前已经存在使用 Endpoints/ConfigMaps 作为选主资源锁的组件,如 scheduler,kcm 等,社区也提出了一个保证稳定性的迁移方案:

  • Migrate all uses of leader-election to use Lease API[5]

Currently, Kubernetes components (scheduler, kcm, …) are using leader election  that is based on either Endpoints or ConfigMap objects. Given that both  of these are watched by different components, this is generating a lot  of unnecessary load.

We should migrate all leader-election to use Lease API (that was designed exactly for this case).

The tricky part is that in order to do that safely, I think the only reasonable way of doing that would be to:

  • in the first phase switch components to:

  1. acquire lock on the current object (endpoints or configmap)

  2. acquire lock on the new lease object

  3. only the proceed with its regular functionality [ loosing any of those two, should result in panicing and restarting the component]

  • in the second phase (release after) remove point 1

@kubernetes/sig-scalability-bugs

也就是说,在第一阶段的过渡期,需要同时获取 Endpoints/Configmap 和 Lease 两种类型的资源锁(MultiLock),任一资源锁的丢失都会导致组件的重启。当更新锁时,先更新 Endpoints/Configmap,再更新 Lease。在判断丢失时,如果两种资源都有 holder 但是不一致,则返回异常,重新选主。

在第二阶段,可以移除 Endpoints/Configmap 的资源锁,完成向 Lease 资源锁的迁移。为了支持该迁移方案,社区在 1.17 版本新增了 EndpointsLeasesResourceLockConfigMapsLeasesResourceLock,完成过渡期的锁获取。没有 svc 的 endpoints 通过 leader 创建的。

  • migrate leader election to lease API[6]

同时,在 1.17 版本中,将 controller-manager 和 scheduler 的资源锁从 Endpoints 切换成 EndpointsLeases:

  • Migrate components to EndpointsLeases leader election lock[7]

在 1.20 版本中,将 controller-manager 和 scheduler 的资源锁从 EndpointsLeases 切换成 Leases:

  • Migrate scheduler, controller-manager and cloud-controller-manager to use LeaseLock[8]

而在 1.24 版本,社区也彻底移除了对 Endpoints/ConfigMaps 作为选主资源锁的支持。

  • Remove support for Endpoints and ConfigMaps lock from leader election[9]

总结

综上,社区整体的趋势是使用 Leases 类型替代原先 Endpoints/Configmaps 作为资源锁的方式。而对于在低版本下使用 Endpoints/Configmaps 作为选主实现的 K8S,很多组件也采取了不处理这些选主的 Endpoints/Configmaps 的方式,以屏蔽频繁的 Endpoints 更新带来的事件处理开销,如:

  • k8s: stop watching for kubernetes management endpoints[10] (cilium)

因此,对于需要选主的组件,可以采取如下方式来规避:

使用 Leases Object 作为选主资源锁,这也符合社区的演进趋势; 对着这个组件(原生调度器),配置 resourceLock 类型就行。

引用链接

[1]

master leader election shouldn’t consume O(nodes) watch bandwidth: https://github.com/kubernetes/kubernetes/issues/34627

[2]

Leader election causes a lot of endpoint updates: https://github.com/kubernetes/kubernetes/issues/23812

[3]

Add Lease implementation to leaderelection package: https://github.com/kubernetes/kubernetes/pull/70778

[4]

#80289: https://github.com/kubernetes/kubernetes/issues/80289

[5]

Migrate all uses of leader-election to use Lease API: https://github.com/kubernetes/kubernetes/issues/80289

[6]

migrate leader election to lease API: https://github.com/kubernetes/kubernetes/pull/81030

[7]

Migrate components to EndpointsLeases leader election lock: https://github.com/kubernetes/kubernetes/pull/84084

[8]

Migrate scheduler, controller-manager and cloud-controller-manager to use LeaseLock: https://github.com/kubernetes/kubernetes/pull/94603

[9]

Remove support for Endpoints and ConfigMaps lock from leader election: https://github.com/kubernetes/kubernetes/pull/106852

[10]

k8s: stop watching for kubernetes management endpoints: https://github.com/cilium/cilium/pull/5448

a4c562867f31195619b2cce3eef0f5f4.gif

78d7f2a52314b0c497838f5b800d3d2d.png

你可能还喜欢

点击下方图片即可阅读

1eef9e0966e67941911efb87320ed7ca.gif

云原生是一种信仰 🤘

关注公众号

后台回复◉k8s◉获取史上最方便快捷的 Kubernetes 高可用部署工具,只需一条命令,连 ssh 都不需要!

50fa385f18f3403c4bd2e3a96bb11499.gif

71d9dfeb0c5e258c4d3dc6cf7f1a17e2.gif

点击 "阅读原文" 获取更好的阅读体验!

发现朋友圈变“安静”了吗?

804ae488ce1283e62945e0de47a2e8a2.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值