Helm

Helm #

Ketika kita mulai menjalankan aplikasi yang lebih besar di Kubernetes, kita akan menyadari bahwa mendeploy aplikasi pihak ketiga (third-party) yang kompleks bukanlah tugas yang sederhana. Bayangkan kita harus memasang tumpukan pemantauan (monitoring stack) seperti Prometheus dan Grafana, atau pengontrol masuk jaringan (Ingress Controller) seperti Nginx Ingress. Aplikasi-aplikasi ini membutuhkan puluhan objek manifest YAML yang saling berhubungan: Deployment, Service, ConfigMap, Secret, ServiceAccount, ClusterRole, hingga Custom Resource Definitions (CRD). Menulis dan memelihara ratusan manifest YAML ini secara manual untuk setiap environment adalah pemborosan waktu yang sangat besar.

Di sinilah Helm masuk sebagai penyelamat. Helm adalah manajer paket (package manager) resmi untuk Kubernetes, yang bertindak layaknya apt di Ubuntu atau pip di Python. Dengan Helm, seluruh manifest yang rumit tersebut dikemas menjadi satu kesatuan paket modular yang disebut Chart. Ansible mendukung penuh integrasi Helm melalui modul khusus di dalam koleksi kubernetes.core. Dengan memadukan Ansible dan Helm, kita dapat mengelola instalasi, pembaruan (upgrade), kustomisasi konfigurasi (values), hingga rollback otomatis aplikasi pihak ketiga secara deklaratif dan terstandardisasi. Artikel ini akan membahas tuntas bagaimana kita mengelola Helm di Kubernetes menggunakan Ansible.


Konsep Dasar Helm: Chart, Release, Repository, dan Values #

Sebelum kita menyelami otomatisasi playbook Ansible, sangat penting bagi kita untuk memahami istilah-istilah kunci yang digunakan dalam ekosistem Helm:

Konsep Utama Helm:
  - Chart: Paket aplikasi Kubernetes yang berisi template manifest YAML dan file metadata konfigurasi.
  - Release: Instance dari Chart yang sedang berjalan di dalam kluster Kubernetes. Satu Chart dapat di-deploy berkali-kali menghasilkan beberapa Release (misal: db-dev dan db-prod).
  - Repository (Repo): Repositori online tempat menyimpan dan membagikan Chart yang siap diunduh.
  - Values: Parameter konfigurasi yang digunakan untuk menyesuaikan Chart dengan kebutuhan kita (seperti jumlah replika, alamat IP, atau memori limit).
KAPAN KITA BUTUH HELM?
  ✓ Kita ingin memasang aplikasi pihak ketiga yang populer (seperti Nginx Ingress, Cert-Manager, Postgres, Keycloak) yang sudah memiliki Chart resmi.
  ✓ Kita ingin membuat deployment aplikasi internal kita menjadi modular dan mudah disesuaikan di berbagai lingkungan melalui file parameter tunggal.
  ✓ Kita ingin mengelola versi rilis aplikasi dengan kemampuan rollback instan ke versi sebelumnya jika terjadi kegagalan.

KAPAN LEBIH BAIK MENULIS MANIFEST MANUAL:
  ✗ Untuk microservices internal buatan kita sendiri yang sangat sederhana dan tidak memiliki rencana dibagikan ke tim luar (menulis YAML k8s murni di Ansible lebih praktis).

Cara Kerja Integrasi Ansible dan Helm #

Menggunakan Ansible untuk mengendalikan Helm memberikan keuntungan besar dibandingkan jika kita hanya menulis skrip shell pembungkus seperti helm upgrade --install.

flowchart TD
    A["Ansible Playbook Execution"] --> B["kubernetes.core.helm Module"]
    B -->|"Membaca Kubeconfig & Helm Binary"| C["Gerbang API Kubernetes"]
    C -->|"Deploy / Upgrade / Rollback"| D["Helm Release di Cluster K8s"]

Ketika kita menggunakan modul kubernetes.core.helm, Ansible akan:

  1. Memverifikasi apakah rilis Helm sudah ada di kluster.
  2. Melakukan perbandingan (diff) antara konfigurasi values saat ini dengan konfigurasi baru yang kita deklarasikan di playbook.
  3. Hanya mengirimkan perubahan yang diperlukan ke API Server Kubernetes (menjaga sifat idempotency).
  4. Menyediakan alur penanganan error jika proses deployment stuck, dengan kemampuan memicu rollback otomatis.

Langkah 1: Instalasi Helm Binary Menggunakan Ansible #

Agar modul Helm di Ansible dapat berjalan, mesin tempat task dijalankan (bisa di localhost atau server target) harus sudah memiliki file binari helm terinstal. Kita dapat menulis task Ansible sederhana untuk mengunduh script installer resmi dan memasang Helm secara otomatis dan idempoten.

# playbooks/install-helm.yml
---
- name: Instalasi Helm CLI di Host Target
  hosts: control_plane
  become: true
  tasks:
    - name: Cek apakah Helm sudah terinstal
      stat:
        path: /usr/local/bin/helm
      register: helm_binary_check

    - name: Unduh script installer resmi Helm
      get_url:
        url: https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
        dest: /tmp/get-helm-3.sh
        mode: '0700'
      when: not helm_binary_check.stat.exists

    - name: Jalankan installer Helm
      command: /tmp/get-helm-3.sh
      when: not helm_binary_check.stat.exists
      changed_when: true

    - name: Verifikasi instalasi dan tampilkan versi Helm
      command: /usr/local/bin/helm version --short
      register: helm_version_output
      changed_when: false

    - name: Tampilkan output versi Helm
      debug:
        msg: "Helm sukses terinstal: {{ helm_version_output.stdout }}"

Langkah 2: Mengelola Helm Repositories #

Sebelum kita dapat memasang paket Chart, kita harus menambahkan alamat repositori pembuat Chart tersebut ke dalam daftar repositori lokal kita. Modul kubernetes.core.helm_repository memungkinkan kita mengelola daftar ini secara deklaratif.

# playbooks/deploy-helm-apps.yml
---
- name: Kelola Helm dan Deploy Chart
  hosts: localhost
  connection: local
  gather_facts: false
  vars:
    k8s_kubeconfig: "{{ playbook_dir }}/kubeconfig/admin.conf"

  tasks:
    - name: Tambahkan repositori Helm pihak ketiga yang dibutuhkan
      kubernetes.core.helm_repository:
        name: "{{ item.name }}"
        repo_url: "{{ item.url }}"
        state: present
      loop:
        - { name: "ingress-nginx", url: "https://kubernetes.github.io/ingress-nginx" }
        - { name: "bitnami",       url: "https://charts.bitnami.com/bitnami" }
        - { name: "prometheus-community", url: "https://prometheus-community.github.io/helm-charts" }

    - name: Perbarui database Chart lokal (helm repo update)
      command: helm repo update
      changed_when: false

Langkah 3: Deploy Helm Chart dengan Kustomisasi Values Inline #

Setelah repositori siap, kita dapat mendeploy Chart pilihan kita. Pada contoh di bawah ini, kita akan memasang Nginx Ingress Controller ke dalam namespace khusus bernama ingress-nginx.

[!TIP] Di lingkungan produksi, selalu tentukan versi Chart secara spesifik menggunakan parameter chart_version. Jika kita tidak menyetel versi, Helm akan otomatis mengambil versi terbaru yang tersedia. Hal ini berisiko merusak sistem (breaking change) ketika playbook kita jalankan kembali di masa depan.

    - name: Deploy Nginx Ingress Controller secara idempoten
      kubernetes.core.helm:
        kubeconfig: "{{ k8s_kubeconfig }}"
        name: my-nginx-ingress
        chart_ref: ingress-nginx/ingress-nginx
        chart_version: "4.9.0" # Mengunci versi Chart demi stabilitas
        release_namespace: ingress-nginx
        create_namespace: true
        state: present
        # Kustomisasi nilai parameter default (values.yaml) secara inline
        values:
          controller:
            replicaCount: 2
            service:
              type: LoadBalancer
            resources:
              requests:
                cpu: "100m"
                memory: "120Mi"
              limits:
                cpu: "300m"
                memory: "256Mi"

Langkah 4: Manajemen Variabel Sensitif dengan Ansible Vault #

Banyak Chart aplikasi pihak ketiga yang membutuhkan data sensitif seperti password admin, kunci enkripsi, atau token integrasi database. Kita tidak boleh menulis parameter sensitif ini secara terbuka di kode playbook.

Kita harus menggunakan Ansible Vault untuk mengenkripsi password tersebut, lalu meneruskannya secara dinamis ke blok values di modul Helm. Kita juga wajib menyertakan parameter no_log: true pada task tersebut untuk menyembunyikan parameter sensitif dari sistem logging terminal.

# ANTI-PATTERN: Menulis password mentah di blok values playbook
# Password ini akan terekspos di layar console CI/CD dan sistem monitoring log lainnya
- name: Deploy Database dengan password terekspos (JANGAN LALUKAN)
  kubernetes.core.helm:
    kubeconfig: "{{ k8s_kubeconfig }}"
    name: bad-db
    chart_ref: bitnami/postgresql
    state: present
    values:
      auth:
        postgresPassword: "password-rahasia-123" # ✗ Bahaya kebocoran kredensial

# BENAR: Mengambil password terenkripsi dari Ansible Vault dan menyembunyikan log task
# Kredensial aman terenkripsi di Git dan log terminal dilindungi dari kebocoran
- name: Deploy PostgreSQL Database dengan Proteksi Kredensial (Sistem Rekomendasi)
  kubernetes.core.helm:
    kubeconfig: "{{ k8s_kubeconfig }}"
    name: prod-database
    chart_ref: bitnami/postgresql
    chart_version: "13.4.0"
    release_namespace: database
    create_namespace: true
    state: present
    values:
      auth:
        database: "production_db"
        username: "app_user"
        postgresPassword: "{{ vault_postgresql_admin_password }}" # ✓ Mengambil dari Vault
        password: "{{ vault_postgresql_user_password }}"         # ✓ Mengambil dari Vault
      primary:
        persistence:
          size: "20Gi"
    # Sembunyikan output task dari terminal console
    no_log: true

Langkah 5: Menggunakan File Values Eksternal dan Multi-Values #

Untuk aplikasi yang membutuhkan konfigurasi yang sangat besar dan detail (misalnya tumpukan pemantauan Prometheus Stack), menulis seluruh parameter secara inline di playbook akan membuat kode playbook menjadi sangat panjang dan sulit dibaca.

Cara terbaik untuk mengatasi masalah ini adalah dengan memisahkan konfigurasi ke dalam satu atau beberapa file YAML eksternal, lalu memanggilnya menggunakan parameter values_files. Kita juga dapat menggabungkan file konfigurasi dasar dengan file konfigurasi spesifik environment (pola override).

    - name: Deploy Prometheus Monitoring Stack dengan File Values Eksternal
      kubernetes.core.helm:
        kubeconfig: "{{ k8s_kubeconfig }}"
        name: monitoring-stack
        chart_ref: prometheus-community/kube-prometheus-stack
        chart_version: "55.5.0"
        release_namespace: monitoring
        create_namespace: true
        state: present
        values_files:
          # File konfigurasi global dasar untuk seluruh kluster
          - "{{ playbook_dir }}/helm-values/prometheus-base-values.yml"
          # File konfigurasi spesifik untuk environment produksi (meng-override parameter base)
          - "{{ playbook_dir }}/helm-values/prometheus-prod-overrides.yml"

Contoh isi file prometheus-prod-overrides.yml:

# helm-values/prometheus-prod-overrides.yml
grafana:
  enabled: true
  adminPassword: "{{ vault_grafana_admin_password }}" # Variabel Ansible dinamis tetap dapat di-render di dalam file values!
  persistence:
    enabled: true
    size: 10Gi

prometheus:
  prometheusSpec:
    retention: 14d
    storageSpec:
      volumeClaimTemplate:
        spec:
          resources:
            requests:
              storage: 50Gi

Siklus Hidup Helm: Upgrade, Tunggu, dan Rollback Otomatis #

Secara default, jika rilis Helm sudah ada di kluster, modul kubernetes.core.helm akan melakukan pembaruan (upgrade) jika mendeteksi adanya perubahan versi Chart atau nilai konfigurasi values.

Namun, ada masalah umum di mana Kubernetes API melaporkan bahwa proses upgrade berhasil diterima, padahal Pod baru di lapangan mengalami crash saat booting. Untuk memastikan deployment kita benar-benar siap saji, kita harus menyetel parameter berikut:

  • wait: true: Memaksa Ansible memblokir proses eksekusi dan menunggu hingga seluruh Pod, Service, dan Ingress di bawah Chart tersebut berada dalam kondisi aktif dan sehat sebelum menganggap task sukses.
  • wait_timeout: Batas waktu tunggu maksimal (misal: “10m”). Jika terlampaui, proses dianggap gagal.
  • atomic: true: Sangat penting di produksi. Jika dikombinasikan dengan wait: true, parameter ini akan menjamin bahwa jika proses upgrade mengalami kegagalan (misal: Pod baru crash), Helm akan otomatis memicu rollback instan ke versi rilis stabil sebelumnya secara bersih.
    - name: Upgrade Nginx Ingress dengan Strategi Atomic Rollback
      kubernetes.core.helm:
        kubeconfig: "{{ k8s_kubeconfig }}"
        name: my-nginx-ingress
        chart_ref: ingress-nginx/ingress-nginx
        chart_version: "4.10.0" # Menaikkan versi Chart
        release_namespace: ingress-nginx
        state: present
        wait: true # Tunggu hingga seluruh pod baru siap
        wait_timeout: "10m" # Timeout 10 menit
        atomic: true # Rollback otomatis ke versi sebelumnya jika gagal!
        values:
          controller:
            replicaCount: 3 # Menambah replika menjadi 3

Setelah rilis diperbarui, kita dapat memantau status rilis tersebut menggunakan modul kubernetes.core.helm_info untuk memastikan keadaan akhir sistem.

    - name: Ambil status informasi dari rilis Helm
      kubernetes.core.helm_info:
        kubeconfig: "{{ k8s_kubeconfig }}"
        name: my-nginx-ingress
        release_namespace: ingress-nginx
      register: ingress_release_info

    - name: Tampilkan status rilis Helm saat ini
      debug:
        msg: 
          - "Release Name: {{ ingress_release_info.status.name }}"
          - "Status Rilis: {{ ingress_release_info.status.status }}"
          - "Versi Aplikasi: {{ ingress_release_info.status.app_version }}"
      when: ingress_release_info.status is defined

Penghapusan Release (State Absent) #

Jika kita ingin membersihkan kluster dari aplikasi yang sudah tidak digunakan lagi, kita dapat menghapusnya secara bersih dengan menyetel parameter state: absent. Perintah ini akan menghapus seluruh resource Kubernetes yang pernah dibuat oleh Chart tersebut secara otomatis.

    - name: Hapus rilis Helm database lama dari kluster
      kubernetes.core.helm:
        kubeconfig: "{{ k8s_kubeconfig }}"
        name: legacy-database
        release_namespace: database
        state: absent

Ringkasan #

  • Helm bertindak sebagai package manager resmi Kubernetes yang membungkus manifest YAML kompleks menjadi satu kesatuan unit Chart yang terstandardisasi.
  • Gunakan modul kubernetes.core.helm secara deklaratif untuk mengotomasi alur install, upgrade, dan uninstall aplikasi pihak ketiga secara idempoten.
  • Selalu kunci versi Chart (chart_version) dalam playbook produksi demi menghindari pembaruan otomatis yang tidak diinginkan dan berisiko merusak kompatibilitas.
  • Integrasikan Ansible Vault untuk menyimpan kredensial database dan API key Chart, serta sertakan parameter no_log: true guna mencegah bocornya data rahasia ke terminal log.
  • Gunakan parameter values_files untuk memisahkan konfigurasi parameter yang sangat besar (seperti monitoring stack) ke file YAML eksternal agar kode playbook tetap bersih dan mudah dipelihara.
  • Setel parameter wait: true dan atomic: true saat melakukan upgrade untuk memicu proses rollback otomatis ke versi stabil sebelumnya jika rilis baru mengalami kegagalan booting.
  • Manfaatkan modul kubernetes.core.helm_info untuk memverifikasi status operasional akhir dari rilis aplikasi pasca deployment.

← Sebelumnya: Deploy Manifest   Berikutnya: Cluster Maintenance →

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