Membongkar teknik debugging Helm secara sistematis: mengenali pola kegagalan instalasi/upgrade, error rendering template, release yang stuck dan failed, hingga recovery dengan rollback dan cleanup manual, ditutup walkthrough diagnosis chart yang gagal dari awal hingga tuntas.

Setelah di episode 25 sebelumnya kita membahas bagaimana Helm berperan dalam arsitektur GitOps — Git menjadi source of truth, ArgoCD dan Flux merekonsiliasi cluster secara terus-menerus — pada episode kali ini kita turun lagi ke medan yang lebih dekat dengan keseharian: apa yang kalian lakukan saat release gagal? GitOps memang otomatis, tapi otomatisasi tidak membuat kegagalan hilang — ia hanya membuat kegagalan muncul lebih cepat dan lebih sering, lengkap dengan stack trace yang harus kita baca.
Fakta jujurnya: sebagian besar waktu engineer Helm dihabiskan bukan untuk menulis chart, melainkan untuk membedah mengapa sesuatu tidak berjalan. Deployment yang tampak berhasil padahal Pod-nya CrashLoopBackOff, upgrade yang menggantung di status pending-upgrade, template yang error dengan pesan yang membingungkan, atau release yang "sudah ada" padahal tidak terlihat di helm list. Tanpa metode debugging yang sistematis, semua ini menjadi tebak-tebakan yang menghabiskan jam kerja.
Di episode ini kita akan membedah pola-pola kegagalan Helm yang paling umum, mempelajari teknik debugging standar dan advanced, memahami cara memulihkan release yang stuck atau failed, lalu menutup dengan walkthrough lengkap: sebuah chart yang gagal kita bedah langkah demi langkah dari error pertama hingga akar masalahnya ditemukan.
Sebelum menyelami teknik, penting untuk mengenali keluarga masalah. Setiap masalah punya jejak khas, dan mengenali jejak ini mempersempit ruang diagnosis secara drastis.
helm install gagal di awal. Penyebab umum: chart tidak ditemukan di repo (salah nama/versi), malformed YAML pada manifest hasil render, atau resource yang sudah ada di cluster dengan nama yang sama. Gejalanya terlihat langsung di output helm install, biasanya berhenti sebelum muncul status release.
helm upgrade gagal di tengah jalan. Ini lebih berbahaya karena release bisa tertinggal dalam status transisi (pending-upgrade). Penyebab umum: nilai baru yang tidak valid (misal nama service yang diubah sehingga selector tidak cocok), resource yang tidak bisa di-update (biasanya karena field immutable seperti pada PVC atau selector Deployment), atau dependensi yang berubah. Kunci untuk memahami ini: selalu ingat bahwa Helm 3 melakukan three-way strategic merge patch — ia membandingkan kondisi lama, nilai baru, dan kondisi live cluster sekaligus.
Chart tidak bisa di-render sama sekali. Penyebab umum: fungsi template yang salah nama, variabel yang belum terdefinisi (misspelling seperti .Value vs .Values), type mismatch saat membandingkan nilai, atau blok if/range yang tidak seimbang. Pesan error Go template memang membingungkan pada awalnya, tapi pola template: mychart/templates/deployment.yaml:12:34: executing ... at <.Values.replicas>: can't evaluate field memberi tahu file, baris, kolom, dan ekspresi yang bermasalah — itu sudah setengah dari solusi.
Error klasik: Error: rendered manifests contain a resource that already exists. Ini terjadi saat resource yang akan dibuat sudah ada di cluster tapi tidak dimiliki release tersebut — misalnya kalian meng-install chart yang sama dua kali tanpa mengganti nama release, atau resource dibuat manual lalu Helm mencoba mengambil alih. Helm 3 tidak akan menimpa resource milik pihak lain.
Hook (yang kita bahas di episode 12) berjalan sebagai Job/Pod terpisah. Jika Job hook gagal — misalnya migration database error — instalasi/upgrade dianggap gagal meski resource utama berhasil dibuat. Gejalanya: release berstatus failed dengan keterangan hook, padahal Deployment-nya sendiri sehat.
Error: pods is forbidden: User "system:serviceaccount:default:default" cannot .... ServiceAccount yang dipakai Helm (biasanya default di namespace) tidak punya izin membuat resource. Ini masalah RBAC murni — baik karena kubeconfig yang salah, atau karena chart menuntut izin yang lebih luas. Pesan ini sering muncul di CI/CD ketika kredensial yang dipakai berbeda dari yang kalian gunakan di laptop.
Sekarang mari bangun kotak alat debugging kalian, dari yang paling cepat sampai yang paling dalam.
--dry-run dan --debugKeduanya adalah teman pertama saat mencurigai masalah rendering. helm template release chart me-render manifest ke stdout tanpa menyentuh cluster — sempurna untuk memeriksa YAML hasil render dengan mata kepala sendiri. Tambahkan --debug pada install/upgrade untuk melihat manifest yang dirender beserta perbandingan kondisi lama vs baru, plus detail koneksi ke cluster. Aturan praktis: jika hasil render sudah salah, cluster tidak akan pernah menyelamatkanmu.
helm template myapp ./my-chart --namespace default
# Set values dari beberapa file & lihat output lengkapnya
helm template myapp ./my-chart \
-f values-staging.yaml \
--debughelm get manifest dan helm get valuesSaat release sudah ter-install dan bermasalah, jangan menebak — lihat apa yang benar-benar ada. helm get manifest myapp menampilkan semua manifest yang diterapkan release tersebut (versi yang ter-deploy, bukan yang ada di Git). helm get values myapp menampilkan nilai konfigurasi efektif yang dipakai, lengkap dengan label yang menunjukkan asal setiap nilai (dari values.yaml, file override, atau --set). Ini jawaban instan untuk pertanyaan "kenapa replica-nya 1 padahal saya set 3?" — kemungkinan besar karena ada --set atau nilai default yang menimpa.
kubectl describe dan kubectl logsHelm hanya menyampaikan manifest; setelah itu Kubernetes yang mengeksekusi. Ketika resource-nya ada tapi tidak sehat, berpindahlah ke kubectl. kubectl describe pod <pod> membedah detail lifecycle pod, termasuk Events di bagian bawah yang menceritakan narasi kegagalan (ImagePullBackOff, CrashLoopBackOff, Probe failed). kubectl logs <pod> (dengan --previous untuk kontainer yang sudah restart) mengungkap error aplikasi itu sendiri.
kubectl describe pod myapp-7f9d8c5b6f-abcde
kubectl logs myapp-7f9d8c5b6f-abcde --previoushelm lintSebelum menyalahkan cluster, pastikan chartnya sendiri bersih. helm lint ./my-chart memeriksa struktur chart, validitas Chart.yaml, dan kebenaran template secara statis. Ia bukan pengganti tes sebenarnya — banyak bug hanya muncul saat rendering dengan nilai riil — tapi ia menangkap kelas kesalahan paling umum dengan cepat.
Teori saja tidak cukup. Mari kita bedah satu kasus nyata dari awal hingga tuntas.
Gejala: tim kalian menjalankan helm upgrade --install api ./api-chart -f values-prod.yaml dan mendapat error:
Error: UPGRADE FAILED: template: api-chart/templates/deployment.yaml:34:21:
executing "api-chart/templates/deployment.yaml" at <.Values.image.repository>:
can't evaluate field image in type interface {}Langkah 1 — baca pesan error dengan teliti. Pesan ini memberi kita: file (deployment.yaml), baris 34 kolom 21, dan ekspresi .Values.image.repository. Helm tidak bisa mengevaluasi .Values.image — artinya field image tidak ada di nilai yang dipakai. Jangan langsung menebak chart-nya rusak; lebih sering nilainya yang tidak ter-set.
Langkah 2 — periksa values efektif. Jalankan helm template api ./api-chart -f values-prod.yaml --debug untuk melihat output render, atau helm get values api jika release-nya sudah terlanjur ada. Mungkin ternyata file values-prod.yaml menaruh konfigurasi image di bawah api::
api:
image:
repository: ghcr.io/company/api
tag: "2.1.0"Sementara template-nya membaca .Values.image.repository (tanpa level api:). Template dan values tidak cocok.
Langkah 3 — verifikasi dengan template sederhana. Untuk memastikan, render chart dengan --set yang eksplisit: helm template api ./api-chart --set image.repository=ghcr.io/company/api --set image.tag=2.1.0. Jika render berhasil, akar masalah dipastikan: mismatch struktur values, bukan template yang rusak.
Langkah 4 — perbaiki di tempat yang benar. Karena ini GitOps, perbaikannya di Git: sesuaikan file values, atau — jika kalian mengontrol chart — pindahkan pembacaan template ke .Values.api.image. Commit, biarkan controller ArgoCD/Flux yang menerapkan.
Langkah 5 — verifikasi hasil. helm status api menunjukkan status deployed, kubectl get pods -l app.kubernetes.io/name=api menunjukkan Pod Running, dan kubectl logs bersih. Selesai.
Tip
Pesan error Go template selalu mengikuti pola template: <chart>/templates/<file>:<baris>:<kolom>. Ambil ketiga informasi itu lebih dulu, lalu cek baris tersebut di file template. Ini teknik yang membuat debugging template terasa jauh lebih cepat — lebih dari 80% error template terjawab hanya dengan membaca pesan error dengan teliti.
Kegagalan tidak selalu selesai dengan memperbaiki nilai. Kadang release-nya sendiri macet. Ini area yang paling sering membuat engineer panik — dan sebenarnya paling mudah ditangani jika kalian paham status release.
Release bisa menggantung di pending-install, pending-upgrade, atau pending-rollback — biasanya karena operasi gagal di tengah jalan (timeout hook, Job tidak selesai) dan Helm tidak sempat menuntaskan status. Jika release sudah "pending" selama berjam-jam, Helm menganggapnya rusak. Solusi klasiknya:
# Lihat status & riwayat release
helm status api
helm history api
# Coba rollback ke versi terakhir yang diketahui baik
helm rollback api <revision-terakhir-sehat>
# Jika rollback juga macet, lepaskan saja
helm uninstall api --keep-historyhelm list --all akan memperlihatkan release berstatus failed. Jangan di-uninstall dulu sebelum memeriksa kenapa ia gagal — sering kali status failed justru memberi informasi yang lebih kaya daripada deployed. Gunakan helm get manifest, helm history, dan helm status untuk membedah. Jika penyebabnya sudah jelas dan bisa diperbaiki, ulangi upgrade dengan nilai yang benar. Helm akan mencoba melanjutkan dari titik terakhir, dan sebagian besar kasus failed bisa diselamatkan tanpa uninstall.
Rollback adalah prosedur pemulihan tercepat dan paling aman. helm rollback api 12 mengembalikan release ke revisi 12. Perlu diingat: rollback bukan restore sempurna — ini operasi upgrade baru yang menerapkan manifest revisi lama terhadap kondisi live saat ini. Itu sebabnya rollback juga bisa gagal (misal resource telah dihapus secara manual). Gunakan helm history api untuk memilih revisi yang tepat, dan jangan lupa bahwa --wait --timeout bisa digunakan pada rollback agar tidak menggantung.
Terkadang release terlalu rusak untuk diselamatkan. Urutan aman:
helm uninstall api --keep-history — hapus resource tapi simpan riwayat untuk audit.kubectl delete untuk resource yang tersisa (helm menandainya dengan label app.kubernetes.io/managed-by: Helm dan helm.sh/release-name).Debugging tidak selalu tentang error — kadang tentang lambat. Tiga penyebab paling umum:
Chart dengan template ratusan baris dan values ribuan baris memperlambat rendering dan upgrade. Setiap template di-render ulang setiap operasi, dan fungsi lookup (yang kita bahas di episode 9) melakukan panggilan API Kubernetes — di dalam loop, satu operasi bisa memicu puluhan panggilan. Aturan praktis: jangan panggil lookup di dalam range atau include yang berulang; cache hasilnya di variabel.
Setiap dependency subchart menambah beban rendering. Chart dengan 20+ dependencies akan jauh lebih lambat daripada chart tunggal. Pertimbangkan memisahkannya menjadi release yang lebih kecil, atau memakai library chart (episode 19) untuk berbagi logika tanpa membawa subchart yang besar.
Upgrade yang berjalan 10 menit biasanya menunggu sesuatu — hook Job yang lama, atau resource yang tidak kunjung ready. Gunakan --timeout yang wajar dan --wait hanya jika benar-benar ingin menunggu readiness. Pada lingkungan yang sangat dinamis, pertimbangkan --wait=false dan biarkan controller (atau monitoring) yang memastikan aplikasi siap.
Ketika teknik dasar tidak cukup, inilah senjata-senjata yang membedakan senior engineer:
helm template api ./api-chart -f values-prod.yaml > /tmp/manifest.yaml lalu periksa file-nya dengan saksama. Simpan sebagai dasar diff: render dengan values lama vs baru, lalu diff keduanya. Ini cara paling cepat melihat "apa yang sebenarnya berubah" di balik upgrade yang gagal.
State release Helm 3 disimpan sebagai Secret (bukan ConfigMap seperti Helm 2). Setiap release punya rangkaian secret bernama sh.helm.release.v1.<release>.v<revisi> — satu per revisi. Membongkarnya berguna saat release korup atau history tidak bisa dibaca:
kubectl get secret -n api sh.helm.release.v1.api.v12 -o yaml
# Decode data release-nya
kubectl get secret -n api sh.helm.release.v1.api.v12 \
-o jsonpath='{.data.release}' | base64 -d | base64 -dNilai yang ter-decode adalah protobuf biner — tidak mudah dibaca, tapi berguna untuk memverifikasi metadata (misal chart version dan revision yang benar-benar tersimpan). Menghapus secret ini (bersama --keep-history) adalah cara terakhir untuk "membersihkan" release yang tidak bisa di-uninstall.
Kombinasi helm status api dan kubectl get all -n api memperlihatkan dua lapis kebenaran: apa yang dideklarasikan release vs apa yang ada di cluster. Perbedaan keduanya adalah drift — sumber utama misteri "kenapa aplikasi tidak ter-update padahal chart sudah di-upgrade".
kubectl get events --sort-by=.lastTimestamp adalah kronik kejadian terbaru di namespace. Saat resource gagal dibuat atau Pod tidak bisa dijadwalkan (insufficient resource, image pull gagal, quota tercapai), event log menceritakannya lebih jujur daripada status resource itu sendiri.
kubectl get events --sort-by=.lastTimestamp -n api
# Filter event terkait pod tertentu
kubectl describe pod api-7f9d8c5b6f-abcde | grep -A10 EventsPada episode 26 ini kita telah memahami bahwa debugging Helm dimulai dari mengenali keluarga masalah — instalasi gagal, upgrade gagal, error template, release conflict, hook failure, dan RBAC — lalu menerapkan teknik dasar secara berurutan: --dry-run/helm template untuk memeriksa render, helm get manifest/helm get values untuk melihat kondisi aktual, dan kubectl describe/kubectl logs untuk menyelami sisi Kubernetes. Kita juga membedah recovery: rollback sebagai prosedur tercepat, uninstall dengan --keep-history, dan manual cleanup sebagai jalan terakhir, plus teknik advanced seperti inspeksi secret release dan analisis event log.
Inti yang harus kalian bawa:
file:baris:kolom di error template sudah menunjuk separuh dari solusi.helm template) selalu lebih cepat dan lebih aman daripada trial-and-error langsung di cluster.failed tidak selalu harus di-uninstall — periksa riwayat dan coba rollback dulu.Kemampuan mendiagnosis ini akan semakin teruji saat kalian berhadapan dengan chart versi lama atau migrasi besar. Di episode 27 selanjutnya kita akan membahas migrasi dan upgrade chart: dari migrasi Helm 2 ke Helm 3 dengan plugin helm-2to3, upgrade chart antar major version dengan breaking changes, strategi upgrade aplikasi (rolling update, blue-green, canary), hingga menghadapi deprecation API Kubernetes. Sampai jumpa di episode 27!