万字长文,玩转 K8s 多集群管理竟然如此简单?
本文主要讲述了一些对于K8s多集群管理的思考,包括为什么需要多集群、多集群的优势以及现有的一些基于Kubernetes衍生出的多集群管理架构实践。
作者:vivo互联网容器团队 – Zhang Rong
一、为什么需要多集群
随着 K8s 和云原生技术的快速发展,以及各大厂商在自己的数据中心使用 K8s 的 API 进行容器化应用编排和管理,让应用交付本身变得越来越标准化和统一化,并且实现了与底层基础设施的完全解耦,为多集群和混合云提供了一个坚实技术基础。谈到多集群多云的数据中心基础架构,会想到为什么企业需要多集群?
1.单集群容量限制:
集群上限5000个节点和15万个Pod。同时单集群的最大节点数不是一个确定值,其受到集群部署方式和业务使用集群资源的方式的影响。
2.多云混合使用:
避免被单家供应商锁定,不同集群的最新技术规划,或是出于成本等考虑,企业选择了多云架构。
3.业务流量突发:
正常情况下用户使用自己的 IDC 集群提供服务,当应对突发大流量时,迅速将应用扩容到云上集群共同提供服务,需具备公有云 IaaS接入,可以自动扩缩容计算节点,将公有云作为备用资源池。该模式一般针对无状态的服务,可以快速弹性扩展,主要针对使用 CPU、内存较为密集的服务,如搜索、查询、计算等类型的服务。
4.业务高可用:
单集群无法应对网络故障或者数据中心故障导致的服务的不可用。通常主要服务的集群为一个,另一个集群周期性备份。或者一个集群主要负责读写,其他备份集群只读,在主集群所在的云出现问题时可以快速切换到备份集群。该模式可用于数据量较大的存储服务,如部署一个高可用的mysql集群,一个集群负责读写,其他2个集群备份只读,可以自动切换主备。
5.异地多活:
数据是实时同步的,多集群都可以同时读写,这种模式通常针对极其重要的数据,如全局统一的用户账号信息等。
6.地域亲和性:
尽管国内互联网一直在提速,但是处于带宽成本的考量,同一调用链的服务网络距离越近越好。服务的主调和被调部署在同一个地域内能够有效减少带宽成本;并且分而治之的方式让应用服务本区域的业务,也能有效缓解应用服务的压力。
二、多集群探索
2.1 社区在多集群上的探索
当前基于 K8s 多集群项目如下:
1.Federation v1:
已经被社区废弃,主要原因在于 v1 的设计试图在 K8s 之上又构建一层 Federation API,直接屏蔽掉了已经取得广泛共识的 K8s API ,这与云原生社区的发展理念是相悖。
2.Federation v2:
已经被社区废弃,提供了一个可以将任何 K8s API type 转换成有多集群概念的 federated type 的方法,以及一个对应的控制器以便推送这些 federated 对象 (Object)。而它并不像 V1 一样关心复杂的推送策略(V1 的 Federation Scheduler),只负责把这些 Object 分发到用户事先定义的集群去。这也就意味着 Federation v2 的主要设计目标,其实是向多集群推送 RBAC,policy 等集群配置信息。
3.Karmada:
参考Kubernetes Federation v2 核心实践,并融入了众多新技术,包括 Kubernetes 原生 API 支持、多层级高可用部署、多集群自动故障迁移、多集群应用自动伸缩、多集群服务发现等,并且提供原生 Kubernetes 平滑演进路径。
4.Clusternet:
是一个兼具多集群管理和跨集群应用编排的开源云原生管控平台,解决了跨云、跨地域、跨可用区的集群管理问题。在项目规划阶段,就是面向未来混合云、分布式云和边缘计算等场景来设计的,支持海量集群的接入和管理、应用分发、流量治理等。
5.OCM:
OCM 是一款 Kubernetes 多集群平台开源项目,它可以帮助你大大简化跨云/多云场景下的集群管理,无论这些集群是在云上托管,还是部署在自建数据中心,再或者是在边缘数据中心中。 OCM 提供的基础模型可以帮助我们同时理解单集群内部的容量情况,也可以横跨多集群进行资源/工作负载的编排调度。 与此同时,OCM 还提供了一系列强大的扩展性或者叫做插件框架(addon-framework)来帮助我们集成 CNCF 生态中的其他项目,这些扩展性也可以帮助我们无侵入地针对你的特定使用场景手工扩展特性。 以上多集群项目主要功能为资源分发和调度,还有如多云基础设施管理 cluster-api,多集群检索 Clusterpedia,多集群 pod 互通 submariner,multicluster-ingress 解决多集群的 ingress,服务治理和流量调度 Service Mesh,如istio、cilium 等网络组件实现的 multi cluster mesh 解决跨集群的mesh网络管理,以及结合存储相关项目实现跨集群存储管理和迁移等。
2.2 vivo 在多集群上的探索
2.2.1 非联邦集群管理
2.2.2 联邦集群管理
vivo在联邦集群的探索方向主要有以下四个方面:
-
资源分发和编排
-
弹性突发
-
多集群调度
-
服务治理和流量调度
三、面向应用的多集群实践
-
应用的弹性:对于云产品的客户来说等价于业务可靠性和业务探索与创新的敏捷性,体现的是云计算所创造的客户价值,应用弹性的另一个关注点在于快速部署、交付、以及在云上的扩缩容能力。这就需要完善的应用交付链路以及应用的云原生开发框架支撑; -
易用性:能更好地发挥应用的弹性,在微服务软件架构成为主流的情形下,易用性需要考虑通过技术手段实现对应用整体做全局性的治理,实现全局最优。这凸显了 Service Mesh 的服务能力; -
可移植性:实现多集群和混合云无障碍迁移等。
3.1 面向应用的多集群持续发布
3.1.1 应用发布
上图是面向应用的多集群持续发布架构,我们主要的工作如下:
管理注册多个 Kubernetes 集群并接入Karmada,Karmada负责多个集群的资源调度编排和故障转移。 容器平台统一管理K8s资源、Karmada策略和配置。 CICD平台对应用进行单元测试、安全测试、编译镜像等操作,配置应用的存储、密钥、环境变量、网络和资源等,最终对接容器平台的API生成K8s对象,统一交付。
比如上图有个游戏的应用game-2408。它涉及到 K8s 资源有 configmap、secret、pv、pvc、service,openkruise 的 cloneset、自研的服务发现和访问资源、以及 Karmada 的 PropagationPolicy
和 OverridePolicy
等资源,都能达到12个资源配置。
可以识别策略属于那个workload 避免策略重复,需要加入workload类型 策略名超过63个字符,需要hash处理 xxx为非workload的资源名
遇到的问题总结:
一个资源无法被多个策略匹配,导致如configmap、secret等公用资源无法再次下发到其它集群。 多个集群之间串行发布,如发布完A集群才能发布B集群的控制。
3.1.2 Openkruise 资源解析
Cloneset
(无状态)和AdvancedStatefulset
(有状态)控制器进行发布。Kamrada目前只能识别 K8s 默认的资源,其它的资源都需要开发资源解析。-
InterpretReplica:
该 hook 点发生在从 ResourceTemplate 到 ResourceBinding 这个过程中,针对有 replica 功能的资源对象,比如类似 Deployment 的自定义资源,实现该接口来告诉 Karmada 对应资源的副本数。
-
ReviseReplica:
该 hook 点发生在从 ResourceBinding 到 Work 这个过程中,针对有 replica 功能的资源对象,需要按照 Karmada 发送的 request 来修改对象的副本数。Karmada 会通过调度策略把每个集群需要的副本数计算好,你需要做的只是把最后计算好的值赋给你的 CR 对象。
-
Retain:
该 hook 点发生在从 Work 到 Resource 这个过程中,针对 spec 内容会在 member 集群单独更新的情况,可以通过该 hook 告知 Karmada 保留某些字段的内容。
-
AggregateStatus:
该 hook 点发生在从 ResourceBinding 到 ResourceTemplate 这个过程中,针对需要将 status 信息聚合到 Resource Template 的资源类型,可通过实现该接口来更新 Resource Template 的 status 信息。
3.2 面向应用的多集群弹性伸缩
3.2.1 弹性伸缩
用户创建HPA资源,如指定workload、cpu上限、min和max值。 FedController开始计算clusterA和clusterB资源,在clusterA和clusterB创建HPA,并按比例分配集群的min和max。 当集群clusterA 和 clusterB 触发定义的cpu资源上限,clusterA和clusterB开始扩容。 Karmada控制平面的clusterA和clusterB的HPA work对象的status里有记录集群扩容副本情况。 FedHPAController感知到work的变化,并获取到每个集群真实的副本数,开始更新调度资源RB和控制平面的workload副本数。保证了控制平面和member集群的调度和副本数一致,不会出现重复调度和副本不一致。反之 cpu 流量下去开始缩容,计算过程一样。 同时添加了资源再度均衡的能力,当集群资源变化时,FedHPAController 会计算集群总资源、节点碎片、是否可调度等情况,重新分配每个集群 HPA 的 min 和 max 值,确保在扩容时候有充足的资源。
3.2.2 定时伸缩
-
用户根据业务需求,创建CronHPA。定义扩容时间和缩容时间。 -
到扩容时间点,CronHPAController开始扩容workload。 -
Karmada-scheduler开始调度,根据每个集群的资源开始合理分配每个集群的副本数。 -
到缩容时间点,CronHPAController开始缩容workload。
3.2.3 手动和指定扩缩容
-
用户指定workload,进行扩容或者缩容。 -
Kamrada-scheduler开始调度,合理分配扩容或者缩容值到每个集群。
-
用户在 clusterA
指定workload
下面一个pod
进行缩容,需要在ScaleStrategy.PodsToDelete
指定pod
。 -
需要在 Karmada
实现openkurise
实现该字段的资源解析,不让它被控制平面覆盖。 -
并在控制平面更新 workload
的副本和pp
资源,保证副本数和调度结果一致。 -
member
集群的openkruise
开始删除指定的pod
。
3.3 统一调度
3.3.1 多集群调度
Karmada 多集群调度主要实现跨集群资源的合理分配和集群故障快速迁移业务。如上图所示主要通过 Karmada scheudler
和 emulator
配合实现,其中emulator主要负责每个集群的资源的估算。
-
用户定义workload和策略匹配,生成RB资源。 -
doSchedulerBinding开始对RB进行调度,通过预选和优选调度算法选择合适的集群,当前不会进行资源计算,和K8s调度预选和优选不一样。 -
selecClusters根据筛选的集群,进行副本分配。这里有2种模式,主要根据用户配置的策略去选择。
a. Static scheduler 只计算所有资源的request,不考虑调度规则。
b. Dynamic scheudler 会在计算所有request的同时,也会考虑一部分调度规则。 -
最终计算出每个集群分配的副本数并更新RB资源,调度结束后其它控制器会根据RB进一步处理。
-
比如当集群clusterA发生故障,在一定判定条件内,会触发Karmada-scheduler重新调度。 -
Karmada-scheduler会将故障集群的资源,调度到clusrerB和clusterC。
3.3.2 重调度
-
过滤RB资源,发现RB调度没有达到预期。 -
对workload发起重新调度。 -
进过预选、优选等流程,再次分配调度结果。 -
最终将workload的所有pod调度起来。
3.3.3 单集群调度模拟器
-
使用fake client 去模拟线上集群。 -
fake client启动k8s默认的调度器以及自研的调度算法,修改binding接口。并配置到每个member集群。 -
podRequest请求每个集群调度模拟器,运行真实的调度算法,并计算调度结果。
3.4 灰度上线
3.4.1 应用迁移
-
管理员通过容器平台,将需要迁移的应用插入迁移白名单。 -
用户通过cicd发布,容器平台会进行发布接口调用。 -
isKarmada模块会查看迁移名单,在白名单内将资源联邦化,接入Karmada管理。不在白名单内保持原有的静态集群管理。 -
最终完成应用的发布,用户完全无感知。保持2种管理方式并行存在。
3.4.2 应用回滚
-
应用发布迁移的过程中发生了未知的错误,并且短时间无法恢复。避免阻塞应用正常发布,需要回滚。 -
应用被Karmada接管后发生未知的错误,需要避免资源联邦化后无法控制,需要回滚。
-
管理员通过容器管理平台,将需要回滚的应用从迁移白名单删除。 -
并对应用对应的workload以及关联的资源打上注解。 -
修改exection-controller源码,exection-controller发现以上注解,最终调用update/create时不做处理。 -
修改defaultInterpreter源码,发现以上注解ReviseReplica不修改副本数。 -
这样就可以阻断Karmada控制平面和member集群的联系。这里为什么没有直接从Karmada删除资源,主要避免删除这种高危操作以及方便后期恢复后重新接入Karmada。
3.4.3 迁移策略
应用迁移Karmada原则:
-
先测试、再预发、最后生产
-
重大变更,分批次灰度,按照1:2:7比例灰度迁移
-
责任人双方点检验证,并观察监控5~10分钟
-
灰度后确认没有异常后继续迁移,否则走回滚流程
四、总结
vivo当前主要通过非联邦多集群管理,结合CICD实现了应用静态发布和管理,具备了应用的滚动、灰度、手动扩缩容、指定缩容和弹性扩缩容等能力。相对于非联邦多集群部分能力不足,如跨集群统一资源管理、调度和故障转移等,在联邦集群进行部分能力的探索和实践。
同时联邦集群增加了整体架构的复杂度,集群之间的状态同步也会增加控制面的额外开销和风险。当前社区在联邦集群还处在一个探索和不断完善的阶段,企业在使用联邦集群应结合自身需求、建立完善的运维保障和监控体系。
对于已经存在的非联邦化的资源需要建设迁移和回滚能力,控制发生故障的范围和快速恢复能力。
参考项目:
-
GitHub:kubernetes-retired/federation
-
GitHub:kubernetes-retired/kubefed
-
GitHub:karmada-io/karmada
-
GitHub:clusternet/clusternet
-
GitHub:open-cluster-management-io/ocm
-
GitHub:kubernetes-sigs/cluster-api
-
GitHub:clusterpedia-io/clusterpedia
-
GitHub:submariner-io/submariner
-
GitHub:karmada-io/multi-cluster-ingress-nginx
-
GitHub:istio/istio
-
GitHub:cilium/cilium
来源:本文转自公众号vivo互联网技术,点击查看原文。
还不过瘾?还想了解更多架构/业务转型?10月26日-27日,GOPS 2023 · 上海站,云原生、持续测试、持续交付、DataOps、DevSecOps 等精彩实践,扫码了解更多⏬
近期好文:
发表评论