Multi-Environment Configuration #
Hampir semua sistem produksi butuh lebih dari satu environment — minimal development, staging, dan production. Tantangannya: konfigurasi harus berbeda per environment (URL database, resource limits, feature flags) tapi struktur dasarnya sama. Tanpa strategi yang jelas, konfigurasi mudah drift — staging tidak lagi mencerminkan production, dan bug hanya muncul di production karena ada yang berbeda.
Pendekatan 1: Namespace per Environment #
Cara paling sederhana: buat namespace terpisah untuk setiap environment dalam satu cluster.
Cluster tunggal:
Namespace: development
Deployment: api (1 replica, resource kecil)
ConfigMap: app-config (LOG_LEVEL=debug, DB_HOST=dev-postgres)
Namespace: staging
Deployment: api (2 replica, resource menengah)
ConfigMap: app-config (LOG_LEVEL=info, DB_HOST=staging-postgres)
Namespace: production
Deployment: api (5 replica, resource besar)
ConfigMap: app-config (LOG_LEVEL=warn, DB_HOST=prod-postgres)
Kelebihan: sederhana, satu cluster untuk semua. Kekurangan: production di-share dengan non-production — ada risiko blast radius jika ada masalah di cluster.
Pendekatan 2: Kustomize — Overlay per Environment #
Kustomize adalah tool bawaan kubectl yang memungkinkan kamu mendefinisikan base konfigurasi dan overlay (modifikasi) per environment tanpa duplikasi manifest.
Struktur direktori dengan Kustomize:
k8s/
├── base/ # konfigurasi dasar yang sama di semua env
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ └── kustomization.yaml
│
└── overlays/
├── development/
│ ├── kustomization.yaml # patch untuk development
│ └── configmap-patch.yaml
├── staging/
│ ├── kustomization.yaml
│ └── configmap-patch.yaml
└── production/
├── kustomization.yaml
├── configmap-patch.yaml
└── hpa.yaml # HPA hanya di production
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 1
template:
spec:
containers:
- name: api
image: my-api:latest
resources:
requests:
cpu: "100m"
memory: "128Mi"
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: production # override namespace
bases:
- ../../base
resources:
- hpa.yaml # tambah HPA yang tidak ada di base
patches:
- path: configmap-patch.yaml
- target:
kind: Deployment
name: api
patch: |-
- op: replace
path: /spec/replicas
value: 5 # override replicas
- op: replace
path: /spec/template/spec/containers/0/resources/requests/cpu
value: "500m" # override resource
images:
- name: my-api
newTag: v2.1.0 # pin image tag di production
# overlays/production/configmap-patch.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: "warn" # override dari base yang mungkin "debug"
DB_HOST: "postgres.production.svc.cluster.local"
MAX_CONNECTIONS: "100"
# Deploy ke production
kubectl apply -k k8s/overlays/production/
# Preview apa yang akan di-deploy (dry-run)
kubectl diff -k k8s/overlays/production/
# Generate manifest lengkap tanpa apply (untuk review)
kubectl kustomize k8s/overlays/production/
Pendekatan 3: Helm Values per Environment #
Helm menggunakan file values.yaml sebagai konfigurasi default, dan kamu bisa override dengan file values per environment.
helm-chart/
├── Chart.yaml
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
├── values.yaml # default values
├── values-development.yaml # override untuk development
├── values-staging.yaml # override untuk staging
└── values-production.yaml # override untuk production
# values.yaml (defaults)
replicaCount: 1
image:
tag: latest
resources:
requests:
cpu: "100m"
memory: "128Mi"
config:
logLevel: "debug"
maxConnections: 10
dbHost: "postgres-dev"
autoscaling:
enabled: false
# values-production.yaml
replicaCount: 5
image:
tag: "v2.1.0" # pin versi di production
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "2Gi"
config:
logLevel: "warn"
maxConnections: 100
dbHost: "postgres.production.svc.cluster.local"
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 20
# Deploy ke production dengan values production
helm upgrade --install api ./helm-chart \
--namespace production \
--values values-production.yaml \
--set image.tag=$(git rev-parse --short HEAD) # override tag dengan commit hash
# Lihat values yang aktif
helm get values api -n production
Mencegah Configuration Drift #
Configuration drift terjadi saat konfigurasi di production secara diam-diam berbeda dari apa yang ada di repository. Strategi untuk mencegahnya:
1. GitOps — satu-satunya cara deploy adalah via Git
Semua perubahan konfigurasi harus melalui pull request
Tidak ada kubectl apply manual ke production
Tools: ArgoCD, Flux
2. Immutable ConfigMap names
Beri versi pada nama ConfigMap:
app-config-v2.1.0 (bukan app-config yang bisa diubah kapan saja)
Update berarti buat ConfigMap baru dan update referensi di Deployment
3. Drift detection
ArgoCD secara otomatis deteksi perbedaan antara Git dan cluster
Alert saat ada resource yang out-of-sync
4. Regular reconciliation
Secara periodik bandingkan state cluster dengan state Git
kubectl diff -k overlays/production/ untuk lihat perbedaan
Pola: Konfigurasi Shared vs Per-Environment #
Tidak semua konfigurasi perlu berbeda per environment. Pisahkan yang truly shared dari yang environment-specific:
# ConfigMap shared — sama di semua environment
apiVersion: v1
kind: ConfigMap
metadata:
name: shared-config
data:
SERVICE_NAME: "api-server"
API_VERSION: "v2"
SUPPORTED_LOCALES: "en,id,ms"
---
# ConfigMap per-environment
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config # nama sama di semua namespace, konten berbeda
data:
APP_ENV: "production" # atau "staging", "development"
LOG_LEVEL: "warn" # berbeda per env
DB_HOST: "..." # berbeda per env
REPLICAS: "5" # berbeda per env
Ringkasan #
- Namespace per environment untuk isolasi simpel — mudah diterapkan tapi semua environment berbagi cluster; risiko blast radius lebih tinggi.
- Kustomize untuk DRY configuration — definisikan sekali di base, override hanya yang berbeda di overlays; tidak ada duplikasi manifest; bawaan kubectl.
- Helm values per environment untuk chart yang kompleks —
values-production.yamloverridevalues.yaml; cocok untuk chart yang sudah ada atau deployment Helm yang sudah mapan.- GitOps mencegah configuration drift — semua perubahan via Git; tidak ada manual kubectl apply ke production; ArgoCD/Flux memastikan cluster selalu sinkron dengan repository.
- Pisahkan shared dari per-environment — tidak semua konfigurasi perlu berbeda; identifikasi apa yang benar-benar environment-specific untuk mengurangi duplikasi.
- Pin image tag di production — jangan gunakan
latestdi production; gunakan commit hash atau semantic version untuk reproducibility dan rollback yang reliable.
← Sebelumnya: Configuration Hot Reload Berikutnya: Anti-Pattern Configuration →