Kubernetes多集群
多集群使用场景 随着容器的普及和Kubernetes的日渐成熟,企业内部运行多个Kubernetes集群已变得颇为常见。概括起来,多个集群的使用场景主要有以下几种:
高可用 可以将业务负载分布在多个集群上,使用一个全局的VIP或者DNS域名将请求发送到对应的后端集群,当一个集群发生故障无法处理请求时,将VIP或者DNS记录切换健康的集群。
低延迟 在多个区域部署集群,将用户请求转向距离最近的集群处理,以此来最大限度减少网络带来的延迟。举个例子,假如在北京,上海,广州三地部署了三个K8s集群,对于广东的用户就将请求转发到所在广州的集群处理,这样可以减少地理距离带来的网络延迟,最大限度地实现各地一致的用户体验。
故障隔离 通常来说,多个小规模的集群比一个大规模的集群更容易隔离故障。当集群发生诸如断电、网络故障、资源不足引起的连锁反应等问题时,使用多个集群可以将故障隔离在特定的集群,不会向其它集群传播。
业务隔离 虽然 Kubernetes 里提供了 namespace 来做应用的隔离,但是这只是逻辑上的隔离,不同 namespace 之间网络互通,而且还是存在资源抢占的问题。要想实现更进一步的隔离需要额外设置诸如网络隔离策略,资源限额等。多集群可以在物理上实现彻底隔离,安全性和可靠性相比使用 namespace 隔离更高。例如企业内部不同部门部署各自独立的集群、使用多个集群来分别部署开发/测试/生成环境等。
避免单一厂商锁定 Kubernetes 已经成容器编排领域的事实标准,在不同云服务商上部署集群避免将鸡蛋都放在一个篮子里,可以随时迁移业务,在不同集群间伸缩。缺点是成本增加,考虑到不同厂商提供的K8s服务对应的存储、网络接口有差异,业务迁移也不是轻而易举。
多集群部署 上面说到了多集群的主要使用场景,多集群可以解决很多问题,但是它本身带来的一个问题就是运维复杂性。对于单个集群来说,部署、更新应用都非常简单直白,直接更新集群上的 yaml 即可。多个集群下,虽然可以挨个集群更新,但如何保证不同集群的应用负载状态一致?如何在不同集群间做服务发现?如何做集群间的负载均衡?社区给出的答案是联邦集群 (Federation)。
Federation v1
Federation 方案经历了两个版本,最早的 v1 版本已经废弃。在 v1 版本中,整体架构与 Kubernetes 自身的架构非常相似,在管理的各个集群之前引入了 Federated APIServer 用来接收创建多集群部署的请求,在控制平面的 Federation Controller Manager 负责将对应的负载创建到各个集群上。
在API层面上,联邦资源的调度通过 annotation 实现,最大程度地保持与原有 Kubernetes API的兼容,这样的好处是可以复用现有的代码,用户已有的部署文件也不需要做太大改动即可迁移过来。但这也是制约 Federation 进一步的发展,无法很好地对 API 进行演进,同时对于每一种联邦资源,需要有对应的 Controller 来实现多集群的调度,早期的 Federation 只支持有限的几种资源类型。
Federation v2
社区在 v1 的基础上发展出了 Federation v2,即 Kubefed。Kubefed 使用 Kubernetes 已经相对成熟的 CRD 定义一套自己的 API 规范,抛弃了之前使用的 annotation 方式。架构上也较之前有很大改变,放弃了之前需要独立部署的 Federated APIServer/ETCD,Kubefed 的控制平面采用了流行的 CRD + Controller 的实现方式,可以直接安装在现有的 Kubernetes 集群上,无需额外的部署。