协会地址:上海市长宁区古北路620号图书馆楼309-313室
使用 Kairos、k0rdent 和 bindy 从零开始构建云原生平台
来源: 云原生计算基金会(Cloud Native Computing Foundation)
作者: Erick Bourgeois,加拿大皇家银行资本市场(RBC Capital Markets)Kubernetes 平台工程总监兼负责人
原文链接: https://www.cncf.io/blog/2026/05/13/building-a-cloud-native-platform-from-the-ground-up-with-kairos-k0rdent-and-bindy/
(https://www.cncf.io/projects/kairos “前往 Kairos”)
正如我们在上一篇关于 FluxCD 的文章中所分享的,RBC Capital Markets 一直在有条不紊地推进 Kubernetes 平台的现代化改造。基于 FluxCD 的 GitOps 为我们提供了坚实的部署基础。但随着平台的发展——如今我们运营着超过 50 个集群,横跨本地 VMware 环境和多个云平台——我们遇到了一系列问题,而这些问题没有任何一个现成的工具能够一并解决:如何管理集群自身的生命周期?如何确保每个节点在启动时是可复现且防篡改的?如何将 Kubernetes 的服务发现与企业 DNS 基础设施集成,而无需每次记录变更都走工单队列?
这篇文章将介绍我们用来回答这些问题的几个项目,以及我们在受监管的金融机构内部使用它们构建时学到的经验。
挑战:在受监管环境中进行大规模平台工程
在混合基础设施上管理 50 多个 Kubernetes 集群不仅仅是运维挑战,在资本市场中,这也是合规挑战。SOX、PCI-DSS 和 Basel III 对可审计性、配置漂移预防和网络分段提出了切实的要求。我们的平台团队无法容忍存在雪花节点、未文档化的集群状态或多年累积的手动 DNS 记录。
当我们退后一步审视工程投入时,三个差距尤为突出:
- 节点配置漂移: 经过长期修补和变更的基于 VM 的节点变得难以追溯。
- 集群部署: 为交易台或风险团队创建新集群需要多天的手动操作,且缺乏单一可信源。
- DNS 集成: 每个新服务或 Ingress 端点都需要向网络团队提交手动工单,这造成了瓶颈,并且审计追踪脱离了我们的 GitOps 工作流。
我们决定从零开始逐一解决这些问题,在已有云原生项目的地方直接使用,在缺失的地方自行构建。
Kairos:值得信赖的节点不可变操作系统
第一个难题是节点不可变性。我们评估了多种方案,但 Kairos(一个 CNCF Sandbox 项目)最直接地符合我们的需求:一个从第一性原理出发设计的 Linux 发行版,具备不可变、声明式配置和可复现的特性。
使用 Kairos,我们集群中的每个节点都从 OCI 镜像启动。该镜像基于已知的基础(在我们的案例中是基于 RHEL 衍生),融入了我们批准的安全配置,并发布到内部镜像仓库。通过 cloud-config 模型,我们可以定义节点行为、SSH 密钥、网络配置、针对 Active Directory 的 SSSD 认证、Kubernetes 代理注册——所有这些都以版本化的 YAML 形式存在,并像其他平台组件一样通过 FluxCD 流转。
操作系统镜像的 CI/CD 流水线
不可变基础设施中一个较少被讨论的挑战是镜像构建和验证所需的纪律性。我们对待 Kairos 镜像的方式与应用程序容器镜像完全相同:每次变更都会触发 GitHub Actions 流水线,该流水线构建镜像、在实时 VM 上运行集成测试,并且仅在测试通过后才发布新的 OCI 标签。夜间构建会在上游基础包或 Kairos 框架本身的回归问题进入生产环境之前将其捕获。
这意味着我们的节点镜像流水线具备与应用程序 CI 相同的特性:
- 每次提交都经过端到端测试,而不仅仅是 lint 或静态分析。
- 夜间运行验证当前固定的基础镜像和包集仍然能够生成可启动、配置正确的节点。
- OCI 标签是不可变制品。 通过集成测试的标签永远不会被修改;回滚只需指向之前的标签即可。
使用 VirtRigaud 进行 Kubernetes 原生 VM 部署
VMware 场景的另一半是我们如何从 Kairos 镜像实际部署 VM。我们没有使用命令式的 vSphere 工具,而是采用了 VirtRigaud,这是一个 Kubernetes Operator,通过统一的 CRD API 在多个虚拟机管理程序(vSphere、Libvirt/KVM 和 Proxmox)上提供声明式 VM 管理。
模型很直接:我们构建的 Kairos OCI 镜像被注册为 VMImage CRD,而 VM 则表示为引用该镜像的 VirtualMachine CRD。FluxCD 像处理其他平台资源一样协调这些清单。最终结果是,在 vSphere 上部署一个新的 Kairos 节点在语义上与部署一个工作负载完全相同:它是一个 Pull Request,经过审查、合并并自动协调。
VirtRigaud 的远程提供商架构也很好地满足了我们的安全需求:提供商凭证被隔离到各自的 Pod 中,控制器通过 gRPC/TLS 与它们通信,而不是集中嵌入虚拟机管理程序凭证。
这种架构带来的运维转变是显著的:
- 设计上消除了配置漂移。 生产节点上不再运行 apt 或 yum。如果需要配置变更,则构建新镜像、进行集成测试,然后滚动更新节点。
- 审计追踪变得简单。 由于每个节点的配置都是注册表中的 OCI 摘要,每个虚拟机都是 Git 中带版本号的 CRD,我们可以精确回答“那个日期该节点上运行的是什么?”。
- VMware 集成完全符合 GitOps 原生模式。 节点的部署、更新和退役都通过与平台上其他所有内容相同的 GitOps 工作流进行。
学习曲线是真实存在的:在不可变镜像中正确配置内核模块、NetworkManager 和企业认证(SSSD/AD)需要反复迭代。但一旦解决,结果就是我们能够真正信任的节点基础,这在监管机构提出问题时至关重要。
k0rdent:作为平台的集群生命周期管理
不可变节点解决了“正在运行什么”的问题。但我们仍然需要在整个集群中一致地回答“集群如何创建、更新和退役?”。
k0rdent 基于 Cluster API (CAPI),为我们提供了一个 Kubernetes 原生的控制平面来管理 Kubernetes 集群。k0rdent 没有将集群部署视为一次性的脚本编写工作,而是将集群建模为 CRD。结合用于集群内控制平面的 k0smotron,我们现在可以声明式地表达整个集群拓扑,而 FluxCD 则持续协调该状态。
我们为工作负载集群选择的 Kubernetes 发行版是 k0s,这是一个 CNCF Sandbox 项目。k0s 是一个完全自包含的单二进制 Kubernetes 发行版,除了内核之外没有主机操作系统依赖。当你的节点运行不可变操作系统时,这个特性非常重要:k0s 可以干净地安装到 Kairos 镜像中,无需包管理器、运行时 systemd 单元文件操作,也不需要 kubeadm 等发行版所做的主机级假设。Kairos 和 k0s 的组合为我们提供了一个完整的从节点到集群的栈,其中每个组件都是声明式表达的、OCI 打包的,并且可以从干净启动中重现。
k0smotron 进一步扩展了这一点,它允许 Kubernetes 控制平面作为工作负载在管理集群内运行,这意味着即使控制平面也被表达为 CRD,由 FluxCD 协调,没有带外状态。
我们最终确定的架构将集群组织成中心辐射模型:
- 管理集群 运行 k0rdent、k0smotron 和 CAPI 控制器。
- 工作负载集群 运行 k0s,通过存储在 Git 中的 CRD 清单进行部署和退役。
- MetalLB 处理裸机段上的负载均衡;Traefik 在所有分支集群上提供配置一致的入口。
除了第一天部署,这种方法还改变了我们处理第二天运维的方式:
- 集群升级 是一个拉取请求。在清单中更新所需的 Kubernetes 版本,经过审查,FluxCD 应用它。不存在“谁在哪个集群上运行了什么命令”的模糊性。
- 集群模板 让我们能够标准化常见用例的配置:交易台集群、风险计算集群、工具集群,并在几分钟内(而不是几天内)启动新实例。
- 合规态势 默认一致。由于每个集群都表达为代码,我们的基于 CEL 的准入 Webhook 和 RBAC 策略在集群创建时统一应用,而不是事后附加。
我们还使用 k0rdent 作为点计算调度器的基础,该调度器允许将捐赠的物理服务器容量动态吸收到我们的平台中,我们计划在未来的文章中分享更多关于这一能力的信息。
bindy:Kubernetes 原生的 DNS 操作
最后一个差距,也是现有项目未能完全满足我们需求的地方,是 DNS。在资本市场中,DNS 并非普通问题。我们的交易应用程序、市场数据馈送和风险系统广泛使用 DNS,而服务于这些系统的企业基础设施已经建立并维护了数十年。
在加拿大皇家银行资本市场(RBC Capital Markets),这套基础设施的核心是 Infoblox——一个深度集成到网络运维中的企业级 DDI 平台。然而,其集成模式是为 Kubernetes 之前的时代构建的:每条 DNS 记录请求都要经过工单工作流,路由到网络团队,处理时间以小时或天计。随着平台扩展到 50 多个集群,每个集群都会启动数十个服务和入口端点,这种配置延迟成了真正的运维瓶颈,而 DNS 变更的纸质记录完全游离在 GitOps 审计追踪之外。
bindy 由 Erick Bourgeois 构建,旨在弥合这一鸿沟。它是一个用 Rust 编写、基于 kube-rs 的 Kubernetes 操作器(operator),将 DNS 区域和记录作为一等 Kubernetes 资源进行管理。其核心设计理念是让 DNS 成为 GitOps 的公民,享有与平台上其他所有资源相同的协调保证:
- 区域和记录是 CRD(自定义资源定义)。 Git 中的 DNSZone 或 ARecord 清单是事实来源,由 bindy 的控制器持续协调。
- RFC 2136 动态更新 允许 bindy 将记录变更推送到 DNS 后端,无需人工干预或工单队列。
- bindcar,一个边车(sidecar)REST API,提供 RNDC 接口,bindy 的控制器通过该接口执行区域生命周期操作(区域创建、删除、重载)以及动态更新。
- 具有严格写入边界的多控制器架构 可防止脑裂场景。选择控制器和同步控制器相互分离;同步状态存储在已同步的资源上,以支持强制协调模式。
效果立竿见影。新服务的 DNS 记录作为部署服务本身的同一 GitOps 工作流的一部分自动创建,配置时间从数小时降至数秒,审计追踪变成了 Git 历史,而非工单系统。之前每次 DNS 变更都需要人工协调的僵化集成边界,被一个协调循环所取代。
目前,bindy 正在扩展以支持合规评分(基于 CRD 的区域健康模型)以及未来的 MCP 服务器接口,用于与 AI 驱动的平台工具集成。
三者如何协同工作
这套技术栈之所以连贯,是因为每一层都建立在相同的基础原则之上:一切皆代码,持续协调,无人工状态。
`
Git (source of truth)
└── FluxCD (reconciliation engine)
├── k0rdent / CAPI manifests → cluster lifecycle
├── Kairos cloud-config → node configuration
└── bindy CRDs → DNS records`
Kairos 确保每个节点从已知、可审计的镜像启动。k0rdent 确保每个集群以声明式方式表达和管理。bindy 确保每条 DNS 记录都是版本化的制品。FluxCD 将它们统一为单一协调平面。最终形成的平台中,节点、集群或网络层面的漂移在结构上被预防,而非通过运维管理。
挑战与经验教训
构建此平台让我们学到了几件希望早点知道的事:
- 采用不可变操作系统需要耐心处理企业集成。 在烘焙不可变镜像时,SSSD、NetworkManager 和企业 CA 信任链都需要明确关注。记录一切;凌晨 2 点调试启动失败的二线运维人员往往不是构建镜像的那个人。
- 基于 CRD 的集群管理将责任左移。 当集群配置通过拉取请求(Pull Request)完成时,平台团队需要提前投入审查流程和模板治理,否则“只是一个 YAML 文件”的简单性本身就会成为新的漂移来源。
- 用 Rust 构建 Operator 是长期正确的选择,但生态系统仍在成熟中。 kube-rs 非常出色,但带有反射器/存储缓存的多控制器架构模式需要深思熟虑的设计决策,而社区仍在对此达成共识。
展望未来
我们的平台持续演进。目前正在积极开发的领域包括:
- SPIRE/SPIFFE 集成,用于所有 50+ 集群的工作负载身份,以中心辐射型 SPIRE 架构替代每服务证书方案,满足零信任要求。
- Foundry,一个用 Rust 构建的内部自助服务 API 层,通过受治理的事件驱动接口,向开发团队提供集群和 DNS 配置能力。
- 基于 Kairos 的现货计算,利用 k0smotron 和 Kata Containers 动态吸收捐赠的物理服务器容量。
我们自豪地基于 CNCF 生态系统构建并回馈社区,期待继续分享所学。如果您在受监管环境中面临类似挑战,我们很乐意交流——欢迎在 Kairos、k0rdent 和 FluxCD 的 Slack 社区找到我们,或通过 LinkedIn 直接联系。
Erick Bourgeois 是 RBC Capital Markets 的 Kubernetes 平台工程总监兼负责人,管理跨多云和本地环境的 50+ Kubernetes 集群。他是 KubeCon 和 FluxCon 演讲者、FINOS Common Cloud Control 成员,以及开源开发者,GitHub 地址:github.com/firestoned。







