Helm #

Menyebarkan (deploy) sebuah aplikasi mikroservis tingkat produksi ke dalam kluster Kubernetes bukanlah tugas yang sederhana. Satu aplikasi biasanya tidak hanya terdiri dari satu manifest Deployment, melainkan sekumpulan manifest terikat yang saling bergantung: Deployment (workload), Service (network access), ConfigMap dan Secret (konfigurasi), HorizontalPodAutoscaler (scaling), Ingress (routing eksternal), serta ServiceAccount, Role, dan RoleBinding (RBAC). Jika kita mengelola seluruh file manifest YAML ini secara manual di setiap lingkungan (development, staging, production), kita akan terjebak dalam proses duplikasi kode yang melelahkan dan rawan memicu kesalahan konfigurasi manusia (human error). Helm hadir sebagai manajer paket (package manager) standar untuk Kubernetes yang mengabstraksikan sekumpulan manifest tersebut menjadi satu unit modular yang dapat di-package, di-version-control, dan di-deploy dengan satu perintah tunggal.


Arsitektur dan Alur Kerja Helm #

Helm bekerja di sisi client (client-side tool) sejak versi Helm 3 dirilis (menghapus komponen server-side Tiller yang memiliki masalah celah keamanan RBAC pada versi terdahulu). Helm Client berinteraksi langsung dengan Kubernetes API Server menggunakan kredensial konfigurasi lokal (kubeconfig).

flowchart TD
    ChartSource["Helm Chart Source Directory (templates/, values.yaml)"] -->|"helm package"| ChartTgz["Chart Archive (.tgz File)"]
    ChartTgz -->|"helm push"| OCIRegistry["OCI Container Registry (ECR / Harbor)"]
    
    subgraph DeployCycle["Siklus Deployment (CI/CD / Developer Machine)"]
        direction TB
        HelmClient["Helm Client CLI"] -->|"Download Chart"| OCIRegistry
        HelmClient -->|"Kompilasi: Templates + values.yaml"| YAMLOutput["Manifest YAML Teks (Plain Text)"]
        YAMLOutput -->|"Kirim Payload HTTP POST"| K8sAPI["Kube-API Server"]
    end
    
    subgraph ClusterStorage["Namespace Kubernetes (Penyimpanan Keadaan)"]
        direction LR
        K8sResources["Active Resources (Pods, Services, Ingress)"]
        ReleaseSecret["Helm Release History (Stored as Secret in target Namespace)"]
    end
    
    K8sAPI --> K8sResources
    K8sAPI --> ReleaseSecret

Mekanisme Rilis dan Penyimpanan State #

Setiap kali kita menjalankan perintah helm install atau helm upgrade, Helm melakukan kompilasi antara file template manifest dengan nilai konfigurasi (values.yaml), kemudian mengirimkan payload YAML hasil kompilasi tersebut ke Kubernetes API Server untuk diterapkan.

Helm mencatat riwayat rilis (release history) kluster secara native di dalam Kubernetes. Setiap versi rilis disimpan sebagai Secret di dalam namespace target (berlabel sh.helm.release.v1.<release-name>.<version>). Informasi ini berisi seluruh snapshot manifest yang diterapkan, mempermudah proses pemulihan (rollback) secara instan tanpa perlu melacak kembali riwayat commit Git di pipa CI/CD.


Anatomi Struktur Helm Chart #

Sebuah paket Helm disebut dengan Chart. Chart adalah direktori terstruktur yang memisahkan antara template manifest dengan nilai-nilai variabel dinamis.

Struktur Direktori Helm Chart Standar:

my-app/
├── Chart.yaml          # Metadata utama chart (nama, deskripsi, versi chart, versi app)
├── values.yaml         # Nilai konfigurasi default (dapat di-override saat deployment)
├── charts/             # Sub-charts/dependencies yang dibutuhkan (file .tgz)
├── templates/          # Direktori file template manifest Kubernetes
│   ├── _helpers.tpl    # Template helper global (blok define template yang dapat digunakan kembali)
│   ├── deployment.yaml # Template Deployment aplikasi
│   ├── service.yaml    # Template Service
│   ├── ingress.yaml    # Template Ingress
│   ├── NOTES.txt       # Skrip teks yang otomatis tercetak setelah instalasi sukses
└── .helmignore         # Pola file yang diabaikan saat chart di-package

Penulisan Chart.yaml (SemVer Versioning) #

File Chart.yaml berisi identitas dan dependensi chart. Kita harus memisahkan secara jelas antara versi kemasan chart dengan versi kode aplikasi.

apiVersion: v2             # Wajib v2 untuk penggunaan Helm 3
name: billing-service
description: Layanan pemrosesan pembayaran mikroservis e-commerce.
type: application          # 'application' untuk deployable chart, 'library' untuk helper shared chart
version: 1.4.2             # Versi Chart (Mengikuti SemVer - dinaikkan jika struktur template berubah)
appVersion: "2.1.0"        # Versi Aplikasi (Mencerminkan tag image kontainer docker aplikasi)
dependencies:
  - name: redis
    version: "17.3.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled # Hanya diinstal jika parameter redis.enabled bernilai true di values.yaml

Mesin Template Go dan Pustaka Fungsi Sprig #

Helm memanfaatkan mesin template teks bawaan bahasa Go (text/template) yang diperkaya dengan fungsi-fungsi manipulasi string dari pustaka Sprig.

File values.yaml: Abstraksi Nilai Konfigurasi #

Semua konfigurasi yang bervariasi antar lingkungan (seperti dev, staging, prod) tidak boleh ditulis keras (hardcoded) di dalam file template manifest. Konfigurasi tersebut wajib didefinisikan sebagai variabel di dalam values.yaml.

# File: values.yaml (Nilai default)
replicaCount: 2

image:
  repository: registry.company.com/apps/billing
  pullPolicy: IfNotPresent
  tag: "" # Jika kosong, default ke appVersion di Chart.yaml

service:
  type: ClusterIP
  port: 8080

resources:
  limits:
    cpu: "500m"
    memory: "512Mi"
  requests:
    cpu: "200m"
    memory: "256Mi"

ingress:
  enabled: false
  hosts:
    - host: billing.company.com
      paths:
        - path: /
          pathType: ImplementationSpecific

Implementasi Templating Manifest (templates/deployment.yaml) #

Kita menulis template manifest menggunakan sintaksis evaluasi double curly braces {{ }}.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "billing.fullname" . }}
  namespace: {{ .Release.Namespace }}
  labels:
    # Sisipkan label standar yang didefinisikan di _helpers.tpl
    {{- include "billing.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "billing.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "billing.selectorLabels" . | nindent 8 }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        # Default tag ke appVersion jika tag kosong di values.yaml
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: 8080
          name: http
        resources:
          # Salin blok resources YAML secara utuh dengan penataan indentasi 10 spasi
          {{- toYaml .Values.resources | nindent 10 }}

Pembuatan Template Helpers (_helpers.tpl) #

Blok template pembantu (helper templates) digunakan untuk membungkus kode label dan penamaan standard agar tidak terjadi duplikasi penulisan kode manifest.

[!IMPORTANT] Perbedaan Kritis template vs include: Di dalam mesin template Helm, kita harus menggunakan fungsi include alih-alih perintah bawaan template saat memanggil helper template. Perintah template tidak dapat dialirkan (pipeline) ke fungsi manipulasi string lainnya seperti nindent (new indent). Penggunaan include memungkinkan kita mengatur tata letak spasi YAML secara akurat.

# File: templates/_helpers.tpl

{{/*
1. Menentukan nama lengkap aplikasi (Release Name + Chart Name)
*/}}
{{- define "billing.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
2. Label standar untuk standarisasi monitoring dan compliance
*/}}
{{- define "billing.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version }}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}

{{/*
3. Selector labels untuk pencocokan service dan pod
*/}}
{{- define "billing.selectorLabels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}

Perintah Operasional Helm Tingkat Produksi #

Berikut adalah daftar perintah baris perintah (CLI) Helm yang wajib diintegrasikan ke dalam pipa CI/CD atau digunakan oleh administrator kluster:

1. Uji Coba Kompilasi dan Dry-Run (Deteksi Dini) #

Sebelum menerapkan perubahan di produksi, kita dapat melihat hasil rendering YAML teks secara lokal tanpa menyentuh kluster untuk memeriksa sintaksis spasi YAML.

# Uji rendering manifest secara lokal
helm template billing-release ./my-chart --values values-production.yaml

# Uji rendering langsung ke API Server dengan mode dry-run (validasi schema API)
helm install billing-release ./my-chart --values values-production.yaml --dry-run

2. Pengecekan Selisih Konfigurasi (Helm Diff Plugin) #

Gunakan plugin helm-diff untuk melihat selisih konfigurasi persis (diff output) antara manifest yang sedang berjalan di produksi dengan manifest baru yang akan di-deploy.

# Instalasi plugin diff
helm plugin install https://github.com/databus23/helm-diff

# Bandingkan perubahan sebelum melakukan upgrade
helm diff upgrade billing-release ./my-chart --values values-production.yaml

3. Penerapan Rilis Aman (Safe Deployment Flags) #

Di tingkat produksi, kita harus mengonfigurasi mekanisme proteksi otomatis agar jika kontainer baru mengalami crash-loop, sistem secara otomatis melakukan pembatalan (rollback) ke revisi sehat sebelumnya.

# Upgrade dengan proteksi otomatis
helm upgrade billing-release ./my-chart \
  --namespace production \
  --values values-production.yaml \
  --set image.tag=v2.1.2 \
  --wait \                  # Tunggu hingga semua Pod berstatus Ready
  --timeout 10m0s \         # Batasi waktu tunggu maksimal 10 menit
  --atomic \                # Hapus resource baru dan rollback otomatis jika proses gagal/timeout
  --cleanup-on-fail         # Bersihkan sisa resource yatim jika upgrade gagal

Menyimpan Helm Chart di OCI Registry (Helm 3.8+) #

Di masa lalu, mendistribusikan Helm Chart membutuhkan server repositori khusus dengan file index.yaml. Mulai dari Helm 3.8+, kita dapat memperlakukan Helm Chart sebagai objek OCI (OCI Artifacts) dan menyimpannya di dalam kontainer registry modern yang sama dengan image aplikasi kita (seperti Harbor, AWS ECR, atau GCP Artifact Registry).

# 1. Login ke OCI Container Registry menggunakan kredensial resmi
helm registry login registry.company.com -u ci-user -p secret-token

# 2. Kemas direktori chart menjadi file arsip terkompresi (.tgz)
helm package ./my-chart
# Menghasilkan file: billing-service-1.4.2.tgz

# 3. Push file arsip ke OCI registry menggunakan skema url oci://
helm push billing-service-1.4.2.tgz oci://registry.company.com/helm-charts

Untuk menginstalnya kembali dari OCI registry:

helm install billing-release oci://registry.company.com/helm-charts/billing-service --version 1.4.2 -n production

Anti-Pattern dalam Praktik Manajemen Helm Chart #

Hindari kesalahan operasional berikut saat membangun dan mengelola Helm Chart:

1. Modifikasi Manual Pasca-Deployment (Ad-Hoc Drifts) #

Melakukan perubahan manifest secara langsung menggunakan perintah kubectl edit atau kubectl patch setelah aplikasi di-deploy melalui Helm.

Risiko Modifikasi Manual:
- State di dalam Kubernetes API Server menjadi tidak sinkron (*drift*) dengan state rilis Helm.
- Saat proses 'helm upgrade' berikutnya dijalankan, Helm akan menimpa seluruh perubahan manual tersebut, menyebabkan hilangnya patch konfigurasi darurat secara tiba-tiba di produksi.
✓ SOLUSI: Seluruh perubahan konfigurasi harus melalui values.yaml dan di-commit ke Git (GitOps flow).

2. Menyimpan Secret Plain-Text di values.yaml #

# ANTI-PATTERN: Menyimpan password database plain-text langsung di values.yaml
db:
  password: "super-secret-password-123" # JANGAN: File ini disimpan di Git repositori publik/internal

# ==============================================================================
# BENAR: Menggunakan referensi eksternal atau enkripsi SOPS.
# Kita hanya menyimpan referensi nama Secret yang dibuat secara aman oleh operator eksternal (ESO).
db:
  secretName: billing-database-credentials

Checklist Audit Helm Chart Produksi #

Gunakan daftar checklist berikut sebelum merilis Helm Chart Anda ke repositori pusat:

STRUKTUR & TATA LETAK KODE:
  □ File Chart.yaml mendefinisikan versi chart (version) dan versi aplikasi (appVersion) secara terpisah.
  □ Versi chart ditingkatkan secara konsisten mengikuti aturan Semantic Versioning (SemVer).
  □ Variabel dinamis tidak di-hardcode di folder templates; melainkan dideklarasikan di values.yaml.
  □ Helper templates (_helpers.tpl) digunakan untuk standarisasi nama dan labels global.
  □ Penggunaan helper template dipanggil menggunakan fungsi 'include', bukan perintah 'template'.

PENGAMANAN & PROTEKSI OPERASIONAL:
  □ Nilai rahasia (Secret) tidak disimpan secara plain-text di file values.yaml.
  □ Pipa CI/CD menggunakan perintah 'helm upgrade' dengan flag '--atomic' dan '--wait'.
  □ Menggunakan plugin 'helm-diff' di dalam pipeline untuk memvalidasi perubahan sebelum deployment.
  □ Helm Chart dikemas dan didistribusikan menggunakan OCI Registry resmi.
  □ Perubahan manifest tidak pernah dilakukan menggunakan kubectl edit secara langsung di produksi.

Ringkasan #

  • Helm Mengelola Kompleksitas Manifest — Abstraksikan kumpulan manifest Kubernetes menjadi satu paket modular (Chart) untuk mempermudah replikasi antar lingkungan (Dev/Prod).
  • Gunakan include untuk Tata Letak Spasi — Selalu gunakan fungsi include untuk memanggil helper template di _helpers.tpl agar format indentasi YAML nindent bekerja sempurna.
  • Aktifkan Proteksi –atomic — Pastikan flag --atomic, --wait, dan --timeout selalu aktif saat rilis di produksi agar Helm memicu auto-rollback jika pod baru gagal start.
  • Pisahkan Chart Version dan App Version — Pahami perbedaannya; version mewakili perubahan file template Helm, sedangkan appVersion mewakili tag kontainer image aplikasi.
  • Terapkan OCI Registry untuk Chart — Hilangkan infrastruktur repositori chart tambahan; simpan arsip .tgz Helm secara native di dalam OCI Container Registry.
  • Hindari Ad-Hoc Drift Pasca Deploy — Seluruh modifikasi manifest kluster wajib dideklarasikan melalui values.yaml dan dilarang keras melakukan kubectl edit manual di produksi.

← Sebelumnya: Anti-Pattern Observability   Berikutnya: Kustomize →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact