随着Kubernetes在企业中的应用和普及越来越广泛,越来越多的企业在生产环境运维多集群。本文主要讲述了关于多集群Kubernetes的一些思考,包括为什么选择多集群、多集群的好处以及多集群的实现方案。根据VMware的2020年Kubernetes使用报告,采用Kubernetes的组织中有20%运行40多个集群。为什么企业需要多集群?单集群Kubernetes的承载能力是有限的。首先看一下官方文档中对单个集群承载能力的描述:在v1.12中,Kubernetes支持最多5000个节点的集群。更具体地说,我们支持满足以下所有条件的配置:不超过5,000个节点Pod总数不超过150,000个容器总数不超过300,000个每个节点不超过100个Pod尽管Kubernetes已经发展到v1。20现在,大约单个集群的承载能力没有变化。由此可见,提高单个集群的负载能力并不是社区的发展方向。如果我们的业务规模超过5000台,那么企业就要考虑多集群。混合云或多云架构决定了对多个集群的需求。事实上,多云或混合云架构非常普遍。例如,企业是提供全球服务的全球公司。或者像新浪微博,自建数据中心+阿里云,用来服务弹性流量。另外,公有云并没有想象中的海量资源。比如当公有云的头部客户做大促需要大量机器时,需要提前向公有云申请,然后公有云提前做好准备。为了避免被单一提供商锁定,或者出于成本考虑,企业选择了多云架构,这也决定了我们需要多集群。不要把鸡蛋放在一个篮子里,即使前两个不满足,那我们是否应该将所有工作负载部署到一个集群中?如果集群控制平面出现故障,所有服务都会受到影响。可能大家认为Kubernetes本身的控制平面是高可用的(三个api-server),不存在整个控制平面不可用的可能。事实上,情况并非如此。我们在生产环境中处理过多次类似的故障。如果一个应用程序(泛指需要调用api-server接口)正在大量调用api-server,会导致api-server接连挂掉,最终变得不可用。直到找到错误的应用程序,并删除错误的应用程序。因此,在生产环境中,首先要严格控制对api-server的访问,其次要做好测试工作,其次可以考虑将业务应用和基础设施分开部署。事实上,单集群和多集群的选择类似于“选择一台超算还是多台普通机器”的问题。后来分布式计算的发展表明大家选择多台普通机器。多集群的好处多集群在以下三个方面有更好的表现:可用性隔离可扩展性多集群应用架构实际上,多集群应用架构的副本构建有两种模式:将应用复制到多可用性区域或数据中心,每个集群运行应用程序的完整副本。我们可以依靠SmartDNS(在GCP中,有GlobalLoadBalancer的概念)将流量路由到离用户最近的集群,以达到最小的网络延迟。如果我们的一个集群发生故障,我们可以将流量路由到其他健康的集群以进行故障转移。按服务划分:根据业务相关程度,将应用部署在不同的集群中。这种模型提供了很好的隔离,但是服务划分比较复杂。事实上,社区一直在探索多集群Kubernetes的最佳实践。目前主要有两种。以Kubernetes为中心专注于为多集群用例支持和扩展核心Kubernetes原语,为多个集群提供集中管理平面。KubernetesClusterFederation项目采用了这种方法。理解集群联合的最好方法是可视化跨越多个Kubernetes集群的元集群。想象一个编排多个Kubernetes主节点的逻辑控制平面,类似于每个主节点如何控制其自己的集群中的节点。事实上,集群联邦本质上做了两件事:跨集群分发资源:通过抽象Templates、Placement、Overrides这三个概念,可以将资源(如Deployment)部署到不同的集群,实现多集群的伸缩。多集群服务发现:支持多集群Service和Ingress。截至目前,联邦项目仍处于阿尔法状态。当我们选择落地时,需要进行一定的开发工作。以网络为中心的方法侧重于在集群之间创建网络连接,以便集群内的应用程序可以相互通信。Istio的多集群支持、Linkerd的服务镜像和Consul的Mesh网关通过ServiceMesh方案实现网络连接。另一个是Cilium针对多集群网络的解决方案。Cilium本身是一个CNI网络,缺乏服务治理的功能。CiliumClusterMesh解决方案通过隧道或直接路由来解决跨多个Kubernetes集群的PodIP路由,无需任何网关或代理。当然,我们需要规划每个集群的PODCIDR。每个Kubernetes集群维护自己的etcd集群,其中包含该集群的状态。来自多个集群的状态永远不会混合到etcd中。每个集群通过一组etcd代理公开自己的etcd。在其他集群中运行的Cilium代理连接到etcd代理以监视更改并将多集群相关状态复制到自己的集群。使用etcd代理可确保etcdwatcher的可扩展性。访问受TLS证书保护。从一个集群到另一个集群的访问始终是只读的。这确保故障域保持不变,即一个集群中的故障永远不会传播到其他集群。配置是通过一个简单的Kubernetes秘密资源进行的,该资源包含远程etcd代理的寻址信息以及访问etcd代理所需的集群名称和凭据。想一想我们上面提到的实现多集群Kubernetes的两种方案,其实既不是A也不是B。比如我们在落地一个大集群的过程中,很多公司只是用Kubernetes来解决部署问题。选择Consul、zk等注册中心做服务发现,配置中心做配置文件管理,不使用kubernetes中的Service做负载均衡。结合这两个选项是此时的最佳实践。集群联邦解决了部署和发布的问题。ServiceMesh解决了多集群流量访问的问题。但是此时workload集群中的Pod、servicemesh的控制面、gateway都需要连接到外部注册中心。具体结构如下:
