DevOps & Cloud

Crossplane: Infrastructure as Code dari Kubernetes

GRATIS

Kuasai Crossplane untuk mengelola infrastruktur cloud dari Kubernetes — providers, compositions, XRDs, claims, provider config, dan GitOps integration

1. Apa itu Crossplane?

Crossplane adalah open-source Kubernetes add-on yang memungkinkan Anda mengelola infrastruktur cloud (database, cluster, storage, networking) menggunakan Kubernetes Custom Resource Definitions (CRDs). Dengan Crossplane, infrastruktur dikelola dengan cara yang sama seperti aplikasi Kubernetes — deklaratif, version-controlled, dan GitOps-friendly.

Arsitektur Crossplane
👤
Platform Team
Definisikan XRD &
Composition (API)
→ Define →
📝
App Team
Submit Claim
(simplified API)
→ Claim →
🔄
Crossplane
Compose & Reconcile
Managed Resources
→ Provision →
☁️
Cloud Provider
AWS, GCP, Azure
Actual infrastructure

1.1 Crossplane vs Terraform

FiturCrossplaneTerraform
StateCRD di Kubernetes (etcd)State file (.tfstate)
ReconciliationContinuous (watch loop)Hanya saat apply
AbstractionXRD + CompositionModules
GitOpsNative (ArgoCD)Butuh wrapper
Drift DetectionOtomatisTerraform plan

2. Instalasi & Setup

Terminal — Install Crossplane
# Install Crossplane menggunakan Helm
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update

# Install Crossplane
helm install crossplane crossplane-stable/crossplane \
  --namespace crossplane-system \
  --create-namespace \
  --wait

# Verifikasi instalasi
kubectl get pods -n crossplane-system

# Install Crossplane CLI (kubectl crossplane)
curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | sh
sudo mv crossplane /usr/local/bin/

# Install provider untuk AWS
kubectl crossplane install provider crossplane/provider-aws:v0.44.0

# Install provider untuk AWS (terbaru)
kubectl crossplane install provider xpkg.upbound.io/crossplane-contrib/provider-aws:v1.1.0

# Cek status provider
kubectl get providers
# NAME                          INSTALLED   HEALTHY   AGE
# crossplane-provider-aws       True        True      2m

3. Providers

Provider adalah plugin yang memungkinkan Crossplane berkomunikasi dengan cloud provider. Setiap provider mendefinisikan Managed Resources (MR) — representasi CRD dari resource cloud yang sebenarnya.

Install & configure providers
# Install provider AWS
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-s3
spec:
  package: xpkg.upbound.io/crossplane-contrib/provider-aws-s3:v1.1.0
  # Runtime config untuk mengatur resource limits
  runtimeConfigRef:
    name: provider-aws-runtime

---
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
  name: provider-aws-runtime
spec:
  deployment:
    spec:
      replicas: 1
      template:
        spec:
          containers:
            - name: package-runtime
              resources:
                limits:
                  cpu: 500m
                  memory: 512Mi
                requests:
                  cpu: 100m
                  memory: 256Mi

# Install provider AWS RDS
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-rds
spec:
  package: xpkg.upbound.io/crossplane-contrib/provider-aws-rds:v1.1.0

# Install provider Kubernetes (untuk mengelola K8s resources)
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-kubernetes
spec:
  package: xpkg.upbound.io/crossplane-contrib/provider-kubernetes:v0.14.0

# Install provider Helm
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-helm
spec:
  package: xpkg.upbound.io/crossplane-contrib/provider-helm:v0.18.0

# Cek semua providers
kubectl get providers

4. XRDs (Composite Resource Definitions)

XRD mendefinisikan API baru yang disederhanakan untuk application teams. Platform team membuat XRD yang mengabstraksi kompleksitas cloud resource menjadi API yang lebih sederhana.

xrd-database.yaml — Definisikan API untuk database
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xpostgresqlinstances.database.example.com
spec:
  group: database.example.com
  names:
    kind: XPostgreSQLInstance
    plural: xpostgresqlinstances
  claimNames:
    kind: PostgreSQLInstance
    plural: postgresqlinstances
  connectionSecretKeys:
    - host
    - port
    - username
    - password
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                parameters:
                  type: object
                  description: "Parameter yang bisa diatur oleh app team"
                  properties:
                    storageGB:
                      type: integer
                      description: "Ukuran storage dalam GB"
                      minimum: 20
                      maximum: 1000
                      default: 50
                    engine:
                      type: string
                      enum: ["postgres"]
                      default: "postgres"
                    engineVersion:
                      type: string
                      enum: ["14", "15", "16"]
                      default: "16"
                    multiAZ:
                      type: boolean
                      default: false
                      description: "Enable Multi-AZ untuk high availability"
                    backupRetentionDays:
                      type: integer
                      minimum: 0
                      maximum: 35
                      default: 7
                  required:
                    - storageGB
              required:
                - parameters
            status:
              type: object
              properties:
                endpoint:
                  type: string
                port:
                  type: integer
                instanceId:
                  type: string
💡 XRD sebagai Internal API

XRD adalah API internal platform Anda. Application team tidak perlu tahu apakah database menggunakan AWS RDS, Google Cloud SQL, atau self-hosted PostgreSQL. Mereka hanya perlu menspesifikasi storageGB dan engineVersion. Platform team yang memutuskan implementasi di belakangnya.

5. Compositions

Composition mendefinisikan bagaimana XRD di-mapping ke managed resources yang sebenarnya. Ini adalah template yang menggabungkan beberapa cloud resource menjadi satu unit logis.

composition-database.yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: postgresql-aws
  labels:
    provider: aws
spec:
  compositeTypeRef:
    apiVersion: database.example.com/v1alpha1
    kind: XPostgreSQLInstance
  writeConnectionSecretsToNamespace: crossplane-system
  patchSets:
    - name: common
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: metadata.labels
          toFieldPath: metadata.labels

  resources:
    # Resource 1: RDS Subnet Group
    - name: subnetGroup
      base:
        apiVersion: rds.aws.crossplane.io/v1alpha1
        kind: DBSubnetGroup
        spec:
          forProvider:
            description: "Crossplane managed subnet group"
            subnetIds:
              - subnet-0123456789abcdef0
              - subnet-0123456789abcdef1
          providerConfigRef:
            name: aws-provider
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: metadata.uid
          toFieldPath: spec.forProvider.tags
          transforms:
            - type: string
              string:
                fmt: "crossplane-%s"
          policy:
            mergeOptions:
              appendSlice: true

    # Resource 2: RDS Instance
    - name: rdsInstance
      base:
        apiVersion: rds.aws.crossplane.io/v1alpha1
        kind: DBInstance
        spec:
          forProvider:
            dbInstanceClass: db.t3.medium
            engine: postgres
            publiclyAccessible: false
            autoMinorVersionUpgrade: true
            storageEncrypted: true
            multiAZ: false
            masterUsername: admin
          providerConfigRef:
            name: aws-provider
          writeConnectionSecretToRef:
            namespace: crossplane-system
      patches:
        - type: CombineFromComposite
          combine:
            variables:
              - fromFieldPath: metadata.uid
            strategy: string
            string:
              fmt: "crossplane-%s"
          toFieldPath: metadata.annotations[crossplane.io/external-name]
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.storageGB
          toFieldPath: spec.forProvider.allocatedStorage
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.engineVersion
          toFieldPath: spec.forProvider.engineVersion
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.multiAZ
          toFieldPath: spec.forProvider.multiAZ
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.backupRetentionDays
          toFieldPath: spec.forProvider.backupRetentionPeriod
      connectionDetails:
        - name: host
          fromFieldPath: status.atProvider.endpoint.address
        - name: port
          fromFieldPath: status.atProvider.endpoint.port
          type: FromFieldPath
        - name: username
          fromConnectionSecretKey: username
        - name: password
          fromConnectionSecretKey: password

6. Claims

Claims adalah cara application team meminta resource. Claims adalah namespace-scoped, berbeda dengan Composite Resource yang cluster-scoped.

claim-database.yaml — App team request
# Application team hanya perlu submit claim ini
apiVersion: database.example.com/v1alpha1
kind: PostgreSQLInstance
metadata:
  name: my-app-db
  namespace: app-team-a
spec:
  parameters:
    storageGB: 100
    engineVersion: "16"
    multiAZ: true
    backupRetentionDays: 14
  compositionSelector:
    matchLabels:
      provider: aws  # Pilih AWS implementation
  writeConnectionSecretToRef:
    name: my-app-db-connection

---
# Cek status claim
# kubectl get postgresqlinstances -n app-team-a
# NAME        READY   CONNECTION-SECRET        AGE
# my-app-db   True    my-app-db-connection     5m

# Connection secret berisi endpoint, port, username, password
# kubectl get secret my-app-db-connection -n app-team-a -o yaml

# Gunakan connection secret di Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: app-team-a
spec:
  template:
    spec:
      containers:
        - name: my-app
          image: my-app:latest
          env:
            - name: DB_HOST
              valueFrom:
                secretKeyRef:
                  name: my-app-db-connection
                  key: host
            - name: DB_PORT
              valueFrom:
                secretKeyRef:
                  name: my-app-db-connection
                  key: port
            - name: DB_USERNAME
              valueFrom:
                secretKeyRef:
                  name: my-app-db-connection
                  key: username
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: my-app-db-connection
                  key: password

7. Provider Config & Secrets

provider-config-aws.yaml
# Simpan AWS credentials di Kubernetes Secret
apiVersion: v1
kind: Secret
metadata:
  name: aws-credentials
  namespace: crossplane-system
type: Opaque
stringData:
  credentials: |
    [default]
    aws_access_key_id = AKIAIOSFODNN7EXAMPLE
    aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

---
# ProviderConfig mengarahkan provider ke credentials
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: aws-provider
spec:
  credentials:
    source: Secret
    secretRef:
      name: aws-credentials
      namespace: crossplane-system
      key: credentials

# Alternatif: IRSA (IAM Roles for Service Accounts) — lebih aman
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: aws-provider-irsa
spec:
  credentials:
    source: InjectedIdentity  # Gunakan workload identity

---
# Multi-region: buat ProviderConfig per region
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: aws-us-east-1
spec:
  credentials:
    source: InjectedIdentity
  region: us-east-1

apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: aws-ap-southeast-1
spec:
  credentials:
    source: InjectedIdentity
  region: ap-southeast-1

8. GitOps Integration

Crossplane bekerja sangat baik dengan GitOps karena semua konfigurasi adalah CRD yang bisa di-commit ke Git dan di-manage dengan ArgoCD.

ArgoCD + Crossplane integration
# Repository structure untuk GitOps dengan Crossplane
# gitops-repo/
# ├── providers/
# │   ├── aws-provider.yaml
# │   └── provider-config.yaml
# ├── xrd/
# │   ├── xrd-database.yaml
# │   ├── xrd-bucket.yaml
# │   └── xrd-cluster.yaml
# ├── compositions/
# │   ├── composition-db-aws.yaml
# │   └── composition-bucket-aws.yaml
# ├── claims/
# │   ├── dev/
# │   │   ├── app-database.yaml
# │   │   └── app-bucket.yaml
# │   └── prod/
# │       ├── app-database.yaml
# │       └── app-bucket.yaml
# └── argocd/
#     ├── app-of-apps.yaml
#     └── applications/
#         ├── providers.yaml
#         ├── xrd.yaml
#         └── claims-dev.yaml

# ArgoCD Application untuk providers
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: crossplane-providers
  namespace: argocd
spec:
  project: infrastructure
  source:
    repoURL: https://github.com/my-org/gitops-infra.git
    targetRevision: main
    path: providers
  destination:
    server: https://kubernetes.default.svc
    namespace: crossplane-system
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

# Perubahan infrastruktur = perubahan Git commit
# Developer mengubah storageGB dari 50 ke 100:
# 1. Edit claim-database.yaml di Git (ubah storageGB)
# 2. Commit & push
# 3. ArgoCD detect perubahan & sync ke cluster
# 4. Crossplane detect perubahan pada Claim
# 5. Crossplane reconcile: update RDS instance storage
# 6. Status Claim menjadi "Ready"
⚠️ Delete Policy

Saat menggunakan ArgoCD dengan Crossplane, perhatikan propagationPolicy saat menghapus resource. Jika ArgoCD menghapus Claim, Crossplane akan menghapus managed resources dan juga cloud resource yang sebenarnya. Pastikan Anda memiliki backup atau menggunakan deletionPolicy: Orphan untuk resource production.

9. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut:

Pertanyaan 1: Apa peran utama XRD (Composite Resource Definition) di Crossplane?

a) Mengelola credentials cloud provider
b) Mendefinisikan API baru yang disederhanakan untuk application team, mengabstraksi kompleksitas infrastruktur
c) Menginstal provider ke cluster
d) Mengelola RBAC Kubernetes

Pertanyaan 2: Apa yang membedakan Crossplane dari Terraform dalam hal state management?

a) Crossplane menggunakan file .tfstate yang sama
b) Crossplane menyimpan state sebagai CRD di Kubernetes etcd dan melakukan reconciliation secara continuous
c) Crossplane tidak menyimpan state
d) Crossplane menggunakan database eksternal untuk state

Pertanyaan 3: Apa fungsi Composition di Crossplane?

a) Menggabungkan beberapa Kubernetes cluster
b) Mendefinisikan mapping dari XRD ke managed resources — template bagaimana infrastruktur dibuat
c) Mengelola secrets untuk provider
d) Monitoring resource usage

Pertanyaan 4: Siapa yang menggunakan Claims di Crossplane?

a) Platform team untuk mendefinisikan infrastruktur
b) Application team untuk meminta resource infrastruktur yang dibutuhkan
c) Cloud provider untuk mengelola layanan
d) Security team untuk auditing

Pertanyaan 5: Mengapa Crossplane sangat cocok untuk GitOps?

a) Karena Crossplane menggunakan Git sebagai database
b) Karena semua konfigurasi Crossplane adalah Kubernetes CRDs yang bisa di-commit ke Git dan di-manage dengan ArgoCD
c) Karena Crossplane hanya bisa di-deploy dari Git
d) Karena Crossplane menggantikan Git
← Sebelumnya Istio Service Mesh Selanjutnya → OpenTofu: Terraform Alternative
🔍 Zoom
100%
🎨 Tema