Crossplane vs Terraform:用 K8s 管 cloud 资源?

起因

cloud 资源(RDS / S3 / VPC)管理工具:

  • Terraform:HCL,最广泛,但状态文件 / drift 问题多
  • Pulumi:用 TS/Python 写
  • Crossplane:K8s controller,cloud 资源当 CR 管

最近用 Crossplane 一个项目,下面对比经验。

Terraform 简单回顾

resource "aws_db_instance" "main" {
    identifier = "myapp-db"
    engine = "postgres"
    instance_class = "db.t3.medium"
    allocated_storage = 100
    username = "admin"
    password = var.db_password
}
terraform plan
terraform apply
  • .tfstate 文件存当前资源映射
  • 多人协作要 remote state(S3 + DynamoDB lock)
  • drift 检测靠 terraform plan

Crossplane 思路

cloud 资源是 K8s CRD。kubectl apply 创建 cloud 资源。

# 装 Crossplane
helm install crossplane crossplane-stable/crossplane -n crossplane-system

# 装 AWS provider
kubectl apply -f - <<EOF
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws
spec:
  package: xpkg.upbound.io/upbound/provider-aws:v1.0.0
EOF

创建 RDS

apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
metadata:
  name: myapp-db
spec:
  forProvider:
    region: us-east-1
    engine: postgres
    engineVersion: "16"
    instanceClass: db.t3.medium
    allocatedStorage: 100
    username: admin
    passwordSecretRef:
      name: db-pass
      key: password
      namespace: default
kubectl apply -f rds.yaml
# Crossplane controller 调用 AWS API 创建 RDS

cluster 里看:

kubectl get instance.rds.aws.upbound.io
NAME       SYNCED   READY   ...
myapp-db   True     True

composition (高层抽象)

写一个 "AppDatabase" abstraction,dev 不用写 50 行 RDS yaml:

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: appdatabases.example.com
spec:
  group: example.com
  names:
    kind: AppDatabase
    plural: appdatabases
  versions:
    - name: v1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                size:
                  type: string
                  enum: [small, medium, large]
                env:
                  type: string
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: appdatabase-aws
spec:
  compositeTypeRef:
    apiVersion: example.com/v1
    kind: AppDatabase
  resources:
    - name: rds-instance
      base:
        apiVersion: rds.aws.upbound.io/v1beta1
        kind: Instance
        spec:
          forProvider:
            engine: postgres
            engineVersion: "16"
      patches:
        - fromFieldPath: spec.size
          toFieldPath: spec.forProvider.instanceClass
          transforms:
            - type: map
              map:
                small: db.t3.small
                medium: db.t3.medium
                large: db.r6g.xlarge

dev 写:

apiVersion: example.com/v1
kind: AppDatabase
metadata:
  name: my-app-db
spec:
  size: medium
  env: prod

→ Crossplane 自动创建 RDS + 关联资源。
平台团队 control 实际 cloud impl,dev 用简单接口。

对比

Terraform Crossplane
状态存储 tfstate file k8s etcd
语言 HCL YAML + composition
Drift 检测 terraform plan 主动 controller 持续 reconcile
自愈 是(detect drift 自动修)
多人协作 state lock k8s 原生 RBAC
学习曲线 高(要懂 K8s)
生态 极大
GitOps 需 Atlantis 等 原生(kubectl apply)

优势:自愈

Crossplane controller 每 N 分钟比 cluster CR 与实际 cloud 资源:

desired (yaml): RDS storage = 100 GB
actual (AWS):   storage = 200 GB (手动改了)
                    ↓
Crossplane:     调 API 改回 100 GB

terraform 不主动 reconcile,要手动 apply 才修。

不想 reconcile 某字段:

spec:
  managementPolicies: [Observe]    # 只读不改

或者 ignoreFields

优势:GitOps 一致

ArgoCD 同步 Crossplane CR → cluster apply → Crossplane 调 cloud API。
整条链 git → cluster → cloud 都声明式。

Terraform 配 ArgoCD 不容易(Terraform 是命令式 apply)。

缺点:复杂

  • composition 写起来累(patches / transforms)
  • debug 调试链长(CR → composition → managed resource → cloud API)
  • provider 质量参差(aws 强,azure / gcp 较新)
  • 没 terraform 那种 module 生态

缺点:要 K8s

Crossplane 跑在 K8s cluster 里。
要管 cloud 资源 → 必须先有 K8s cluster(鸡生蛋问题)。

我们方案:一个 "management cluster"(小 EKS)跑 Crossplane → 它管
其它 cluster + cloud 资源。

适合的场景

  • 已经深度 K8s
  • 多团队 self-service(dev 写 yaml,平台控制 composition)
  • ArgoCD 已用 → 想统一 GitOps
  • 容忍 K8s 复杂度

不适合:
- 单 cloud 资源 / 简单项目 → Terraform 够
- 团队不会 K8s
- 需要快速 prototype

与 Pulumi 对比

Terraform Pulumi Crossplane
语言 HCL TS/Python/Go YAML
真正编程
state tfstate own backend k8s etcd
多人 locking locking k8s
学习 中 (语言+SDK)

Pulumi 是"真编程语言写基础设施"。
Crossplane 是"K8s 思维管基础设施"。
Terraform 是"DSL 描述基础设施"。

真实 case

某客户多 cluster + 多 cloud 资源:

  • Terraform:3 个团队各自有 tfstate,conflict / drift 频发
  • 改 Crossplane:
  • 平台团队建 AppDatabase / AppQueue / AppBucket 等 abstraction
  • 业务团队 yaml 申请:kind: AppDatabase, size: medium
  • Crossplane 创建 + 自愈
  • ArgoCD 跟踪

效果:

  • 业务 dev 不学 RDS 细节
  • 资源命名 / tag 强制规范(composition 模板控制)
  • drift 自动修
  • 一切都在 ArgoCD UI 可见

挑战:
- composition 写起来痛苦(YAML 模板表达力差)
- provider bug 偶尔(aws provider 几个版本 ec2 有问题)

与 ACK (AWS Controllers for K8s)

ACK 是 AWS 官方出的 K8s controller for AWS 资源。
跟 Crossplane provider-aws 重叠。

Crossplane ACK
Composition
多 cloud AWS only
抽象
稳定 高(AWS 维护)

如果只 AWS + 不要 composition → ACK。
多 cloud / 要 abstraction → Crossplane。

踩过的坑

  1. YAML 长:1 个 RDS 的 yaml 100 行。composition 抽象后 dev 写 5 行,
    但 platform team 写 composition 累。

  2. provider 升级 breaking:provider-aws v1 → v2 schema 变 → 所有
    CR 要改。锁 provider 版本 + 计划升级。

  3. delete 危险:删 CR 默认 delete cloud 资源。deletionPolicy: Orphan 保留 cloud 资源仅删 CR。

  4. 多 region:每 region 一个 ProviderConfig。CR 用
    providerConfigRef 指。

  5. state recovery:万一 etcd 丢 → cloud 资源仍在但 cluster 不知道。
    crossplane beta 有 import 功能。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。