IaC — Crossplane
Architecture
platform-gitops / management cluster Cloud Providers
──────────────────────────────────────────────────────────────────────
crossplane/providers/ → Provider CRDs installed GCP / AWS / Azure / IBM
crossplane/xrds/ → XRD: XGKECluster registered (defines the API)
crossplane/compositions/ → Composition: gke-cluster-gcp (implements the API)
<domain>-gitops / management cluster Cloud
──────────────────────────────────────────────────────────────────────
crossplane/claims/prod/gke-main.yaml
→ Claim: GKECluster in payments-prod-infra
→ Composite (XR) created by Crossplane
→ GKE cluster provisioned in GCP
Infra Namespace
One namespace per domain per env, separate from application namespaces:
apiVersion: v1
kind: Namespace
metadata:
name: payments-prod-infra
labels:
project: payments
env: prod
purpose: infra
team: team-payments
backstage.io/domain: payments
backstage.io/managed-by: crossplane
argocd/app-set: crossplane-payments
Claim Example
# payments-gitops/crossplane/claims/prod/cloudsql-main.yaml
apiVersion: platform.myorg.io/v1alpha1
kind: CloudSQLInstance
metadata:
name: cloudsql-main # {resourceType}-{name}
namespace: payments-prod-infra # {domain}-{env}-infra
labels:
project: payments
env: prod
resource-type: cloudsql
provider: gcp
team: team-payments
backstage.io/system: gateway
backstage.io/resource: gcp-payments-prod-cloudsql-main
argocd/app: crossplane-payments-prod-cloudsql-main
argocd/app-set: crossplane-payments
annotations:
platform.myorg/backstage-entity: gcp-payments-prod-cloudsql-main
platform.myorg/ownership-level: system
spec:
parameters:
domain: payments
env: prod
project: payments-prod
location: us-central1
engine: POSTGRES_15
tier: db-custom-2-7680
availabilityType: REGIONAL
backupRetentionDays: 30
deletionPolicy: Orphan # never auto-delete prod resources
writeConnectionSecretToRef:
name: gcp-payments-prod-cloudsql-main-conn
namespace: payments-prod-infra
compositionSelector:
matchLabels:
provider: gcp
resource-type: cloudsql
Ownership Levels
| Level | Claim owns | Use case |
|---|---|---|
domain | backstage.io/domain only | Cluster, VPC, KMS — shared by all systems |
system | backstage.io/system | Shared DB, message bus — shared within a system |
component | backstage.io/system + Component dependsOn | Per-service queue, cache |
Supported Providers and Resource Types
| Type slug | Backstage spec.type | GCP | AWS | Azure | IBM |
|---|---|---|---|---|---|
gke/eks/aks/iks | kubernetes-cluster | ✅ | ✅ | ✅ | ✅ |
cloudsql/rds/postgres/cosmos | database | ✅ | ✅ | ✅ | ✅ |
pubsub/sqs/servicebus/eventstreams | message-queue | ✅ | ✅ | ✅ | ✅ |
gcs/s3/blobstorage/cos | object-storage | ✅ | ✅ | ✅ | ✅ |
memorystore/elasticache/redis | cache | ✅ | ✅ | ✅ | — |
bigquery/dynamodb | data-store | ✅ | ✅ | — | — |
artifact-registry/ecr/acr | container-registry | ✅ | ✅ | ✅ | — |
secretmanager/keyvault/secrets-manager | secret-store | ✅ | ✅ | ✅ | ✅ |
Provider Setup
# platform-gitops/crossplane/providers/provider-gcp.yaml
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-gcp
annotations:
argocd.argoproj.io/sync-wave: "-10" # before Claims
spec:
package: xpkg.upbound.io/upbound/provider-gcp:v0.41.0
---
apiVersion: gcp.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: gcp-provider-config
spec:
projectID: myorg-platform
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: gcp-credentials
key: credentials.json
Sync Wave Order
Wave -10: Providers + XRDs + Compositions → crossplane-platform AppSet
Wave 0: Claims → crossplane-<domain> AppSets
Wave 10: App workloads (optional) → domain ApplicationSets
Crossplane vs Terraform
| Concern | Terraform | Crossplane |
|---|---|---|
| Resource definition | .tf files + modules | XRD + Composition |
| Resource instance | terraform apply pipeline | Claim (Kubernetes object) |
| State | .tfstate in S3/GCS | etcd (Kubernetes) |
| Reconciliation | Pipeline on push | Continuous controller loop |
| Drift correction | terraform plan in CI | Crossplane selfHeal: true |
| Secret output | Terraform output | Kubernetes Secret in infra namespace |