ConfigMap #

Di dalam arsitektur aplikasi terdistribusi modern, pemisahan yang ketat antara kode logika aplikasi dengan parameter konfigurasi adalah sebuah keharusan. Prinsip ini diabadikan sebagai pilar ketiga dalam metodologi 12-Factor App yang menyatakan bahwa seluruh konfigurasi harus disimpan di dalam lingkungan eksekusi (environment), bukan di dalam kode sumber (hardcoded). Kubernetes memfasilitasi kebutuhan ini secara elegan melalui objek yang disebut ConfigMap.

ConfigMap adalah sumber daya (resource) Kubernetes yang dirancang khusus untuk menyimpan data konfigurasi non-sensitif dalam bentuk pasangan kunci-nilai (key-value pairs). Dengan menggunakan ConfigMap, kita dapat membangun satu citra kontainer (Docker image) tunggal yang bersifat generik, kemudian menjalankannya di berbagai lingkungan kerja yang berbeda—seperti development, staging, dan production—hanya dengan menyuntikkan ConfigMap yang berbeda di setiap lingkungan tersebut. Pendekatan ini tidak hanya menghemat waktu pembangunan citra (build time), tetapi juga menjamin konsistensi perilisan karena citra yang diuji di staging adalah citra yang persis sama dengan yang berjalan di produksi.


Anatomi ConfigMap #

Secara struktural, manifest YAML sebuah ConfigMap terbagi menjadi dua bagian utama di bawah blok spesifikasi data: data untuk nilai-nilai tekstual standar, dan binaryData untuk menyimpan konten biner (seperti berkas biner kecil atau berkas konfigurasi terenkripsi) dalam format Base64.

Mari kita pelajari contoh manifest ConfigMap komprehensif di bawah ini yang memuat parameter kunci tunggal serta berkas konfigurasi multi-baris (multi-line configuration files):

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-gateway-config
  namespace: production
data:
  # Parameter kunci-nilai sederhana
  DATABASE_TIMEOUT: "30s"
  MAX_CONNECTIONS: "150"
  LOG_LEVEL: "info"
  APP_ENV: "production"

  # File konfigurasi Nginx utuh yang disematkan sebagai blok teks multi-baris
  nginx.conf: |
    user nginx;
    worker_processes auto;
    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;
    events {
      worker_connections 1024;
    }
    http {
      include /etc/nginx/mime.types;
      default_type application/octet-stream;
      sendfile on;
      keepalive_timeout 65;
      server {
        listen 80;
        server_name api.internal.local;
        location / {
          proxy_pass http://localhost:8080;
        }
      }
    }    

  # File konfigurasi aplikasi YAML internal
  app-settings.yaml: |
    cache:
      provider: redis
      ttl: 3600
      redis:
        host: redis-master.production.svc.cluster.local
        port: 6379    

Metode Pembuatan ConfigMap #

Kubernetes mengizinkan kita untuk membuat ConfigMap baik menggunakan pendekatan imperatif langsung lewat perintah CLI kubectl maupun pendekatan deklaratif menggunakan berkas manifes YAML. Untuk kebutuhan operasional produksi skala besar, pendekatan deklaratif wajib kita gunakan karena mendukung prinsip infrastructure as code (IaC) dan terintegrasi dengan pipeline GitOps.

Perbandingan Pembuatan Konfigurasi #

Berikut adalah perbedaan antara membuat konfigurasi secara imperatif manual di terminal produksi (anti-pattern) dan membuat konfigurasi terstruktur secara deklaratif (solusi):

# ANTI-PATTERN: Membuat ConfigMap secara imperatif langsung di kluster produksi
# Tindakan ini tidak meninggalkan rekam jejak di Git, mempersulit pemulihan bencana (disaster recovery)
kubectl create configmap app-config \
  --from-literal=DB_TIMEOUT=30s \
  --from-file=nginx.conf=/tmp/nginx.conf \
  -n production

# BENAR: Buat manifes YAML secara deklaratif dan terapkan menggunakan kubectl apply
# ✓ Pendekatan ini melacak perubahan di Git dan mendukung rollback konfigurasi
kubectl apply -f /deployments/production/config/app-gateway-config.yaml

Untuk keperluan pengembangan lokal cepat, kita juga bisa membuat ConfigMap secara dinamis dari satu direktori yang berisi sekumpulan berkas konfigurasi:

# Membuat ConfigMap dari seluruh berkas yang ada di dalam folder ./configs
kubectl create configmap app-settings-dir --from-file=./configs/ -n development

Dalam perintah di atas, setiap nama berkas di dalam direktori ./configs akan otomatis menjadi kunci (key), dan seluruh isi dari berkas tersebut akan menjadi nilai (value) di dalam objek ConfigMap yang dihasilkan.


Menggunakan ConfigMap sebagai Environment Variable #

Salah satu cara paling umum untuk mengonsumsi data ConfigMap di dalam Pod adalah dengan menyuntikkannya sebagai variabel lingkungan (environment variables) kontainer. Kubernetes menyediakan dua mekanisme utama untuk melakukan ini: menyuntikkan entri spesifik menggunakan parameter valueFrom, atau memuat seluruh entri ConfigMap sekaligus menggunakan envFrom.

Perbandingan Metode Injeksi Variabel #

Berikut adalah contoh perbandingan antara memuat variabel secara manual satu per satu yang tidak efisien (anti-pattern) dengan memuat seluruh grup konfigurasi secara dinamis (solusi):

# ANTI-PATTERN: Menyuntikkan puluhan parameter secara manual satu per satu
# ✗ Membuat manifest Pod membengkak dan sulit dirawat jika ada penambahan parameter baru
apiVersion: v1
kind: Pod
metadata:
  name: app-pod-inefficient
spec:
  containers:
  - name: app
    image: my-app:v1.0
    env:
    - name: DB_TIMEOUT
      valueFrom:
        configMapKeyRef:
          name: app-gateway-config
          key: DATABASE_TIMEOUT
    - name: MAX_CONN
      valueFrom:
        configMapKeyRef:
          name: app-gateway-config
          key: MAX_CONNECTIONS
    - name: LOG_LEVEL
      valueFrom:
        configMapKeyRef:
          name: app-gateway-config
          key: LOG_LEVEL
---
# BENAR: Suntikkan seluruh kunci ConfigMap secara massal menggunakan envFrom
# ✓ Sangat bersih, otomatis memetakan setiap kunci ConfigMap menjadi variabel lingkungan
apiVersion: v1
kind: Pod
metadata:
  name: app-pod-efficient
spec:
  containers:
  - name: app
    image: my-app:v1.0
    envFrom:
    - configMapRef:
        name: app-gateway-config

[!WARNING] Keterbatasan utama dari metode variabel lingkungan adalah sifatnya yang statis. Jika kita memperbarui isi ConfigMap di etcd, variabel lingkungan di dalam kontainer yang sedang berjalan tidak akan berubah. Kita harus memulai ulang kontainer (pod restart) agar proses aplikasi dapat membaca nilai variabel lingkungan yang baru.


Menggunakan ConfigMap sebagai Volume Mount #

Jika konfigurasi kita berukuran besar, terdiri dari struktur berkas direktori, atau membutuhkan pembaruan dinamis tanpa me-restart Pod, pendekatan terbaik adalah me-mount ConfigMap sebagai berkas fisik di dalam sistem penyimpanan kontainer menggunakan mekanisme Volume Mount.

Ketika kita mendefinisikan volume berbasis ConfigMap, Kubernetes akan membuat direktori virtual di dalam kontainer dan memproyeksikan setiap kunci di dalam ConfigMap menjadi sebuah berkas fisik.

Manifest Implementasi Volume Mount ConfigMap #

Berikut adalah contoh manifes Deployment yang me-mount kunci-kunci spesifik ConfigMap ke direktori konfigurasi aplikasi:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-gateway
  namespace: production
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web-gateway
  template:
    metadata:
      labels:
        app: web-gateway
    spec:
      volumes:
      - name: gateway-config-volume
        configMap:
          name: app-gateway-config
          # Tentukan hak akses POSIX default untuk berkas (read-only bagi non-root)
          defaultMode: 420  # Setara dengan oktal 0644
          items:
          - key: nginx.conf
            path: nginx.conf  # Nama berkas fisik di dalam volume
          - key: app-settings.yaml
            path: settings/config.yaml  # Menempatkan berkas ke sub-path internal
      containers:
      - name: nginx-proxy
        image: nginx:1.25.3-alpine
        volumeMounts:
        - name: gateway-config-volume
          mountPath: /etc/nginx/config  # Jalur mount di dalam kontainer
          readOnly: true

Risiko Overwriting Direktori dengan Volume Mount #

Saat kita me-mount sebuah volume langsung ke direktori yang sudah ada di dalam kontainer (misalnya /etc/nginx), seluruh konten asli yang bawaan dari citra kontainer di dalam direktori tersebut akan disembunyikan dan ditimpa oleh file dari ConfigMap.

Jika kita hanya ingin menyisipkan satu file konfigurasi ke dalam direktori sistem tanpa menghilangkan berkas penting lainnya, kita memiliki dua pilihan solusi:

  1. Menggunakan Sub-direktori Baru: Jangan me-mount langsung ke /etc/nginx, melainkan mount ke /etc/nginx/conf.d atau direktori kustom lain yang dibaca oleh aplikasi.
  2. Menggunakan properti subPath: Kita bisa menentukan subPath pada parameter volumeMounts untuk memproyeksikan file tunggal tanpa menimpa direktori. Namun, perhatikan bahwa penggunaan subPath mematikan fitur auto-update yang dijelaskan di bawah ini.

Keunggulan utama dari me-mount ConfigMap sebagai Volume dibandingkan menyuntikkannya sebagai variabel lingkungan adalah kemampuannya untuk melakukan pembaruan berkas secara dinamis (hot reload) tanpa memerlukan restart Pod.

Bagaimana Kubelet Memperbarui File secara Atomik #

Ketika kita memperbarui data ConfigMap di API Server, agen kubelet di setiap node worker akan mendeteksi perubahan tersebut pada siklus sinkronisasi berikutnya (secara default berkisar antara 1 hingga 2 menit). Kubelet tidak langsung menulis ulang file yang sedang dibaca kontainer untuk menghindari kondisi korupsi berkas setengah tertulis (partial writes). Kubelet menerapkan teknik pertukaran tautan simbolik (symlink swap) secara atomik.

Mari kita lihat struktur representasi berkas di dalam direktori kontainer saat volume ConfigMap di-mount:

/etc/nginx/config/
  ├── ..2026_06_17_07_00_00.000000000/  <-- Direktori aktual versi 1
  │     ├── nginx.conf
  │     └── app-settings.yaml
  ├── ..data ──> ..2026_06_17_07_00_00.000000000/  <-- Symlink penunjuk data aktif
  ├── nginx.conf ──> ..data/nginx.conf  <-- Symlink berkas ke file aktual
  └── app-settings.yaml ──> ..data/app-settings.yaml

Ketika kita melakukan perubahan data ConfigMap, proses sinkronisasi kubelet akan berjalan sebagai berikut:

Langkah 1: Kubelet membuat direktori timestamp baru (versi 2)
  /etc/nginx/config/..2026_06_17_07_20_00.999999999/
        ├── nginx.conf (data baru)
        └── app-settings.yaml

Langkah 2: Kubelet mengubah arah tautan symlink "..data" secara atomik ke direktori baru
  ..data ──> ..2026_06_17_07_20_00.999999999/

Langkah 3: Direktori versi lama (versi 1) dihapus dari sistem berkas kontainer

Karena aplikasi membaca file melalui rantai symlink nginx.conf -> ..data/nginx.conf, aplikasi akan langsung melihat konten baru begitu langkah 2 selesai. Namun, jika aplikasi kita menggunakan pustaka yang melakukan caching file konfigurasi ke dalam memori saat startup, aplikasi tetap tidak akan menyadari perubahan ini sampai ia menerima sinyal reload (seperti SIGHUP) atau dipicu oleh watcher eksternal.


Immutable ConfigMap untuk Optimasi Skala Besar #

Secara default, Kubernetes memantau setiap ConfigMap untuk mendeteksi adanya pembaruan data agar file di volume mount dapat disinkronkan. Namun, untuk aplikasi berskala besar dengan ribuan Pod, proses pemantauan berkala (watching) ini menghasilkan beban lalu lintas kueri (API overhead) yang signifikan pada kontrol plane.

Jika kita memiliki konfigurasi yang bersifat statis dan tidak pernah berubah selama masa hidup deployment (misalnya berkas konfigurasi sistem bawaan), kita bisa menyetel properti immutable: true.

apiVersion: v1
kind: ConfigMap
metadata:
  name: static-system-settings
  namespace: production
immutable: true  # Setelah dibuat, data di bawah ini tidak dapat diubah lagi
data:
  SYSTEM_ARCH: "x86_64"
  KERNEL_VERSION: "5.15"

Keuntungan Teknis Immutable ConfigMap: #

  1. Reduksi Beban API Server: Kubelet di node worker tidak akan lagi melakukan kueri watch ke API Server untuk memantau ConfigMap ini. Ini secara drastis mengurangi latensi jaringan internal kluster pada kluster skala besar.
  2. Perlindungan Konfigurasi: Menghindari kesalahan manusia (human error) akibat ketidaksengajaan mengubah parameter konfigurasi kritis yang dapat membuat aplikasi crash. Jika kita butuh mengubah konfigurasi, kita dipaksa membuat ConfigMap baru dengan nama baru (pola versioning).

Batasan Ukuran dan Ruang Lingkup ConfigMap #

Meskipun fleksibel, ConfigMap memiliki beberapa batasan kritis yang wajib kita pahami sebelum merancang arsitektur penyimpanan konfigurasi kluster:

  • Batasan Ukuran 1 Megabyte (MB): ConfigMap disimpan langsung di dalam database etcd Kubernetes. Untuk menjaga performa baca-tulis etcd tetap optimal, Kubernetes membatasi ukuran data maksimum satu objek ConfigMap sebesar 1 MB. Jika kita perlu memuat file konfigurasi yang sangat besar (seperti database GeoIP sebesar 50MB), jangan gunakan ConfigMap. Gunakan volume persistent eksternal atau download file tersebut saat startup menggunakan init container.
  • Bukan untuk Data Sensitif: Data di dalam ConfigMap disimpan dalam bentuk plain text tanpa enkripsi apa pun di etcd. Siapa saja yang memiliki akses RBAC untuk melihat ConfigMap dapat membaca isinya. Jangan pernah menyimpan password, token, atau private keys di ConfigMap. Gunakan objek Secret untuk keperluan ini.
  • Terikat Namespace (Namespace-Scoped): Objek ConfigMap hanya ada di dalam namespace tempat ia dibuat. Pod di namespace production tidak dapat merujuk atau me-mount ConfigMap yang berada di namespace development. Untuk berbagi konfigurasi global, kita harus menduplikasinya di setiap namespace atau memanfaatkan operator eksternal.

Pola: Pembaruan Aman Melalui Versioning ConfigMap #

Salah satu bahaya terbesar dalam memperbarui ConfigMap secara langsung (in-place update) adalah hilangnya kendali atas waktu penerapan konfigurasi. Karena kubelet mensinkronisasikan perubahan volume secara acak (tergantung siklus sinkronisasi node masing-masing), sebagian Pod kita mungkin akan berjalan menggunakan konfigurasi baru sementara sebagian lainnya masih menggunakan konfigurasi lama. Jika konfigurasi baru tersebut mengandung kesalahan ketik, aplikasi akan crash secara acak dan sulit untuk di-rollback secara instan.

Pola terbaik untuk mengatasi masalah ini adalah dengan menerapkan Versioning ConfigMap.

POLA VERSIONING CONFIGMAP (Aman & Terkendali):

  Langkah 1: Terapkan ConfigMap baru dengan suffix versi: "app-config-v2"
  Langkah 2: Perbarui referensi ConfigMap di manifest Deployment ke "app-config-v2"
  Langkah 3: Kubernetes memicu rolling update resmi:
             - Pod baru dibuat dengan config-v2 (diverifikasi readiness probe)
             - Pod lama dengan config-v1 tetap berjalan sampai Pod baru sehat
             - Rollback instan tinggal mengarahkan kembali Deployment ke config-v1

Mari kita bandingkan manifest pembaruan antara pendekatan in-place update yang berbahaya (anti-pattern) dengan pola versioning (solusi):

# ANTI-PATTERN: Memperbarui isi ConfigMap yang sama secara langsung di kluster
# ✗ Memicu transisi konfigurasi yang tidak sinkron dan merusak mekanisme rollback otomatis
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-shared  # Nama tetap sama, hanya nilainya yang diubah manual
data:
  APP_THEME: "dark-blue-broken-typo"  # Kesalahan input parameter
---
# BENAR: Buat objek ConfigMap baru dan perbarui referensi di Deployment
# ✓ Mengaktifkan siklus rolling update standar dan memastikan keamanan rollback
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-v2  # Menambahkan versi baru pada nama objek
  namespace: production
data:
  APP_THEME: "dark-blue"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: billing-app
  namespace: production
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: billing
        image: billing:v1.2.0
        envFrom:
        - configMapRef:
            name: app-config-v2  # Rujuk ke versi baru yang aman

Dengan mengadopsi pola versioning, kita dapat memastikan bahwa setiap perubahan konfigurasi melewati siklus pengujian rolling update yang sama ketatnya dengan perubahan kode aplikasi, meminimalkan risiko downtime di lingkungan produksi.


Ringkasan #

  • Pemisahan konfigurasi adalah kunci: Gunakan ConfigMap untuk mengimplementasikan prinsip 12-Factor App dengan memisahkan berkas konfigurasi non-sensitif dari citra kontainer.
  • Pahami trade-off variabel lingkungan vs volume: Variabel lingkungan bersifat statis dan butuh restart Pod untuk diperbarui, sedangkan volume mount memperbarui file secara dinamis melalui symlink swap kubelet tetapi membutuhkan kesiapan hot-reload dari aplikasi.
  • Jangan gunakan subPath jika ingin auto-update: Penggunaan properti subPath pada volume mount mengunci inode file secara permanen, sehingga pembaruan data ConfigMap tidak akan ter-sinkron ke dalam kontainer.
  • Gunakan properti immutable untuk efisiensi: Setel immutable: true pada ConfigMap statis untuk mengurangi kueri watch dari kubelet ke API Server guna mengoptimalkan skalabilitas kluster.
  • Patuhi batas ukuran 1 MB: Jangan menyimpan berkas berukuran besar di ConfigMap karena akan membebani database konsensus etcd.
  • Terapkan pola versioning: Selalu buat objek ConfigMap baru dengan nama versi yang berbeda (misalnya config-v2) untuk memicu rolling update yang aman dan terkontrol pada Deployment.

← Sebelumnya: Anti-Pattern Networking   Berikutnya: Secret →

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