RBC Capital Markets 的 Kubernetes 平台演进走了一条很务实的路线:先用 FluxCD 把 GitOps 的底座打牢,再逐步向上解决更硬的问题——节点操作系统不可变性、多集群生命周期管理、跨集群网络连通。Kairos、k0rdent 和 bindy 这三个项目分别对应这三层需求,组合起来构成了一套从裸金属到应用交付的完整链路。
下面拆解每层做了什么,以及怎么落地。
FluxCD 打了底,但平台还要往上走
FluxCD 解决的是"声明式部署"这一层:Git 仓库里的 YAML 就是集群状态的真实来源,控制器自动同步。RBC 的实践证明这套机制可靠,但 GitOps 本身不回答另外三个问题:
- 节点 OS 怎么交付? 传统做法是手动装系统再装 kubelet,版本漂移、配置漂移难以追踪。
- 多集群怎么统一管理? 金融场景下集群数量多、合规要求严,逐个手工运维不可接受。
- 集群之间怎么连通? 不同区域、不同环境的集群需要安全、可控的跨集群通信,而不是简单打通 VPN。
这三层缺任何一层,平台都会在规模扩张时撞墙。Kairos、k0rdent、bindy 正是逐层补上这些缺口。
Kairos:让节点 OS 也变成声明式交付
Kairos 的核心思路是把操作系统做成不可变镜像——类似容器的思路,但作用范围是整台机器。你定义一个镜像配方,构建出可启动的 ISO 或云镜像,部署后节点以只读根文件系统运行,升级就是替换镜像,而不是 apt upgrade。
这样做的好处直击金融合规痛点:
- 节点状态可审计——镜像版本即节点版本,没有灰色地带。
- 升级可回滚——旧镜像还在,回滚就是切回旧镜像启动。
- 配置漂移被物理阻止——根文件系统只读,
/etc下的临时修改重启即消失。
构建一个 Kairos 镜像
以下是一个最小化 Kairos 镜像配方,基于 Ubuntu 并预装 kubelet。实际使用时需要根据目标基础设施调整 cloud-init 和架构参数。
# kairos-image.yaml — Kairos 镜像配方
name: kairos-ubuntu-kubelet
version: "1.29.2-0"
base-image: ubuntu:22.04
# 要打入镜像的容器化组件
container-images:
- name: kubelet
image: registry.k8s.io/kubelet:v1.29.2
- name: kairos-agent
image: quay.io/kairos/kairos-agent:latest
# 启动后执行的 cloud-init
cloud-init:
users:
- name: core
lock_passwd: true
shell: /bin/bash
sudo: "ALL=(ALL) NOPASSWD:ALL"
write_files:
- path: /etc/kairos/config.yaml
content: |
# Kairos 节点配置
node-name: "{{ .NodeName }}"
cluster-token: "CHANGE_ME_TO_REAL_TOKEN"
runcmd:
- systemctl enable kairos-agent
- systemctl start kairos-agent
构建命令:
# 拉取 Kairos 构建工具并生成镜像
docker run --rm -v $(pwd):/workspace \
quay.io/kairos/kairos-builder:latest \
build --config kairos-image.yaml \
--output-type iso \
--output-name kairos-ubuntu-kubelet.iso
# 产物 kairos-ubuntu-kubelet.iso 可直接写入 USB 或通过 PXE 部署到裸金属
部署后节点启动,kubelet 已经在镜像里,不需要额外安装。升级节点时,Kairos agent 拉取新镜像并切换启动分区,整个过程与容器镜像更新逻辑一致。
k0rdent:多集群生命周期的控制平面
节点 OS 不可变之后,下一步是让集群本身也变成声明式资源。k0rdent 是一个多集群管理框架,它的定位不是又一个 Cluster API fork,而是在 Cluster API 之上提供更贴近平台运维的抽象层。
核心机制:
- ClusterTemplate:定义集群的"规格书"——节点数量、Kairos 镜像版本、网络插件、合规策略等。
- ClusterDeployment:引用模板并填入具体参数(区域、集群名、凭证),控制器按此创建真实集群。
- ClusterUpgrade:声明式触发集群升级,与 Kairos 镜像版本联动。
这样做的直接收益是:新建一个合规集群从"人天级"变成"分钟级",且每个集群的规格可追溯、可对比。
用 k0rdent 声明一个新集群
# cluster-template.yaml — 集群模板,一次定义多次复用
apiVersion: k0rdent.mirantis.com/v1alpha1
kind: ClusterTemplate
metadata:
name: financial-compliance-cluster
spec:
nodeGroups:
- name: control-plane
count: 3
machineConfig:
imageRef: kairos-ubuntu-kubelet:1.29.2-0
cpu: 4
memory: 8Gi
- name: worker
count: 5
machineConfig:
imageRef: kairos-ubuntu-kubelet:1.29.2-0
cpu: 8
memory: 16Gi
addons:
- name: calico
version: "3.26.1"
- name: fluxcd
version: "2.2.3"
compliance:
auditLog: true
podSecurityStandard: restricted
---
# cluster-deployment.yaml — 从模板派生一个具体集群
apiVersion: k0rdent.mirantis.com/v1alpha1
kind: ClusterDeployment
metadata:
name: prod-east-01
namespace: k0rdent-system
spec:
templateRef: financial-compliance-cluster
region: us-east-1
provider: aws # 也支持 bare-metal、vsphere 等
credentialsRef: aws-financial-team
提交到管理集群后,k0rdent 控制器会调用 Cluster API 的机器驱动去创建节点,节点启动时加载 Kairos 镜像,kubelet 自注册,集群自动成型。FluxCD 再接管应用部署——整条链路全部声明式。
bindy:跨集群连通的"安全管道"
多集群建好了,下一个问题是:prod-east-01 和 prod-west-01 之间的服务怎么互相调用?传统做法是打通底层网络(VPN、VXLAN),但这在金融合规下风险很高——底层一通,上层很难做细粒度控制。
bindy 的思路是在应用层做连通:每个集群部署一个 bindy agent,agent 之间建立 mTLS 通道,通过声明式规则决定哪些服务可以跨集群暴露、哪些集群可以消费。
关键特性:
- 零底层网络依赖:不需要 VPN、不需要 VPC peering,agent 之间通过公网或已有网络 + mTLS 通信。
- 声明式服务暴露:在集群 A 里声明"服务 X 可被集群 B 访问",只有这个通道会建立。
- 审计友好:所有跨集群调用经过 bindy agent,可记录、可限流、可撤销。
配置跨集群服务连通
# bindy-export.yaml — 在 prod-east-01 集群声明暴露服务
apiVersion: bindy.mirantis.com/v1alpha1
kind: ServiceExport
metadata:
name: trade-validation-service
namespace: trading
spec:
service:
name: trade-validator
port: 8080
allowedConsumers:
- cluster: prod-west-01
namespace: settlement
# 可选:限流与认证策略
rateLimit:
requestsPerSecond: 100
authPolicy:
mtls: true
tokenValidation: true
---
# bindy-import.yaml — 在 prod-west-01 集群声明消费远端服务
apiVersion: bindy.mirantis.com/v1alpha1
kind: ServiceImport
metadata:
name: trade-validation-service
namespace: settlement
spec:
remoteCluster: prod-east-01
remoteNamespace: trading
remoteService: trade-validator
# 本地会生成一个同名的 Kubernetes Service,应用代码无感知
localPort: 8080
应用在 prod-west-01 里直接调用 trade-validation-service.settlement:8080,bindy agent 自动将请求路由到远端集群,整个过程对应用代码透明。如果合规审计要求切断通道,删掉 ServiceExport 即可——比改防火墙规则快得多,也更可追溯。
三层联动:从裸金属到跨集群调用的完整链路
把三个项目串起来看,RBC 的平台架构形成了一个清晰的分层:
| 层次 | 工具 | 解决的问题 | 声明式载体 |
|---|---|---|---|
| 节点 OS | Kairos | 不可变、可审计、可回滚的操作系统交付 | 镜像配方 YAML |
| 集群生命周期 | k0rdent | 多集群规格统一、快速创建、声明式升级 | ClusterTemplate / ClusterDeployment |
| 跨集群连通 | bindy | 安全、细粒度、可审计的服务间通信 | ServiceExport / ServiceImport |
| 应用部署 | FluxCD | GitOps 部署与配置同步 | Git 仓库中的 HelmRelease / Kustomization |
每一层都是声明式的,每一层都有控制器确保实际状态与声明一致。这意味着平台运维的核心工作从"执行操作"变成了"编写和审查 YAML"——这对金融场景下的合规审计是根本性的改变。
落地时的几个现实考量
不可变 OS 的调试成本。 Kairos 的只读根文件系统在防止漂移方面非常有效,但调试时需要临时写入。Kairos 提供了 kairos-debug 模式和持久化分区(/var、/etc 的 overlay),上线前务必演练"调试→恢复"的完整流程。
k0rdent 的模板粒度。 模板太粗,不同环境的差异靠参数补丁堆叠,YAML 会变得难以阅读;模板太细,维护成本上升。建议先做两到三套模板(prod / staging / dev),差异用参数覆盖而不是拆成十几个模板。
bindy 的延迟与可靠性。 跨集群调用引入了额外网络跳数,金融交易场景对延迟敏感。bindy 适合做跨集群的管理类、校验类调用(如合规校验、结算确认),不适合做高频交易的数据面调用。数据面仍应保持在单集群内。
升级顺序。 三层联动意味着升级有依赖关系:Kairos 镜像升级 → k0rdent 触发节点滚动更新 → FluxCD 同步应用新版本。建议在 staging 环境完整跑一遍这个链路后再推进 prod。
RBC 的实践说明,云原生平台的成熟不是单点突破,而是逐层补齐。FluxCD 解决了部署层,但节点、集群、连通这三层如果不做声明式改造,平台规模扩张时运维复杂度会指数级增长。Kairos + k0rdent + bindy 的组合提供了一个从底到顶的声明式路径——不是最简单的路径,但在合规和可审计性上是最扎实的。