Membedah cara kerja Helm 3 dari dalam: arsitektur client-only tanpa Tiller, penyimpanan release di dalam Secret, konsep Chart, Repository, Release, Values dan Templates, struktur direktori chart, serta mekanisme three-way strategic merge patch untuk upgrade dan rollback.

Setelah di episode 1 kita memahami mengapa Helm ada — menjawab masalah manajemen puluhan file YAML, konfigurasi antar environment, dan lifecycle aplikasi — pada episode kali ini kita membuka kap mesinnya. Kita akan membedah arsitektur dan konsep inti Helm 3: bagaimana ia bekerja tanpa Tiller, di mana state release disimpan, apa saja konsep yang membentuk bahasa keseharian Helm, bagaimana struktur sebuah chart yang baik, dan — bagian yang paling jarang dibahas dengan jelas — apa yang sebenarnya terjadi di balik upgrade dan rollback.
Mengapa penting memahami arsitektur, bukan hanya mengetik perintah? Karena hampir semua error "misterius" di Helm berakar dari kesalahpahaman arsitektur: orang yang tidak tahu bahwa release disimpan sebagai Secret akan bingung melihat Secret aneh bernama sh.helm.release.v1.* di namespace-nya; orang yang tidak paham three-way merge akan salah mengira bahwa --force menyelesaikan semua konflik. Seperti membongkar mesin mobil, memahami bagian-bagiannya membuat kalian tidak hanya bisa berkendara, tapi juga memperbaiki ketika ada yang macet.
Perbedaan arsitektur terbesar Helm 3 dibanding pendahulunya adalah tidak ada komponen server. Helm 3 adalah binary client tunggal (helm) yang berjalan di mesin kalian — tidak ada daemon, tidak ada service yang perlu di-deploy ke cluster.
Ketika kalian menjalankan helm install, client Helm membaca file kubeconfig yang sama dengan kubectl, mendapatkan kredensial yang relevan dengan context aktif, lalu berkomunikasi langsung dengan Kubernetes API server melalui HTTPS. Tidak ada perantara. Konsekuensi pentingnya: semua kontrol akses mengikuti RBAC Kubernetes standar. Jika user kalian hanya punya akses ke namespace dev, maka release yang kalian install pun hanya bisa menyentuh namespace dev — bukan seluruh cluster seperti yang terjadi dengan Tiller di Helm 2.
helm CLI (client lokal)
│ kubeconfig (RBAC user)
▼
Kubernetes API server
├── installs manifests (Deployment, Service, ...)
└── stores release state (Secret, namespace-scoped)Tip
Karena Helm memakai kubeconfig, kalian bisa berpindah target hanya dengan mengganti context: kubectl config use-context dev-cluster lalu helm install ... akan otomatis mendeploy ke cluster dev. Tidak ada konfigurasi Helm terpisah yang perlu disinkronkan — satu source of truth untuk kredensial.
Helm 3 menyimpan semua state setiap release sebagai Secret dengan tipe helm.sh/release.v1, di namespace tempat release di-install (bukan di kube-system seperti era Tiller). Setiap instalasi menghasilkan Secret baru; setiap upgrade menghasilkan Secret baru lagi. Cara menyaksikannya:
kubectl get secrets
kubectl get secret sh.helm.release.v1.myapp.v1 -o yamlapiVersion: v1
kind: Secret
metadata:
name: sh.helm.release.v1.myapp.v1
namespace: myapp
type: helm.sh/release.v1
data:
release: eyJjaGFydCI6Ik15YXBwIiwi...Isi release adalah manifest ter-render seluruh aplikasi yang disimpan dalam bentuk base64-compressed. Dari sinilah helm get manifest, helm rollback, dan helm history membaca datanya. Satu implikasi praktis yang penting: hapus secret = kehilangan riwayat release. Jangan pernah menghapus Secret sh.helm.release.* secara manual kalau masih ingin release itu di-manage oleh Helm.
Ada dua implikasi lebih lanjut yang patut dicatat. Pertama, karena tersimpan sebagai Secret, isinya terenkripsi saat idle di etcd (jika cluster mengaktifkan enkripsi etcd) — data manifest yang mungkin memuat konfigurasi sensitif tidak terbaca polos. Kedua, karena scoped ke namespace, satu release tidak bisa secara tidak sengaja melihat atau memengaruhi release lain di namespace berbeda — isolasi yang sejalan dengan model RBAC namespace standar.
Lima konsep ini adalah kosakata wajib Helm. Kuasai, karena semua perintah dan semua diskusi di series ini dibangun di atasnya.
Chart adalah paket aplikasi: direktori berisi metadata (Chart.yaml), konfigurasi default (values.yaml), dan sekumpulan template (templates/) yang menghasilkan manifest Kubernetes. Chart bisa berupa direktori, arsip .tgz, atau referensi ke repository. Satu chart mendeskripsikan satu aplikasi yang lengkap — Deployment + Service + Ingress + ConfigMap dalam satu paket.
Repository adalah tempat penyimpanan chart, diakses lewat HTTP/HTTPS atau OCI registry. Repositori menyimpan arsip .tgz dan file index.yaml yang memetakan nama chart ke versi yang tersedia. Analoginya persis npm registry: kalian menambahkan registry, lalu mengambil paket dari sana.
Release adalah satu instance chart yang ter-install ke cluster dengan nama unik. Inilah titik krusial yang membedakan Helm dari sekadar templating: helm install myapp nginx menghasilkan release bernama myapp, dan Helm melacak seluruh riwayatnya — setiap perubahan menghasilkan revision baru yang bisa di-rollback.
Values adalah konfigurasi chart: nilai-nilai yang disuntikkan ke template saat rendering. Setiap chart punya values.yaml berisi default; user bisa meng-override lewat file (-f) atau parameter baris perintah (--set). Nilai inilah yang membuat satu chart bisa melayani banyak environment tanpa mengubah template sama sekali.
Nilai-nilai ini punya hierarki yang tegas: values.yaml (default) adalah lapisan paling bawah, file override (-f values-prod.yaml) menimpanya, dan --set di baris perintah menimpa keduanya. Hierarki inilah yang memungkinkan satu chart melayani dev, staging, dan production hanya dengan menukar file values — topik yang akan kita bedah menyeluruh di episode 6.
Templates adalah file manifest yang ditulis dalam Go template dengan sintaks {{ .Values.replicaCount }}. Saat install, Helm merender setiap template dengan nilai values yang efektif, menghasilkan YAML final yang dikirim ke API server. Template adalah "kode", values adalah "data" — pemisahan inilah yang membuat chart reusable.
Template tidak sekadar mengganti placeholder: ia bisa memuat file, memanggil helper, melakukan perulangan, dan menyesuaikan struktur output secara kondisional — misalnya "buat Ingress hanya jika ingress.enabled bernilai true". Kalian akan membangun template sendiri mulai episode 7, dan menggali bahasa templating-nya hingga episode 10.
Sebuah chart yang sehat memiliki struktur yang hampir selalu sama. Mari bedah satu per satu:
my-chart/
├── Chart.yaml # metadata chart: nama, versi, apiVersion, dependencies
├── values.yaml # nilai konfigurasi default
├── .helmignore # file yang diabaikan saat packaging (pola gitignore)
├── README.md # dokumentasi penggunaan chart
├── LICENSE # lisensi distribusi (wajib untuk chart publik)
├── charts/ # dependency (subcharts) yang ter-packaging
├── crds/ # CustomResourceDefinition (di-install global, sekali saja)
└── templates/ # template manifest + helpers + NOTES
├── _helpers.tpl # named templates yang bisa di-include
├── deployment.yaml
├── service.yaml
├── NOTES.txt # pesan yang ditampilkan setelah install
└── NOTES.mdapiVersion, name, version, appVersion, description, type, dan daftar dependencies..yaml/.tpl di sini dirender (kecuali yang diawali _).helm dependency (dibahas di episode 11).Contoh Chart.yaml yang sehat — perhatikan apiVersion: v2, version (versi paket), dan appVersion (versi aplikasi):
apiVersion: v2
name: my-chart
description: A Helm chart for my application
type: application
version: 0.1.0
appVersion: "1.16.0"
dependencies:
- name: postgresql
version: "15.x.x"
repository: https://charts.bitnami.com/bitnamiField dependencies di sinilah yang membuat satu chart bisa menarik chart lain secara otomatis saat install — dan versinya akan dikunci di Chart.lock. Kalian akan membangun chart seperti ini dari nol di episode 7, dan mendalami dependency di episode 11.
Alur internal helm install — dan juga helm upgrade — adalah pipa empat tahap:
values.schema.json jika ada), lalu menanyakan API server apakah resource bisa dibuat (dry-run di sisi server).Karena urutan ini, kegagalan di tahap manapun meninggalkan jejak yang bisa diperiksa: --dry-run untuk menguji render, kubectl get secrets untuk melihat apakah release tersimpan, dan kubectl get pods untuk melihat apakah resource benar-benar hidup.
Tahap render juga bisa dijalankan tanpa cluster sama sekali dengan helm template — cara paling cepat memeriksa output chart tanpa menyentuh API server:
helm template web bitnami/nginx --namespace web
helm template web bitnami/nginx --set replicaCount=5 | head -40Perintah pertama menghasilkan seluruh manifest yang akan dikirim; perintah kedua menunjukkannya dengan override replicaCount=5 diterapkan. Ini adalah jendela transparansi utama Helm: apa pun yang tertulis di file ini, itulah yang akan dikirim ke API server.
Di sinilah sihir sesungguhnya terjadi. Ketika kalian menjalankan helm upgrade, Helm tidak sekadar "mengirim YAML baru". Ia menggabungkan tiga sumber:
Dari ketiganya, Helm menghitung strategic merge patch yang hanya mengubah bagian yang memang berbeda — dan yang terpenting, tidak membatalkan perubahan yang dilakukan pihak lain terhadap resource yang tidak disentuh chart. Inilah yang membuat upgrade Helm "aman": kalian mengubah replicas dari 3 ke 5, dan perubahan label yang dilakukan tool lain di resource itu tidak ikut terhapus.
Perumpamaan yang paling mudah: bayangkan tiga salinan dokumen — salinan lama (revisi sebelumnya), salinan baru (yang ingin diterapkan), dan salinan di dinding (keadaan aktual di cluster). Helm membandingkan ketiganya bidang demi bidang: jika replicas berubah di salinan baru, ia meng-update nilainya; jika ada anotasi yang ditambahkan orang lain pada salinan di dinding dan tidak disentuh oleh kedua salinan, ia membiarkannya tetap ada. Hasil perbandingan itulah strategic merge patch yang dikirim ke API server — bukan menimpa seluruh file seperti diff biasa.
Semua perbedaan di atas dirangkum dalam tabel berikut:
| Aspek | Helm 2 | Helm 3 |
|---|---|---|
| Arsitektur | Client + Tiller (daemon di cluster) | Client-only, langsung ke API server |
| Model keamanan | Tiller punya akses luas, sulit RBAC | RBAC standar Kubernetes (kubeconfig) |
| Penyimpanan release | ConfigMap di namespace kube-system | Secret di namespace release |
| Skema chart | apiVersion: v1 | apiVersion: v2 |
| Validasi values | Tidak ada | JSON Schema (values.schema.json) |
| Dependency | Tidak ada lockfile | Chart.lock untuk reproducibilitas |
| OCI registry | Tidak didukung | Didukung (Helm 3.8+) |
Tiga poin terakhir layak digarisbawahi. apiVersion: v2 menandakan skema chart modern yang menambahkan kemampuan dependency deklaratif, type, dan appVersion. JSON Schema validation berarti chart bisa mendefinisikan kontrak ketat untuk nilai input — kesalahan tipe data terdeteksi saat install, bukan saat aplikasi meledak di runtime (dibahas mendalam di episode 13). Chart.lock mengunci versi dependency, sehingga helm dependency build menghasilkan chart yang identik di semua mesin — fondasi reproducibilitas dan supply chain yang aman.
Important
Jika kalian menemui chart lama dengan apiVersion: v1 di Chart.yaml-nya, Helm 3 tetap bisa meng-install-nya (kompatibilitas mundur), tapi semua fitur v2 — dependency deklaratif, type, validasi schema — tidak tersedia. Seluruh series ini memakai chart apiVersion: v2.
Pada episode 2 ini kita telah membedah arsitektur Helm 3 dari dalam: client-only tanpa Tiller yang berkomunikasi langsung dengan API server memakai RBAC standar, state release yang disimpan sebagai Secret di namespace release, lima konsep inti (Chart, Repository, Release, Values, Templates), struktur direktori chart yang baku, serta alur kerja empat tahap render → validasi → apply → simpan dengan mekanisme three-way strategic merge patch di balik upgrade dan rollback.
Inti yang harus kalian bawa:
sh.helm.release.* — jangan dihapus manual.apiVersion: v2, JSON Schema, dan Chart.lock.Sekarang kalian memahami mesin di balik Helm. Di episode 3 selanjutnya kita naik ke kokpit: instalasi Helm dan dasar-dasar CLI — dari script installer, shell completion, struktur perintah, manajemen repository, mencari chart di Artifact Hub, hingga deployment pertama kalian memakai Helm. Sampai jumpa di episode 3!