从集群创建到工作负载就绪,自动化每一步。
译自 Managing 100s of Kubernetes Clusters using Cluster API,作者 CSS Engineering。
由核心基础设施团队成员 Zain Malik 和 Nibir Bora 撰写。
在 City Storage Systems,我们的核心基础设施团队驾驭着管理 100 多个多租户 Kubernetes 集群的复杂性,每个集群每天托管数万个活动 Pod。我们的整个软件堆栈在 Kubernetes 上运行,从关键任务微服务到有状态数据库和可观测性解决方案。
这篇博文深入探讨了我们在集群配置、生命周期管理和升级中实现完全自动化的历程。借助新的工具集,我们将配置和准备工作负载就绪集群所需的时间从 1.5 周缩短到不到 1 天,同时保持精简的工程师团队。这种转型是由我们在几个月内迁移到 Microsoft Azure 的战略决策催化的。在过渡期间,我们运营的集群数量增加了一倍以上。
我们提供了一组 Kubernetes 自定义资源 和 Operator,对我们的基础设施和相关操作进行建模。Kubernetes 运营商模式的灵活性使这种方法极其强大,我们相信它可用于管理任何公有云提供商上的集群。
图 1:用于管理 Kubernetes 集群和节点池的所有自定义资源的层次结构。
我们最初使用 Terraform 创建集群,然后使用自定义内部 Kubernetes 运营商管理节点池。包括 Kubernetes 版本升级在内的更改是通过 GitOps 处理的。然而,所需的认知开销和手动干预使得这种方法不可持续,特别是将 80 多个集群从一个云提供商迁移到另一个云提供商。
这促使我们探索 Cluster API,它提供声明性 API,用于简化多个 Kubernetes 集群的配置、升级和管理。两个关键因素使Cluster API 特别有吸引力:
要使用 Cluster API 和适用于 Azure 的 Cluster API 提供商 (CAPZ) 创建集群,我们只需创建以下自定义资源的对象:
类似地,要创建节点池,我们需要创建以下自定义资源的对象:
我们能够将这些流程无缝集成到我们现有的 CI 流水线中,完全依赖 GitOps 进行集群管理。我们不使用 Cluster API 提供的 clusterctl CLI。
但是,立即采用 Cluster API 有三个主要障碍:
我们依靠与 Microsoft Azure 的合作关系来找到前进的道路。他们建议我们在开源中协作 CAPZ 项目以实现功能完整性。Microsoft AKS 团队的几名工程师以及我们核心基础设施团队的工程师为 CAPZ 项目做出了贡献,优先考虑与我们的生产用例相一致的功能。这种合作取得了巨大的成功。它使我们能够在三个月内使用 Cluster API 和 CAPZ 启动我们的第一个 Kubernetes 集群。
虽然Cluster API 和 CAPZ 简化了集群创建,但这些集群尚未为工作负载做好准备。
使用 Terraform 并运行 Azure CLI 命令为每个集群配置这些内容与我们最大程度减少人工干预的原则不符。因此,我们决定编写一个配套的 Kubernetes 运算符。这引入了 AzureClusterAdditionalConfig,这是一个可扩展的自定义资源,适用于集群所需的任何其他 Azure 托管服务配置。对于 ACR 权限,这会解析为 AzureRoleAssignment 对象,以及用于自定义集群自动扩缩器配置的 AzureClusterAutoscaler 对象。
引入配套 operator 使我们能够通过使用 GitOps 安装单个 Kubernetes 资源来完全自动执行集群创建,并准备它们以支持工作负载。这种简化的方式促进了 80 多个生产集群在不同云提供商之间的迁移。
在新的云提供商上运行生产工作负载几个月后,我们发现了两个主要的运营痛点。
我们实现了一个节点池 Kubernetes operator,它引入了一个封装了替换节点池多步骤过程的 Nodepool 资源。在后台,该运算符会创建一个新的节点池、清空旧节点池,然后在对用户完全不透明的过程中删除它。从用户的角度来看,所有节点池操作都是通过单个 GitOps 更改就地完成的。这种端到端自动化在 Kubernetes 版本升级期间尤其强大。
唯一的限制是,我们无法使用 ownerReference 将新的 Nodepool 资源链接到 Cluster API 的 MachinePool 或 CAPZ 的 AzureManagedMachinePool 资源的现有层次结构。相反,这些资源并排存在,并使用 objectReference 链接。在完全删除节点池时,此缺点变得明显,因为资源层次结构是使用 finalizers 删除的。
图 2:完整的集群管理堆栈。
不断发展的集群管理工具链使我们能够管理两倍数量的集群和应用程序,同时维持核心基础设施团队中相同数量的工程师。这一成就标志着运营效率的显着提升,这得益于我们对 GitOps 原则的坚定承诺和消除人工干预过程。沿着同样的思路,自修复、漂移检测等是我们平台上的首要理念。这种思维方式使我们始终能够优先考虑组织需求,同时平衡效率、可靠性和敏捷性,利用 Kubernetes 的可扩展性。
回顾我们的历程,我们有一些关键的收获和失误:
那么,我们未来有什么计划?我们已经启动了一项战略计划,以使我们达到下一个规模水平。这涉及自动分区工作负载集群,考虑 API 服务器压力和节点大小等因素。我们还开始配置更多单租户集群。此外,正在努力简化准备工作负载就绪集群所需的时间,包括 IP 地址分配和安装集群附加组件等步骤。所有这些举措都以最大程度地减少人为干预和实现完全自动化为指导。通过此路线图,我们旨在熟练地高效管理 500 多个 Kubernetes 集群。
我们要感谢 Microsoft 的 Cécile Robert-Michon、David Tesar 和 Jack Francis。每个人都在项目的不同阶段做出了贡献。