Configuration Hot Reload #

Restart Pod setiap kali konfigurasi berubah menyebabkan downtime singkat dan mengganggu koneksi yang sedang berjalan. Hot reload memungkinkan aplikasi memperbarui konfigurasinya tanpa perlu restart — Pod tetap berjalan, koneksi tidak terputus, dan perubahan konfigurasi langsung berlaku. Namun hot reload tidak selalu lebih baik dari restart; ada trade-off yang perlu dipahami.

Cara Kubernetes Memperbarui ConfigMap Volume #

Saat ConfigMap yang di-mount sebagai volume diperbarui, Kubernetes secara otomatis memperbarui file di dalam container — tanpa restart Pod. Mekanismenya menggunakan atomic symlink swap:

Sebelum update:
/etc/config/
  ..data → ..2024_01_15_10_00_00/    (symlink ke direktori lama)
  app.yaml → ..data/app.yaml          (symlink ke file)

ConfigMap diperbarui via: kubectl apply -f new-configmap.yaml

Proses update (kubelet sync period, default ~1 menit):
  1. Kubernetes buat direktori timestamp baru: ..2024_01_15_11_00_00/
  2. Tulis file baru ke direktori baru
  3. Atomik: update symlink ..data ke direktori baru
  4. File lama masih ada sampai dibersihkan

Setelah update:
/etc/config/
  ..data → ..2024_01_15_11_00_00/    (symlink ke direktori baru)
  app.yaml → ..data/app.yaml          (masih symlink yang sama, tapi sekarang menunjuk ke file baru)

Perubahan ini terjadi tanpa restart container. Tapi aplikasi tetap harus membaca ulang file untuk mendapat konfigurasi baru.


Pola 1: inotify — Deteksi Perubahan File di Aplikasi #

Cara paling langsung: aplikasi secara aktif memantau perubahan file konfigurasi menggunakan inotify (Linux kernel facility) atau abstraksi di atasnya.

# Python: menggunakan watchdog library
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import yaml, threading

class ConfigHandler(FileSystemEventHandler):
    def __init__(self, app):
        self.app = app

    def on_modified(self, event):
        if event.src_path.endswith('app.yaml'):
            self.app.reload_config()

class App:
    def __init__(self):
        self.config = self.load_config()
        self.start_config_watcher()

    def load_config(self):
        with open('/etc/config/app.yaml') as f:
            return yaml.safe_load(f)

    def reload_config(self):
        try:
            new_config = self.load_config()
            self.config = new_config
            print(f"Config reloaded: {self.config}")
        except Exception as e:
            print(f"Failed to reload config, keeping old: {e}")

    def start_config_watcher(self):
        handler = ConfigHandler(self)
        observer = Observer()
        observer.schedule(handler, '/etc/config/', recursive=False)
        observer.start()
// Go: menggunakan fsnotify
import "github.com/fsnotify/fsnotify"

func watchConfig(configPath string, onReload func()) {
    watcher, _ := fsnotify.NewWatcher()
    defer watcher.Close()

    watcher.Add(filepath.Dir(configPath))

    for {
        select {
        case event := <-watcher.Events:
            // Kubernetes update symlink, bukan file langsung
            // Pantau event Create dan Chmod selain Write
            if event.Op&(fsnotify.Create|fsnotify.Write|fsnotify.Chmod) != 0 {
                onReload()
            }
        }
    }
}

Pola 2: SIGHUP Signal untuk Reload #

Banyak server (nginx, haproxy, prometheus) mendukung reload konfigurasi via signal SIGHUP — tanpa restart proses, tanpa memutus koneksi aktif:

# Kubernetes bisa kirim signal ke container via lifecycle hook
# atau via sidecar yang mengirim signal saat file berubah

spec:
  containers:
  - name: nginx
    image: nginx:1.25
    volumeMounts:
    - name: nginx-config
      mountPath: /etc/nginx/conf.d
    lifecycle:
      # Saat konfigurasi di-update dan Pod di-restart (graceful):
      preStop:
        exec:
          command: ["/usr/sbin/nginx", "-s", "quit"]
# Kirim SIGHUP ke nginx untuk reload konfigurasi tanpa restart
kubectl exec deployment/nginx -- nginx -s reload
# atau:
kubectl exec deployment/nginx -- kill -HUP 1

Untuk otomatisasi, gunakan sidecar yang memantau perubahan ConfigMap dan kirim signal ke container utama.


Pola 3: Sidecar Config Watcher #

Sidecar container yang bertugas memantau perubahan file dan mengirim signal ke container utama:

spec:
  volumes:
  - name: config
    configMap:
      name: app-config

  containers:
  # Container utama
  - name: nginx
    image: nginx:1.25
    volumeMounts:
    - name: config
      mountPath: /etc/nginx/conf.d

  # Sidecar config watcher
  - name: config-reloader
    image: jimmidyson/configmap-reload:v0.9.0
    args:
    - --volume-dir=/etc/nginx/conf.d    # direktori yang dipantau
    - --webhook-url=http://localhost:9113/-/reload  # endpoint reload
    # atau kirim signal:
    # - --webhook-method=POST
    volumeMounts:
    - name: config
      mountPath: /etc/nginx/conf.d
      readOnly: true

Pola 4: Polling Periodik #

Untuk aplikasi yang tidak mendukung file watching, bisa gunakan polling periodik — cek perubahan setiap N detik:

import threading, yaml, hashlib, time

class ConfigPoller:
    def __init__(self, config_path, on_change, interval=30):
        self.config_path = config_path
        self.on_change = on_change
        self.interval = interval
        self.last_hash = self._hash_file()
        threading.Thread(target=self._poll, daemon=True).start()

    def _hash_file(self):
        with open(self.config_path, 'rb') as f:
            return hashlib.md5(f.read()).hexdigest()

    def _poll(self):
        while True:
            time.sleep(self.interval)
            current_hash = self._hash_file()
            if current_hash != self.last_hash:
                self.last_hash = current_hash
                self.on_change()

Kapan Restart Pod Lebih Baik dari Hot Reload #

Hot reload tidak selalu tepat. Ada situasi di mana restart Pod lebih aman dan lebih predictable:

Restart Pod lebih baik jika:

  Konfigurasi startup yang kompleks:
  → Beberapa framework membaca konfigurasi hanya saat startup
  → Memaksa hot reload bisa menyebabkan state yang tidak konsisten
  → Contoh: thread pool size, connection pool configuration

  Perubahan yang memerlukan re-initialization:
  → Ganti database host → semua koneksi harus di-reconnect
  → Hot reload partial lebih berbahaya dari restart bersih

  Aplikasi yang tidak dirancang untuk hot reload:
  → Memaksa hot reload di aplikasi yang tidak mendukungnya
    bisa menyebabkan behavior yang tidak terduga

  Secret yang berubah:
  → Env var dari Secret tidak auto-update → harus restart Pod
  → Volume mount Secret auto-update, tapi aplikasi tetap harus support reload

Cara trigger restart yang controlled:
  kubectl rollout restart deployment/api -n production
  → Rolling restart — Pod baru dimulai sebelum yang lama dihapus
  → Zero downtime jika replicas > 1 dan readinessProbe dikonfigurasi

Trigger Restart Otomatis saat ConfigMap Berubah #

Untuk aplikasi yang tidak mendukung hot reload, bisa gunakan annotation checksum untuk trigger rolling restart saat ConfigMap berubah:

spec:
  template:
    metadata:
      annotations:
        # Checksum ConfigMap — berubah saat ConfigMap berubah → rolling restart
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}

Ini pola umum di Helm chart — saat ConfigMap diperbarui, checksum berubah, annotation Pod berubah, dan Kubernetes otomatis melakukan rolling restart Deployment.


Ringkasan #

  • Kubernetes auto-update volume ConfigMap via symlink swap — file dalam container diperbarui tanpa restart Pod dalam ~1 menit; tapi aplikasi harus membaca ulang file.
  • inotify/fsnotify untuk deteksi perubahan langsung — lebih efisien dari polling; perhatikan bahwa Kubernetes update symlink bukan file langsung, pantau event Create dan Chmod juga.
  • SIGHUP untuk server yang mendukung — nginx, haproxy, prometheus mendukung reload via SIGHUP; kirim signal tanpa restart proses utama, koneksi aktif tidak terputus.
  • Sidecar config watcher sebagai solusi universalconfigmap-reload sidecar yang memantau direktori dan mengirim HTTP webhook atau signal saat file berubah.
  • Restart Pod untuk konfigurasi startup yang kompleks — tidak semua konfigurasi cocok di-reload secara hot; perubahan yang memerlukan re-initialization lebih aman dengan restart bersih.
  • Helm checksum annotation untuk auto-restart — pola umum di Helm chart untuk trigger rolling restart Deployment saat ConfigMap berubah, tanpa perlu intervensi manual.

← Sebelumnya: ConfigMap vs Secret   Berikutnya: Multi-Environment Configuration →

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