起因
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。
踩过的坑
-
YAML 长:1 个 RDS 的 yaml 100 行。composition 抽象后 dev 写 5 行,
但 platform team 写 composition 累。 -
provider 升级 breaking:provider-aws v1 → v2 schema 变 → 所有
CR 要改。锁 provider 版本 + 计划升级。 -
delete 危险:删 CR 默认 delete cloud 资源。
deletionPolicy: Orphan保留 cloud 资源仅删 CR。 -
多 region:每 region 一个 ProviderConfig。CR 用
providerConfigRef指。 -
state recovery:万一 etcd 丢 → cloud 资源仍在但 cluster 不知道。
crossplane beta有 import 功能。
登录后参与评论。