Memastikan manifest dan deployment aman sebelum sampai ke produksi: validasi manifest dengan linting dan policy OPA/Kyverno, dry-run testing dengan flux diff, preview environments berbasis PR, integration testing pasca-deploy, hingga chaos engineering untuk menguji ketahanan klaster.

Di episode 27 kalian sudah membangun pipeline CI/CD yang mengalir otomatis dari commit kode sampai deployment melalui Git. Kini perubahan bisa sampai ke produksi dengan kecepatan tinggi — yang berarti kesalahan juga bisa sampai ke produksi dengan kecepatan yang sama. Pertanyaan yang muncul adalah: bagaimana memastikan kualitas sebelum perubahan menyentuh klaster nyata?
Kecepatan tanpa jaring pengaman adalah resep insiden. Deployment yang berjalan mulus selama berbulan-bulan bisa tiba-tiba merusak produksi karena satu manifest yang salah skema, satu policy yang dilanggar, atau satu service yang lupa dimigrasi. Testing di dunia GitOps tidak hanya tentang menguji aplikasi — ia tentang menguji manifest, proses deployment, dan ketahanan klaster itu sendiri.
Pada episode ini kita akan membangun strategi testing berlapis untuk stack Flux: validasi manifest dengan linting dan policy, dry-run testing dengan flux diff, preview environments berbasis PR, integration testing pasca-deploy, dan chaos engineering untuk membuktikan bahwa klaster bisa bertahan dari kegagalan.
Kesalahan paling dasar dan paling sering terjadi adalah YAML yang tidak valid — indentasi salah, tab di tengah spasi, atau struktur yang rusak. YAML yang rusak akan membuat seluruh render gagal. Linting adalah jaring pertama yang menangkapnya. yamllint memeriksa sintaks dan aturan gaya:
yamllint clusters/ apps/Jalankan linting di setiap pull request sebelum manifest dibiarkan menembus pipeline. Ini murah, cepat, dan mencegah sejumlah besar masalah sepele di tahap berikutnya.
YAML yang valid belum tentu valid sebagai manifest Kubernetes. Skema objek berbeda antar versi API, dan salah ketik di field bisa membuat objek ditolak atau dibuat dengan perilaku tak terduga. kubeconform memvalidasi manifest terhadap skema resmi Kubernetes:
kubeconform -strict -summary \
-schema-location default \
clusters/ apps/Validasi skema menangkap masalah seperti versi API yang sudah tidak berlaku atau field yang salah nama. Untuk memastikan Flux dan CRD-nya juga valid, tambahkan skema khusus untuk custom resource Flux.
Tip
Untuk melihat hasil render manifest tanpa menerapkan apa pun, gunakan flux build yang menggabungkan Kustomize dan mengambil artifact source: flux build kustomization apps --path ./apps --kustomization-file ./clusters/production/apps.yaml. Output-nya bisa disalurkan langsung ke validator skema.
Validasi skema hanya memeriksa struktur, bukan kebijakan. Kebijakan seperti "semua container wajib punya resource limits" atau "image tidak boleh berasal dari registry tidak dikenal" butuh mesin policy. Dua tool yang umum:
ClusterPolicy. Cocok jika ingin policy ditulis dengan YAML sederhana dan dijalankan sebagai admission controller di klaster.Contoh kebijakan Kyverno untuk mewajibkan resource limits:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resources
spec:
validationFailureAction: Enforce
rules:
- name: require-limits
match:
any:
- resources:
kinds:
- Deployment
validate:
message: "Container wajib memiliki resource limits"
pattern:
spec:
template:
spec:
containers:
- resources:
limits:
cpu: "?*"Dengan validationFailureAction: Enforce, deployment yang melanggar ditolak sebelum masuk ke klaster. Jalankan policy yang sama di CI (misal dengan kyverno test) dan di klaster sebagai admission controller untuk lapisan ganda.
Sebelum perubahan diterapkan, kita perlu tahu persis apa yang akan berubah di klaster. flux diff memperlihatkan perbedaan antara manifest di Git dan kondisi klaster saat ini, tanpa menerapkan apa pun:
flux diff kustomization apps \
--path ./apps \
--kustomization-file ./clusters/production/apps.yamlflux diff menandai objek yang akan dibuat, diubah, atau dihapus. Ini adalah alat utama untuk analisis dampak sebelum pull request di-merge.
Lapisan kedua dari dry-run adalah meminta klaster menghitung hasilnya secara server-side. kubectl apply --dry-run=server mengirimkan manifest ke API server yang melakukan validasi skema dan webhook admission tanpa menyimpan perubahan:
kubectl apply --dry-run=server -f rendered-manifest.yamlServer-side dry run menangkap masalah yang hanya bisa diketahui server — seperti konflik dengan resource yang ada, webhook admission yang menolak, atau quota yang terlampaui. Jalankan setelah flux build menghasilkan manifest final.
Kombinasikan kedua dry-run untuk analisis dampak yang lengkap:
flux build untuk menghasilkan manifest final dari Git.flux diff untuk melihat perbedaan terhadap kondisi klaster.kubectl apply --dry-run=server untuk validasi server.Analisis dampak yang terdokumentasi juga membantu tim review: bukti bahwa perubahan yang diusulkan sudah diverifikasi, bukan sekadar klaim.
Warning
Perhatikan objek yang akan dihapus saat diff. Penghapusan resource (misal Namespace atau CRD) bisa menyebabkan data hilang. Sebelum menyetujui PR, pastikan setiap deletion memang disengaja dan sudah dicatat.
Preview environment adalah klaster atau namespace sementara yang dibuat untuk setiap pull request — tempat perubahan diuji dalam kondisi nyata sebelum di-merge. Alur yang umum:
Kuncinya adalah namespace unik per PR, sehingga beberapa PR bisa diuji bersamaan tanpa konflik.
Untuk skala yang lebih besar, preview bisa berupa klaster ephemeral penuh — dibuat otomatis saat PR, dihancurkan saat PR selesai. Pendekatan ini paling mendekati kondisi produksi nyata, termasuk operator dan policy yang terpasang. Namun biayanya lebih tinggi dan waktu tunggunya lebih lama, jadi pakailah secara bijak:
Preview environment yang tidak pernah dibersihkan akan menumpuk resource dan biaya. Otomasi pembersihan harus menjadi bagian dari workflow sejak awal:
name: cleanup-preview
on:
pull_request:
types: [closed]
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
flux delete kustomization preview-${{ github.event.number }} \
--silent --force || true
kubectl delete namespace preview-${{ github.event.pull_request.number }} \
--ignore-not-foundPerhatikan penggunaan --force agar Flux menghapus resource turunan yang mengikutinya. Pembersihan otomatis menjaga klaster tetap rapi tanpa bergantung pada disiplin tim.
Deployment sukses bukan berarti aplikasi berfungsi. Integration testing pasca-deploy memverifikasi bahwa aplikasi yang baru di-deploy benar-benar bekerja bersama dependensinya. Mulai dengan menunggu kondisi Ready secara eksplisit:
kubectl wait --for=condition=Ready pod \
-l app.kubernetes.io/name=checkout --timeout=120sKemudian verifikasi integrasi nyata — panggil endpoint, cek koneksi database, dan pastikan service routing bekerja.
Smoke test adalah pengujian cepat yang memastikan layanan utama berfungsi setelah deployment — bukan pengujian menyeluruh, melainkan alarm awal. Contoh smoke test sederhana:
curl -sf http://checkout.apps/healthz && echo "healthy"Jika smoke test gagal, pipeline menandai deployment bermasalah dan memicu rollback atau investigasi. Kecepatan adalah prioritas: smoke test harus selesai dalam hitungan detik agar bisa dijalankan di setiap deployment.
End-to-end (E2E) test menjalankan skenario dari perspektif pengguna akhir: login, checkout, dan alur lengkap melintasi banyak service. Tool seperti k6 untuk performance atau Playwright/Cypress untuk UI berjalan setelah deployment selesai dan smoke test lolos. E2E adalah lapisan paling mahal — jalankan di preview environment atau staging, bukan di setiap deployment produksi.
Tip
Bangun tangga pengujian berjenjang: lint dan validasi skema di setiap commit, flux diff dan server-side dry run di setiap PR, smoke test di setiap deployment, dan E2E lengkap di staging. Semakin mahal pengujian, semakin jarang dijalankan — tetapi pastikan setiap lapisan benar-benar menahan masalah di levelnya.
Chaos engineering adalah ujian ketahanan yang disengaja: memecahkan sesuatu di lingkungan terkontrol untuk membuktikan sistem bisa bertahan. Tujuannya bukan merusak produksi, melainkan menemukan kelemahan sebelum ditemukan oleh insiden nyata. Contoh injeksi kegagalan yang sederhana dan aman:
kubectl delete pod -l app=checkout --wait=falseFlux seharusnya memulihkan ReplicaSet ke jumlah yang diinginkan. Uji juga injeksi yang lebih kompleks: matikan node, ganggu jaringan antar service, atau buat registry tidak bisa diakses. Tool seperti Litmus atau Chaos Mesh mengotomasi injeksi ini dengan skenario yang bisa dijadwalkan.
Setelah kegagalan di-injeksi, bagian penting berikutnya adalah memverifikasi pemulihan — termasuk peran Flux di dalamnya. Pertanyaan yang dijawab: apakah Flux benar-benar memulihkan state ke desired state? Uji pemulihan yang relevan dengan GitOps:
kubectl delete deployment checkout -n apps
flux reconcile kustomization apps
kubectl get deployment checkout -n appsHasil chaos engineering harus menjadi metrik, bukan anekdot. Catat setiap eksperimen, dampaknya, dan apakah sistem pulih dalam waktu yang diharapkan. Ketahanan yang tervalidasi memberi kepercayaan untuk men-deploy lebih cepat: kita tahu batas sistem, bukan menebaknya.
Mulailah dengan chaos di staging, perluas perlahan ke produksi dengan skenario yang dampaknya terbatas (misal menghapus satu Pod di lingkungan non-kritis), dan selalu sediakan cara untuk menghentikan eksperimen dengan cepat.
Important
Chaos engineering di lingkungan produksi harus dibatasi: gunakan blast radius yang kecil, jadwalkan di jam sepi, dan sediakan prosedur abort. Nilai chaos bukan pada kerusakannya, melainkan pada bukti bahwa sistem — dan Flux di dalamnya — pulih sesuai harapan.
Pada episode 28 ini kalian telah membangun strategi testing berlapis untuk stack Flux: validasi manifest dengan yamllint, kubeconform, dan policy OPA/Kyverno, dry-run testing dengan flux diff dan server-side dry run untuk analisis dampak, preview environments berbasis PR dengan otomasi pembersihan, integration testing pasca-deploy dengan smoke dan end-to-end test, serta chaos engineering untuk memvalidasi ketahanan dan pemulihan klaster.
Inti yang harus dibawa pulang:
flux diff dan dry-run adalah jaring pengaman PR — mereka memperlihatkan dampak nyata tanpa mengubah klaster.Sekarang kode, manifest, dan klaster kalian teruji. Namun ada satu lapisan yang belum masuk ke dalam Git sepenuhnya: infrastruktur itu sendiri. Di episode 29 selanjutnya kita akan membahas Infrastructure as Code dengan Terraform — mengelola klaster dan infrastruktur dengan Terraform, integrasi provider Flux dan bootstrap via Terraform, lapisan-lapisan infrastruktur, serta GitOps untuk infrastruktur dengan Crossplane, Terraform Controller, dan Atlantis. Pastikan tetap semangat!