字节跳动 kube-apiserver 高可用方案 KubeGateway
kube-apiserver 本质上是一个无状态的服务器,为了实现其高可用,开发人员通常会部署多个 kube-apiserver 实例,同时引入外部负载均衡器(以下简称 LB)进行流量代理。
为了保证集群的安全,kube-apiserver 对请求进行认证和授权的准入控制,其中认证是为了 识别出用户的身份 。
Kubernetes 支持多种认证策略,比如 Bootstrap Token、Service Account Token、OpenID Connect Token、TLS 双向认证等。 目前 kube-apiserver 的客户端使用得较多的策略是 TLS 双向认证。 TLS 双向认证需要 LB 将请求中的 Client X509 Cert 正确传递给 kube-apiserver,但是传统的七层 LB 无法做到这一点,在转发过程中会丢失 Client X509 Cert,导致 kube-apiserver 无法认证用户。
因此目前 LB 的选型一般为 LVS、云厂商的 SLB 或 nginx、HAProxy 的四层负载均衡方案。四层负载均衡工作在 OSI 的第四层即传输层,使用 NAT 技术进行代理转发但是使用四层 LB 会引起另外的问题,具体如下:
七层负载均衡工作在 OSI 的第七层即应用层,一般是基于请求 URL 地址的方式进行代理转发。
-
请求负载不均衡 :由于 kube-apiserver 和 client 是使用 HTTP2 协议连接,HTTP2 的多个请求都会复用底层的同一个 TCP 连接并且长时间不断开。在 kube-apiserver 滚动升级或者某个实例重启时,很容易引起迟些启动的 kube-apiserver 在长时间内只有很少的请求数。极端情况下,负载较高的实例会出现 OOM,甚至引起雪崩。
-
缺乏请求治理的灵活性 : 4 层负载均衡在传输层工作,它只负责消息的传递,但是无法处理应用层的 HTTP 协议的信息,因此相较于 7 层负载缺乏对请求治理的“灵活性”和 “智能性”。比如无法根据请求的内容(比如 verb、url 等字段)制定灵活的负载均衡和路由策略,也无法在网关层对请求级别进行限流降级等处理。
KubeGateway 作为七层网关接入和转发 kube-apiserver 的请求,它具有以下特点 :
- 对于客户端完全透明,客户端无需任何改造即可以接入 KubeGateway;
-
支持同时代理多个 K8s 集群的请求,不同 K8s 集群通过不同的域名或者虚拟地 址(vip)进行区分;
- 负载均衡从 TCP 连接级别变为 HTTP 请求级别,进而实现快速、有效的进行负载均衡,彻底解决 kube-apiserver 负载不均衡的问题;
- 高扩展性的负载均衡策略,目前支持 Round Robin、Random 策略,负载均衡策略插件化,易于扩展;
-
支持灵活的路由策略,KubeGateway 根据请求信息,包括但不限于 resource/ verb/ user/ namespace/ apigroup 等进行路由。 为 kube-apiserver 分组提供基础能力,以低运维成本实现 kube-apiserver 组之间的隔离性,提高集群稳定性;
- 配置管理云原生化,以 K8s 的标准 API 形式管理网关配置,支持配置热更新;
- 支持限流、降级、动态服务发现、优雅退出、upstream 异常检测等网关的通用能力。
-
资源请求 ,如对 Pod 的 CRUD(增删改查)
-
非资源请求 ,如访问 /healthz 查看 kube-apiserver 的健康情况,访问 /metrics 查看暴露的指标等
从 请求中解析出多维度的路由字段后,开发人员可以很方便地组合出非常强大的路由规则来区分不同的 API 请求,比如
- 通过 Verb 和 Resource 的结合,我们可以直接匹配到所有的 list pod 的请求
- 通过 User/UserGroup/ServiceAccount 等,我们可以匹配出 kube-controller-manager/kube-scheduler 等核心控制组件的请求
-
基于 x509 客户端证书的认证方式 :KubeGateway 通过规则 upstream kube-apiserver 中的 CA 证书,解析出客户端证书中用户和用户组信息;
-
基于 Bearer Token 的认证方式 :KubeGateway 通过给 upstream kube-apiserver 发送 TokenReview 请求,要求 upstream kube-apiserver 对 Bearer Token 进行认证,从而得到对应的用户信息。
识别出用户后,KubeGateway 通过 kube-apiserver 提供的 Impersonate(用户扮演)机制进行转发,详细内容会在后文 进行介绍。
此外,KubeGateway 只会对请求进行认证,并不会对请求进行授权判断,授权操作由 upstream kube-apiserver 进行。 请求治理 KubeGateway 作为七层网关,有着丰富的流量治理能力,具体包括: 负载均衡 UpstreamCluster 确定后,Upstream Servers 也随之确定。KubeGateway 按照负载均衡策略从 Upstream Servers 中选择出一个进行请求转发。良好的负载均衡策略可以优化资源效率,最大化吞吐量,减少延迟和容错。 目前 KubeGateway 支持 Round Robin 和 Random 负载均衡策略,这两种策略简单有效,能够满足大部分场景的需求。 此外,KubeGateway 支持灵活的负载均衡策略扩展,可以快速实现 Least Request 等算法,以满足更多场景的需求。 健康监测 KubeGateway 会定期主动地访问 kube-apiserver 的 /healthz 接口进行健康监测。代理流量只会转发给健康的 kube-apiserver;而不健康的 kube-apiserver 会被临时屏蔽,当它被恢复健康后才会重新有新的流量限流
KubeGateway 默认提供限流的能力,可以有效地防止 upstream kube-apiserver 在某些情况下过载。它的限流方案相比于 Kubernetes 本身的 APF(API Priority and Fairness)更容易理解和配置。请求经过请求解析和路由匹配之后,KubeGateway 会确定这个请求的限流规则。 比如我们想要限制普通用户 list pod 的 QPS,但是又要对管控组件(如 controller-manager,scheduler)进行豁免,可以在路由匹配中区分出两种类型的用户然后为他们单独配置 FlowControl 限流规则。KubeGateway 提供了两种限流策略:
-
token bucket :令牌桶是常用的限流方式,它能有效地限制请求的 QPS 并在一定程度上允许突发的请求;
-
max requests inflight :最大请求数是比令牌桶更严格的限制方式,它限制在某个时刻能够执行的最大请求数量,通常用来限制一些更加耗时的请求,比如在大集群 list 全量 pods,这种请求会可能会持续好几分钟,而且会占用 kube-apiserver 大量的资源,只通过令牌桶的限流会放入过多的请求而造成 kube-apiserver OOM 等问题。
降级
KubeGateway 支持降级以应对集群管控面异常的情况。 在 kube-apiserver 或者 ETCD 发生故障的时候,可能引起集群的雪崩。在雪崩情况下,部分请求会返回成功,部分请求返回失败,加上客户端不断重试,容易导致集群出现非预期行为,比如 Node NotReady、 Pod 大量驱逐和删除等。 在这种情况下,我们可以通过 KubeGateway 进行降级操作拒掉所有流量。在降级状态下集群相当于被冻结了,所有写入都无法成功,可以保证存量的 Pod 进程保持存活状态,避免对业务造成影响。在集群恢复正常后,首先放开限制允许 Node 上报心跳,然后再恢复集群的其他流量。 请求治反向代理 KubeGateway 在反向代理部分,有以下关键的技术点:Impersonate(用户扮演)
在通过流量治理后,KubeGateway 会根据选择出的 kube-apiserver 进行转发。在转发的时候 KubeGateway 通过 impersonate 的机制将用户信息通过 Request Header 传递给 upstream kube-apiserver。在 Request Header 中添加以下信息:Impersonate-User: Client 用户名Impersonate-Group: Client 用户组
-
kube-apis erver 认证 KubeGateway 用户,识别出用户扮演的行为;
- kube-apiserver 确保 KubeGateway 具有 Impersonate 权限;
- kube-apiserver 根据 HTTP Header 识别出 KubeGateway 扮演的用户名和用户组,然后将请求执行者替换成被扮演的用户;
-
对 被扮演的用户进行授权验证,检查他是否有权限访问对应的资源。
HTTP2 多路复用
KubeGateway 默认使用 HTTP2 协议,基于 HTTP2 协议的多路复用能力,单条连接上默认支持 250 个 Stream,即单个连接上支持 250 个并发的请求,使得 upstream 单个 kube-apiserver 的 TCP 连接数可以降低两个数量级。Forward & Exec 类请求处理
经过压测,KubeGateway 性能优异,经过代理后, 请求延迟增加在 1ms 左右 。目前 KubeGateway 已经平滑的接管了字节所有的 Kubernetes 集群, 总 QPS 20w+ 。
在 KubeGateway 的帮助下,研发团队彻底解决了 kube-apiserver 流量不均衡的问题,而且极大增强了 kube-apiserver 请求的治理能力,包括请求分组、路由、限流、降级等,有效提高了集群的稳定性和可用性。
同时,我们在 KubeGateway 优雅升级、多集群动态证书管理、可观测性上也做了很多优化,具体技术细节以后会进行更多的介绍,敬请期待。 KubeGateway 未来演进 目前,KubeGateway 已在 GitHub 开源,未来它会在以下几个方面持续演进:-
提供更完整的 7 层网关能力,比如黑白名单,缓存等;
- 持续提高可观测性,可以在异常情况下能够快速定位到问题,辅助排障;
-
探索基于 KubeGateway 网关实现新型的联邦方案,通过 KubeGateway 可以将多个 K8s 集群透明地聚合成一个集群。
- AI绘画火了!一文看懂背后技术原理
- B站直播的自研P2P实践 | 助力S12英雄联盟总决赛
- 美团高性能终端实时日志系统建设实践
- RocksDB 7 终于解决了 Compaction 时性能下降问题
- 实时营销引擎在vivo营销自动化中的实践 | 引擎篇04
本文由高可用架构转载。技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿