设计一个多云资源编排平台(Multi-Cloud Resource Orchestration Platform)
设计一个多云资源编排平台(Multi-Cloud Resource Orchestration Platform) 背景:Apple 的内部团队需要在 AWS、Azure、GCP 上统一管理云资源(虚拟机、数据库、存储、网络等)。目前每个团队各自用 Terraform 脚本,缺乏统一管控,存在资源泄漏、配置不一致、权限混乱等问题。 需求:
- 用户通过统一的 API 或 YAML 声明式地提交资源需求(如 “我要一个 AWS RDS 实例,规格 db.t3.medium”)
- 平台负责在对应云厂商上创建 / 更新 / 删除资源,并保持最终一致性
- 支持资源的生命周期管理:创建、更新、删除、查询状态
- 支持多租户隔离,不同团队只能操作自己的资源
- 支持操作审计和成本统计
这个需求本质上就是我们前面聊 Crossplane 时讲的那个场景的完整实现——”用统一控制平面管理多云资源、支持自助式声明式申请、持续一致性、多租户隔离”。所以我会以 Crossplane 的架构思路为骨架来设计,同时针对 Apple 场景里提到的资源泄漏、成本统计、审计这些具体痛点做针对性设计,而不是从零发明一套新东西。下面按分层来讲。
整体架构理念
不做”命令行工具+CI 触发”的一次性执行模型(也就是现在各团队各自跑 Terraform 的做法),而是做一个常驻运行、持续调谐(reconcile)的控制平面——这直接解决”资源泄漏”和”配置不一致”两个痛点:控制平面知道每个资源”应该是什么样”,能持续核对云上”实际是什么样”,发现漂移主动纠正或告警,而不是等人手动发现。整个平台分七层:声明式 API 层、控制平面核心、Provider 适配层、多租户隔离层、生命周期管理、审计层、成本层。
第一层:声明式 API 层——YAML 和 REST/gRPC 双入口
底层数据模型基于 Kubernetes 的 CRD(Custom Resource Definition),团队可以用 kubectl 风格的 YAML 提交需求,也可以走 REST/gRPC API(内部有一层 API Gateway 把 REST/gRPC 请求翻译成对底层 CR 对象的创建/更新,这样不熟悉 K8s 的团队也能通过熟悉的 HTTP 接口使用平台,呼应我们之前聊 gRPC 时提到的多语言 SDK 优势——不同团队的自动化脚本可以用任意语言调用)。
apiVersion: platform.apple.com/v1alpha1 kind: DatabaseClaim metadata: name: payments-db namespace: team-payments spec: provider: aws # aws / azure / gcp engine: postgres size: db.t3.medium region: us-west-2 environment: prod
这里的关键设计是抽象层:DatabaseClaim 是一个跟具体云厂商无关的高阶概念,底层由平台根据 provider 字段翻译成 AWS RDS、Azure Database for PostgreSQL 或 GCP Cloud SQL 的具体资源定义。这正是 Crossplane 的 Composition 机制要解决的问题——业务团队只需要表达意图(“我要一个 postgres 数据库”),不需要精通三家云各自的资源模型和参数差异。
第二层:控制平面核心——基于 Crossplane 而不是重新造轮子
核心引擎建议直接采用 Crossplane 跑在一个专属 Kubernetes 集群上,而不是自建一套调谐引擎——原因我们之前详细聊过:它天然是持续调谐(解决”最终一致性”需求),天然复用 Kubernetes 的 RBAC/审计/存储(不用自己发明多租户和权限系统),而且已经有成熟的 provider-aws、provider-azure、provider-gcp 可以直接对接三朵云。对于个别 Crossplane provider 覆盖不到的冷门资源类型,可以用 provider-terraform 这个桥接 provider,让 Crossplane 在背后调用一段 Terraform 配置来补齐——这也是很多真实企业采用的过渡方案,不需要一步到位把所有资源类型都用原生 Crossplane provider 覆盖。
Composition 负责把 DatabaseClaim 翻译成具体资源,示意:
# 平台团队定义的 Composition(对业务团队不可见)
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: database-aws-postgres
spec:
compositeTypeRef:
apiVersion: platform.apple.com/v1alpha1
kind: XDatabase
resources:
- name: rds-instance
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
engine: postgres
instanceClass: db.t3.medium
# 强制打标签,呼应下面的成本追踪层
tags:
apple:owner: "{{ claim.namespace }}"
apple:platform-managed: "true"
第三层:多租户隔离——K8s Namespace + 云账号双重隔离
平台层用 Kubernetes Namespace 对应每个团队,配合 RBAC(Role/RoleBinding)限制团队只能读写自己 namespace 下的资源,这是”逻辑隔离”。但更关键的是”物理隔离”:每个团队在每个云厂商下应该有独立的账号/订阅/项目(AWS Account、Azure Subscription、GCP Project),平台通过每个 namespace 绑定不同的 ProviderConfig(存了不同的云凭证,通常是短期 STS/托管身份凭证而不是长期密钥),确保就算某个团队的凭证泄漏,影响范围也只限于这个团队自己的云账号——这直接解决背景里提到的”权限混乱”问题。建议再叠加一层准入策略(OPA Gatekeeper 或 Kyverno),比如限制团队只能选平台允许的实例规格、只能部署到指定区域,防止团队申请到不合规的配置。
第四层:生命周期管理——复用 Kubernetes 原生语义
创建/更新直接是 kubectl apply(幂等,重复提交同样的 YAML 不会重复创建);删除是 kubectl delete,对有状态资源(数据库这类)建议加 finalizer 做二次确认或者软删除保护,避免误删;查询状态直接读 CR 的 status 字段,Crossplane 会把云上资源的真实状态(Ready/Synced/报错信息)同步回这个字段,业务团队 kubectl get databaseclaim payments-db 就能看到当前状态,不需要额外去查云厂商控制台。REST API 层对这套状态做轮询或者 watch,转成 webhook 通知或者提供状态查询接口。
第五层:审计——三层交叉验证
审计设计成三层,互相印证:第一层是 GitOps 流程本身——建议团队提交资源需求走 Git PR(用 ArgoCD/Flux 做同步),每次变更都有 commit 记录和 code review,这层记录的是”谁请求了什么、谁批准的”;第二层是 Kubernetes 原生的 audit log,记录”控制平面实际执行了什么操作、什么时候执行的”;第三层是各云厂商自己的审计日志(AWS CloudTrail、Azure Activity Log、GCP Cloud Audit Logs),记录”云端实际发生了什么调用”。三层对得上说明系统运转正常,对不上就是排查的切入点——比如云端有资源变更但 K8s audit log 没有对应记录,大概率是有人绕过平台直接操作了云控制台,这正好也是下面”资源泄漏检测”要抓的场景。
第六层:资源泄漏检测——专门针对背景痛点设计
这是背景里明确提到的问题,值得单独设计一个机制:跑一个周期性的对账 Job,扫描三朵云上所有带 apple:platform-managed=true 标签的资源,和 Crossplane 当前管理的资源清单(相当于它的”总账本”)做全量比对。云上存在但平台账本里没有的,就是孤儿资源(可能是历史遗留、可能是有人绕开平台手动创建),自动打标记、发告警给对应团队,超过宽限期未处理的可以纳入自动清理流程。这个能力是分散式 Terraform 天然做不到的——因为每个团队的 state 是各自独立的孤岛,没有一个全局视角能做跨云、跨团队的资源对账,而这里因为所有资源都汇聚到同一个控制平面的账本里,对账变得很自然。
第七层:成本统计——强制标签 + 云账单 API 聚合
前提是第二层 Composition 里已经强制给每个资源打上 owner/team/environment 标签(不是团队自愿打标,是平台层强制注入,业务团队没法绕过),这是做成本归集的地基。再定期从三朵云各自的账单 API 拉数据(AWS Cost Explorer / CUR、Azure Cost Management API、GCP Billing Export to BigQuery),按标签聚合,汇总到统一的成本看板。因为整个平台本来就是 K8s 原生的,这块也可以直接接入 Kubecost/OpenCost 这类现成工具,减少自研成本。
关于迁移路径:怎么从现状过渡过来
不建议大爆炸式切换,现状是”每个团队各自的 Terraform 脚本”,迁移思路是团队级别逐步接管:对每个已存在的资源,用我们上周聊过的 import 机制(Crossplane 层面对应类似的 import 能力,或者先用 provider-terraform 包一层把现有 Terraform 配置原样接管过来),把资源”收编”进平台的账本里,而不是先销毁重建。接管完成之后这个资源才正式享受到持续调谐、审计、成本统计这些平台能力,新建资源则直接走平台的声明式流程,新老并存、逐步收敛。
为什么不是”统一大家都用同一套 Terraform 规范”这种更轻量的方案
这也是个合理的替代思路,值得说明取舍:如果只是想解决”配置不一致”,统一 Terraform module 规范+集中 remote backend 确实成本更低。但背景里明确提到还要解决资源泄漏(需要持续对账能力,Terraform 的一次性执行模型做不到)、多租户隔离(Terraform 本身没有原生的细粒度权限模型,得自己在外面再搭一层)、自助式声明式 API(非 Terraform 背景的团队直接写 HCL 有门槛)。这几个需求叠加在一起,已经超出了”规范化 Terraform 使用”能覆盖的范围,值得投入建一个真正的控制平面。
如果你需要的话,我可以把这个设计整理成一份更正式的架构文档(包含组件图、数据流时序图、API 规范),或者针对某一层(比如多租户的云账号隔离方案、或者成本聚合的具体实现)再深入展开细节设计。
