Mengelola infrastruktur dengan cara yang sama seperti aplikasi: Terraform dengan GitOps, Crossplane sebagai IaC native Kubernetes, Cluster API untuk lifecycle cluster, dan pola full stack GitOps dari infrastruktur, platform, sampai aplikasi.

Di episode 28 sebelumnya kita mengatur agar banyak tenant hidup damai dalam satu platform. Namun ada celah besar yang belum kita tutup: bagaimana infrastruktur itu sendiri dibuat? Selama ini kita berasumsi cluster sudah ada — padahal di dunia nyata, cluster, VPC, database, dan bucket S3 juga harus dikelola, diubah, dan dilacak. Jika aplikasi dikelola GitOps tetapi infrastrukturnya dikerjakan manual lewat konsol cloud, maka sebenarnya kita hanya separuh GitOps.
Episode ini menutup celah tersebut. Kita membahas infrastructure GitOps — menerapkan prinsip yang sama (Git sebagai sumber kebenaran, declarative, auto-sync) pada lapisan yang berada di bawah aplikasi: Terraform, Crossplane, dan Cluster API. Tujuannya: seluruh stack dari cluster sampai aplikasi dikelola dari satu Git, satu pipeline, satu sumber kebenaran.
Infrastructure as Code (IaC) adalah prasyarat GitOps infrastruktur: jika infrastruktur tidak bisa dinyatakan sebagai kode, ia tidak bisa dikelola dari Git. Empat pendekatan utama:
| Pendekatan | Model | Peran ArgoCD |
|---|---|---|
| Terraform | IaC eksternal, state di backend | ArgoCD menjalankan workflow, bukan menerapkan |
| Crossplane | CRD di dalam cluster, reconcile kontinu | ArgoCD menerapkan CRD + claim secara langsung |
| Cluster API | Kubernetes-native untuk lifecycle cluster | ArgoCD mengelola CAPI resource dan add-on |
| External provisioners | Operator/controller pihak ketiga | ArgoCD menerapkan resource operator |
Perbedaan kunci: Terraform adalah pull-once (apply saat dijalankan), sedangkan Crossplane adalah reconcile-terus (seperti controller Kubernetes). Crossplane lebih cocok dengan mental model GitOps karena tidak ada step manual "terraform apply" — resource terus disesuaikan ke keadaan yang diinginkan.
Terraform tidak memahami reconciliation kontinu, jadi pola GitOps untuk Terraform biasanya adalah: workflow pipeline (episode 18). CI mendeteksi perubahan di repo infra/, menjalankan terraform plan, menunggu approval, lalu terraform apply:
jobs:
terraform:
steps:
- run: terraform init -backend-config=backend.tfvars
- run: terraform plan -out=tfplan
- run: terraform apply tfplanKarena state Terraform disimpan di luar Git (misalnya S3), Git bukan satu-satunya sumber kebenaran di sini — ini kelemahan struktural yang membuat banyak tim beralih ke Crossplane untuk hal-hal yang bisa di-reconcile terus-menerus. Terraform tetap ideal untuk resource yang tidak punya controller Kubernetes-native: VPC, IAM, DNS provider tertentu.
Crossplane menempatkan provider di dalam cluster yang bisa membuat resource cloud apa pun — S3 bucket, RDS, GKE cluster — sebagai CRD Kubernetes. Ini mengubah cloud provider menjadi "API yang dikelola oleh controller".
Provider adalah controller yang berbicara ke cloud API:
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
spec:
package: xpkg.upbound.io/upbound/provider-aws-s3:v1.30.0
---
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
name: aws-creds
namespace: crossplane-systemCrossplane memisahkan abstraksi dan implementasi lewat dua konsep:
PostgresDB, yang diwujudkan sebagai kombinasi RDS instance, security group, dan kredensial.apiVersion: platform.example.org/v1alpha1
kind: PostgresDB
metadata:
name: billing-db
namespace: tenant-billing
spec:
size: smallTenant cukup membuat claim; Crossplane mewujudkannya. Status claim bisa dipantau langsung: kubectl get postgresdb billing-db -n tenant-billing akan menunjukkan apakah claim sudah READY. Inilah analogi "self-service" untuk infrastruktur — pasangan sempurna dari pola tenant onboarding di episode 28.
Karena Crossplane resource adalah CRD biasa, ArgoCD mengelolanya tanpa plugin khusus. Application bisa langsung menargetkan claim, provider, dan composition:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform-database
namespace: argocd
spec:
project: platform
source:
repoURL: https://github.com/org/infra
path: crossplane/claims
destination:
server: https://kubernetes.default.svc
namespace: tenant-billingTip
Pisahkan lapisan mengelola Crossplane itu sendiri dari lapisan claim. Tim platform mengelola Provider, ProviderConfig, dan Composition (sebagai Application dengan project platform); tenant mengelola hanya claim mereka. Dengan begitu, tenant tidak bisa mengubah perilaku platform.
Cluster API (CAPI) membawa pola Kubernetes ke lifecycle cluster itu sendiri: Cluster dan MachineDeployment adalah CRD, dan controller mengangkat/menurunkan cluster sesuai keinginan.
Lifecycle cluster dikelola lewat resource CAPI: Cluster untuk kontrol plane, MachineDeployment untuk node pool, MachineHealthCheck untuk mengganti node yang rusak. Upgrade cluster = mengubah versi di MachineDeployment dan membiarkan controller melakukan rolling update — semuanya bisa di-declare di Git. Untuk melihat kondisi seluruh fleet: kubectl get clusters -A.
Setelah cluster lahir, isi dengan add-on. Pola umum: ArgoCD mengelola ApplicationSet dengan cluster generator (episode 11) yang men-deploy add-on ke semua cluster yang terdaftar:
spec:
generators:
- clusters: {}
template:
metadata:
name: 'addon-metrics-{{name}}'
spec:
project: platform
source:
repoURL: https://github.com/org/addons
path: metrics-server
destination:
server: '{{server}}'Kombinasi CAPI + ArgoCD menghasilkan self-healing fleet: CAPI menjaga jumlah cluster sesuai keinginan, ArgoCD menjaga isi tiap cluster sesuai Git. Hub-and-spoke dari episode 9 menjadi benar-benar otomatis — cluster baru muncul, langsung diregistrasi, langsung terisi.
Tujuan akhir adalah satu pipeline untuk seluruh tumpukan, dalam tiga lapisan:
| Lapisan | Contoh | Tools |
|---|---|---|
| Infrastruktur | VPC, cluster, database, bucket | Terraform / Crossplane / CAPI |
| Platform | Ingress, monitoring, ArgoCD, policy | ArgoCD + ApplicationSet |
| Aplikasi | Layanan bisnis | ArgoCD + App of Apps |
Koordinasi antar lapisan dilakukan lewat urutan dan dependensi — bukan menunggu manual. ApplicationSet untuk platform menunggu sampai cluster sehat (dideteksi CAPI), lalu add-on platform di-deploy; aplikasi menunggu platform siap. Dependency antar lapisan diekspresikan dengan sync waves (episode 7) atau pipeline yang memicu lapisan berikutnya hanya jika lapisan sebelumnya Healthy.
Warning
Hati-hati dengan siklus bootstrap. ArgoCD yang mengelola ArgoCD (self-managed) adalah pola yang valid (episode 6), tetapi butuh jalur manual darurat: jika ArgoCD hilang, kalian harus bisa mem-bootstrap ulang dari Git tanpa ArgoCD. Simpan dokumentasi dan skrip bootstrap di repo, dan uji di DR drill (episode 21).
Episode ini memperluas GitOps ke bawah: Terraform dengan pola workflow untuk resource non-Kubernetes, Crossplane sebagai IaC native Kubernetes dengan provider, composite resource, dan claim-based provisioning, Cluster API untuk lifecycle, upgrade, dan add-on management lintas cluster, serta pola full stack GitOps dengan tiga lapisan yang terkoordinasi.
Poin yang harus kalian bawa:
Infrastruktur tidak berjalan sendiri; ia hidup dalam ekosistem tool CI/CD yang lebih luas. Di episode 30 selanjutnya kita membahas ecosystem integration — Tekton, Jenkins dan Jenkins X, GitHub Actions, GitLab CI/CD, migrasi FluxCD, integrasi Terraform, policy engine, dan Backstage. Sampai jumpa di episode 30!