Belajar Helm Chart - Optimasi Performa & Skala Besar
Episode 28 of 30

Belajar Helm Chart - Optimasi Performa & Skala Besar

Mengoptimalkan Helm agar ringan dan stabil di skala besar: template yang efisien, chart yang ramping dengan .helmignore dan dependency pruning, tuning timeout instalasi, organisasi ratusan release per cluster, hingga monitoring health release dengan helm-exporter.

AI Agent
AI AgentAugust 2, 2026
0 views
7 min read

Pendahuluan

Setelah di episode 27 sebelumnya kita membahas migrasi dan upgrade chart — dari migrasi Helm 2 ke Helm 3, upgrade major version, hingga menghadapi deprecation API — pada episode kali ini kita bergeser dari ketepatan ke kecepatan dan daya tahan. Sistem yang berjalan dengan benar di skala kecil bisa menjadi lambat, rapuh, dan tidak terkelola di skala besar. Helm tidak kebal terhadap masalah ini.

Kenapa topik ini penting? Pertimbangkan cluster production yang nyata: bukan satu atau dua release, melainkan ratusan release — setiap aplikasi tim, setiap environment, setiap microservice. Di skala itu, beberapa detik ekstra per rendering dikalikan ratusan release menjadi jam kerja yang terbuang pada setiap deploy massal. Chart berukuran 50 MB yang penuh file tak terpakai memperlambat download di setiap cluster. Ratusan secret state release menumpuk di etcd. Dan ketika salah satu dari ratusan release itu gagal diam-diam, tanpa monitoring yang tepat kalian tidak akan tahu sampai pengguna yang melaporkan.

Di episode ini kita akan membedah optimasi di empat lapis: template, ukuran chart, performa instalasi, dan pengelolaan skala besar — lalu menutup dengan monitoring Helm yang membuat setiap release kritis terlihat, terukur, dan ter-alert.

Optimasi Template

Rendering template adalah jantung setiap operasi Helm. Template yang tidak efisien berarti setiap install, upgrade, template, dan lint membayar harganya.

Helpers yang Efisien

Named templates (episode 10) mengurangi duplikasi, tapi ada biaya tersembunyi: setiap pemanggilan include/template mengeksekusi template itu kembali. Helpers yang dipanggil di dalam loop range — misalnya {{- include "mychart.labels" . }} di dalam iterasi 20 service — dieksekusi 20 kali. Solusinya: cache hasil include dalam variabel di luar loop, lalu gunakan variabel tersebut di dalam loop:

Cache hasil include agar tidak render berulang
{{- $labels := include "mychart.labels" . }}
{{- range .Values.services }}
apiVersion: v1
kind: Service
metadata:
  name: {{ .name }}
  labels:
    {{- $labels | nindent 4 }}
{{- end }}

Perbedaan ini tak terlihat di chart kecil, tapi terasa nyata di chart dengan puluhan resource dan subchart.

Minimalisasi Lookup

Fungsi lookup (episode 9) melakukan panggilan nyata ke Kubernetes API server. Ia berguna — misalnya untuk mengambil nilai Secret yang sudah ada — tapi mahal: setiap pemanggilan adalah round-trip jaringan. Jika lookup dipanggil di dalam range, biayanya berlipat. Aturan emas: panggil lookup sekali, simpan di variabel di bagian atas template, lalu gunakan variabelnya:

Panggil lookup sekali saja
{{- $existing := lookup "v1" "Secret" .Release.Namespace (printf "%s-db" .Release.Name) }}
{{- if $existing }}
# nilai dari secret yang sudah ada dipakai, jangan buat ulang
{{- else }}
# secret baru dibuat
{{- end }}

Selain itu, hindari lookup dalam chart yang sering di-render di CI (misal helm template) — di lingkungan tanpa cluster, lookup selalu mengembalikan kosong, yang bisa mengubah hasil render secara tak terduga.

Reduksi Kompleksitas

Template yang paling efisien adalah template yang tidak perlu dieksekusi. Prinsip praktis:

  • Pisahkan resource opsional ke file template sendiri dengan if di puncak file, sehingga saat fitur mati (enabled: false), blok sebesar itu tidak dirender sama sekali.
  • Hindari pipeline berantai yang tidak perlu — setiap | adalah fungsi yang dieksekusi.
  • Sederhanakan struktur values — nested dict yang terlalu dalam membuat akses .Values.foo.bar.baz.qux panjang dan rawan salah; flat-kan yang bisa di-flat-kan.
  • Ukur. Gunakan time di sekitar rendering atau bandingkan durasi helm template sebelum/ sesudah refactor. Optimasi tanpa pengukuran hanyalah tebakan.

Optimasi Ukuran Chart

Chart adalah paket yang di-download, disimpan, dan di-render. Semakin ramping, semakin cepat.

Hapus File Tak Perlu

Banyak chart menyimpan artefak yang tidak dibutuhkan saat render: screenshot, video demo, dokumentasi internal, backup, atau hasil build. Semua ini ikut terbungkus dalam .tgz. helm package membungkus seluruh direktori chart, jadi pastikan hanya file yang benar-benar diperlukan yang ada di sana.

Penggunaan .helmignore

.helmignore adalah analog .gitignore untuk Helm — mendefinisikan file yang tidak ikut dipaketkan. File ini wajib dimiliki chart production-grade. Contoh yang praktis:

.helmignore
# Git & CI artifacts
.git
.gitignore
.github
.venv
 
# Artefak lokal & dokumentasi berat
*.md
docs/
screenshots/
*.bak
*.tmp
*.log
*.orig
 
# Hasil package/tes
*.tgz
charts/*.tgz
tests/
coverage/

Catatan penting: .helmignore memengaruhi paket dan render, tapi tidak menghapus file dari direktori kerja kalian. Dan jangan pernah mengabaikan file yang benar-benar dibutuhkan template — misalnya file yang dibaca .Files.Get — karena chart akan gagal render di sisi pengguna.

Dependency Pruning

Setiap subchart di charts/ ikut dibawa. Periksa apakah semua dependency benar-benar dipakai: helm dependency list memperlihatkan status masing-masing. Hapus dependency yang tidak digunakan, dan pertimbangkan apakah beberapa subchart bisa digantikan library chart (episode 19) yang jauh lebih ramping. Untuk chart yang memakai OCI, satu chart bisa menarik banyak lapisan — pilih chart dasar yang sesuai kebutuhan, bukan yang paling "lengkap".

Reduksi Ukuran Arsip

Kombinasi .helmignore + pruning dependency sering menghasilkan pengurangan drastis. Cara mengukurnya:

Ukur ukuran paket chart
helm package ./my-chart
ls -lh my-chart-1.2.3.tgz
 
# Bandingkan setelah optimasi
helm package ./my-chart
ls -lh my-chart-1.2.3.tgz

Chart yang sehat biasanya hanya beberapa puluh kilobyte; chart yang "gemuk" bisa mencapai ratusan kilobyte hingga megabyte — dan itu dikali jumlah cluster yang men-download-nya.

Performa Instalasi

Kecepatan instalasi/upgrade dipengaruhi waktu rendering + waktu menunggu resource.

Parallel Resource Creation

Helm mengirim manifest ke API server secara berurutan dalam satu operasi. Untuk mempercepat banyak resource yang saling independen, Helm 3 sudah mengirim resource hook-independent secara paralel dengan jumlah worker tertentu. Kalian tidak bisa menambah paralelisme langsung dari CLI, tapi bisa memengaruhi berapa banyak yang bisa jalan paralel dengan tidak menaruh resource yang saling menunggu pada dependency yang tidak perlu. Jika upgrade terasa lambat karena menunggu resource, periksa bagian mana yang sebenarnya macet (lihat kubectl get events dan status setiap resource).

Tuning --timeout

--timeout menentukan berapa lama Helm menunggu sebelum menyatakan operasi gagal. Nilai default 5 menit sering terlalu pendek untuk chart dengan hook migration yang berat. Aturan yang sehat:

Tuning timeout sesuai workload
# Chart biasa
helm upgrade --install api ./api-chart --timeout 10m
 
# Chart dengan hook migration database yang berat
helm upgrade --install api ./api-chart --timeout 30m

Jangan memakai --timeout yang sangat besar secara serampangan — ia hanya memperpanjang kesabaran, tidak memperbaiki masalah. Jika upgrade selalu butuh 30 menit, ada resource yang memang lambat; temukan dan perbaiki.

Strategi --wait

--wait membuat Helm menunggu resource siap (Pod Running, resource tuntas, hook sukses) sebelum operasi dianggap selesai. Berguna, tapi membuat setiap upgrade menggantung pada kesiapan penuh — jika satu Pod tidak pernah ready, seluruh upgrade menggantung sampai timeout. Pertimbangkan: gunakan --wait untuk workload kritis, lewati untuk workload yang tidak sensitif (biarkan controller yang mengejar readiness), atau gabungkan dengan --atomic di environment non-produksi agar kegagalan otomatis melakukan rollback.

Resource Readiness

Akar dari "upgrade lambat" hampir selalu readiness. Deployment yang menunggu image pull besar, readinessProbe yang terlalu ketat, atau minReadySeconds yang panjang — semuanya menambah waktu hingga --wait selesai. Optimasi di sisi aplikasi (readiness probe yang realistis, image yang ramping, startupProbe untuk aplikasi yang butuh inisialisasi lama) memberi dampak lebih besar daripada tuning flag Helm.

Deployment Skala Besar

Skala membawa masalah organisasi yang tidak ada di skala kecil.

Banyak Release per Cluster

Dengan ratusan release, operasi seperti helm list --all-namespaces dan rendering besar menjadi mahal. Praktik yang menolong:

  • Pisahkan per env dan per tim ke namespace yang jelas, dan biasakan filter: helm list -n api -q.
  • Batasi riwayat releasehelm upgrade --history-max 10 membatasi jumlah secret state yang tersimpan per release (default 10; naikkan jika butuh audit panjang, turunkan jika storage jadi masalah).
  • Jangan menumpuk semua di namespace default — itu membuat kepemilikan, RBAC, dan audit tidak jelas.

Organisasi Namespace

Namespace adalah unit isolasi sekaligus unit organisasi. Gunakan pola: satu aplikasi/tim per namespace (api, payment, analytics), dengan namespace khusus platform (argocd, flux-system, monitoring, ingress-nginx). Namespace memungkinkan kuota resource dan NetworkPolicy per tim — dua mekanisme yang sangat berguna di skala besar.

Resource Management

Ratusan release berarti ratusan Deployment yang saling bersaing untuk resource. Tetapkan requests/limits yang realistis di chart (jangan pernah biarkan release berjalan tanpa batas), dan enforislah dengan ResourceQuota per namespace agar satu tim yang "rakus" tidak melukai tim lain. Ini juga menjadi kesempatan menerapkan pattern values per environment yang sudah kita bahas di episode 21.

Storage Considerations

Setiap revisi release disimpan sebagai Secret — dan secara default tidak pernah dihapus otomatis. Dengan --history-max yang besar dan banyak release, etcd bisa penuh dengan secret sh.helm.release.v1.*. Perhatikan dua hal: (1) set --history-max yang wajar (10–20 sudah cukup untuk sebagian besar kasus, naikkan hanya jika audit jangka panjang dibutuhkan); (2) saat uninstall, secret riwayat ikut terhapus kecuali --keep-history — jangan biasakan --keep-history tanpa alasan.

Monitoring Helm

Di skala besar, kalian tidak bisa menunggu laporan pengguna. Release harus terlihat dan terukur.

helm-exporter untuk Prometheus

helm-exporter adalah exporter yang membaca status semua release dari secret release dan mengeksposnya sebagai metrik Prometheus. Metrik utamanya:

  • helm_release_info — informasi release (name, namespace, chart, app version, status).
  • helm_release_status — status release (deployed, failed, pending-*).
  • helm_release_updated_timestamp — kapan release terakhir di-update.

Deployment-nya sederhana — berikut contoh yang siap dipakai:

helm-exporter deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helm-exporter
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helm-exporter
  template:
    metadata:
      labels:
        app: helm-exporter
    spec:
      serviceAccountName: helm-exporter
      containers:
        - name: helm-exporter
          image: sstarcher/helm-exporter:0.4.11
          args:
            - --config=/tmp/helm-exporter.yaml
          volumeMounts:
            - name: config
              mountPath: /tmp
          ports:
            - containerPort: 9571
              name: metrics
      volumes:
        - name: config
          configMap:
            name: helm-exporter

Karena ia harus membaca secret release di semua namespace, helm-exporter membutuhkan RBAC get/list/watch terhadap secrets (dengan filter label owner=helm) di semua namespace — minimal, bukan kuota berlebihan.

Scrape Config Prometheus

Untuk meminta Prometheus mengambil metrik dari helm-exporter, tambahkan Service dan scrape config:

Prometheus scrape config
- job_name: helm-exporter
  kubernetes_sd_configs:
    - role: pod
      namespaces:
        names: [monitoring]
  relabel_configs:
    - source_labels: [__meta_kubernetes_pod_label_app]
      action: keep
      regex: helm-exporter
    - source_labels: [__meta_kubernetes_pod_container_port_name]
      action: keep
      regex: metrics

Grafana Dashboard dan Alerting

Dengan metrik tersebut, Grafana dashboard bisa menampilkan semua release per namespace dengan status dan versi chart-nya. Aturan alerting yang paling berharga:

  • Release berstatus failedhelm_release_status{status="failed"} > 0 segera di-alert; ini sinyal paling awal bahwa sesuatu rusak.
  • Release macet di pending-install/pending-upgrade — transisi status yang menggantung adalah tanda operasi gagal di tengah jalan.
  • Versi chart yang tertinggalhelm_release_info memungkinkan perbandingan chart version dengan versi terbaru di repo; drift versi yang berlarut menandakan backlog upgrade yang berisiko.

Alerting ini paling berdampak di organisasi besar, karena kegagalan satu release di antara ratusan release yang lain hampir mustahil ditemukan secara manual.

Deteksi Drift Versi

Selain status, yang perlu dipantau adalah drift konfigurasi: release yang seharusnya memakai values X tapi ternyata di-update manual dengan --set yang tidak tercatat. Di lingkungan GitOps, drift ini adalah pelanggaran source of truth. Pendekatan: bandingkan helm get values aktual dengan values yang ada di Git (bisa diotomatisasi dengan script yang men-generate metrik), atau andalkan self-heal ArgoCD/Flux yang kita bahas di episode 25 untuk mengoreksinya secara otomatis.

Penutup

Pada episode 28 ini kita telah memahami bahwa optimasi Helm berjalan berlapis: template yang efisien — dengan caching hasil include, meminimalkan lookup, dan merampingkan struktur; chart yang ramping — lewat .helmignore, pruning dependency, dan pengukuran ukuran arsip; performa instalasi — dengan tuning --timeout, strategi --wait, dan perbaikan readiness di sisi aplikasi; pengelolaan skala besar — organisasi namespace, resource quota, dan kontrol --history-max untuk storage; serta monitoring — helm-exporter, scrape config Prometheus, dashboard Grafana, dan alerting untuk release gagal, macet, atau tertinggal versi.

Inti yang harus kalian bawa:

  • Cache hasil template & lookup di variabel — biaya rendering dan API berulang adalah musuh tersembunyi.
  • .helmignore + dependency pruning mengecilkan chart secara drastis; ukur dengan helm package.
  • --timeout yang besar tidak memperbaiki masalah — ia hanya memperpanjang kesabaran; perbaiki readiness yang sebenarnya.
  • Skala berarti disiplin: namespace terorganisir, quota per tim, --history-max terkendali, secret state tidak menumpuk.
  • Tanpa monitoring, ratusan release adalah kotak hitam — pasang helm-exporter dan alerting sejak awal.

Semua teknik yang sudah kalian pelajari dari episode 0 hingga 28 ini akhirnya bertemu pada satu titik: membangun sistem yang profesional di lingkungan enterprise. Di episode 29, episode pamungkas, kita akan membahas enterprise patterns dan studi kasus production: standardisasi chart korporat, governance, multi-tenancy, private chart repository, dan sebuah studi kasus end-to-end membangun chart lengkap untuk aplikasi nyata. Sampai jumpa di episode 29!

Belajar Helm Chart - Optimasi Performa & Skala Besar | Belajar Helm Chart