Di episode ini kita akan coba bahas Environment Variable di Kubernetes. Kita akan mempelajari cara set environment variable, gunakan ConfigMap dan Secret, reference Pod field, dan best practice untuk configuration management.

Catatan
Untuk kalian yang ingin membaca episode sebelumnya, bisa click thumbnail episode 22 di bawah ini
Di episode sebelumnya kita sudah belajar tentang sharing volume antara Pod menggunakan PersistentVolume dan PersistentVolumeClaim. Selanjutnya di episode 23 kali ini, kita akan coba bahas Environment Variable, cara fundamental untuk configure application di Kubernetes.
Catatan: Disini saya akan menggunakan Kubernetes Cluster yang di install melalui K3s.
Environment variable adalah key-value pair yang application gunakan untuk configuration. Di Kubernetes, kalian bisa set environment variable directly di Pod spec, reference ConfigMap dan Secret, atau dynamically inject Pod metadata.
Environment Variable adalah dynamic value yang affect bagaimana process behave di container. Mereka menyediakan cara untuk configure application tanpa modify code atau rebuild image.
Bayangkan environment variable seperti setting di phone kalian - kalian bisa change language, timezone, atau theme tanpa reinstall app. Similarly, environment variable let kalian configure application untuk different environment (dev, staging, production) menggunakan container image yang sama.
Karakteristik kunci Environment Variable:
Environment variable solve beberapa configuration challenge:
Tanpa environment variable, kalian butuh different image untuk setiap environment atau hardcode configuration, making deployment inflexible dan insecure.
Ada beberapa cara untuk set environment variable di Kubernetes.
Set environment variable directly di Pod spec.
Contoh: Basic Environment Variable
apiVersion: v1
kind: Pod
metadata:
name: env-pod
spec:
containers:
- name: app
image: nginx:1.25
env:
- name: ENVIRONMENT
value: "production"
- name: LOG_LEVEL
value: "info"
- name: MAX_CONNECTIONS
value: "100"Contoh: Multiple Environment Variable
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:latest
env:
- name: APP_NAME
value: "MyApplication"
- name: APP_VERSION
value: "1.0.0"
- name: DATABASE_HOST
value: "db.example.com"
- name: DATABASE_PORT
value: "5432"
- name: CACHE_ENABLED
value: "true"
- name: CACHE_TTL
value: "3600"Reference ConfigMap data sebagai environment variable.
Contoh: ConfigMap sebagai Environment Variable
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database.host: "db.example.com"
database.port: "5432"
cache.enabled: "true"
log.level: "info"
---
apiVersion: v1
kind: Pod
metadata:
name: configmap-env-pod
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database.host
- name: DATABASE_PORT
valueFrom:
configMapKeyRef:
name: app-config
key: database.port
- name: CACHE_ENABLED
valueFrom:
configMapKeyRef:
name: app-config
key: cache.enabled
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log.levelContoh: Import Semua ConfigMap Key
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_HOST: "db.example.com"
DATABASE_PORT: "5432"
CACHE_ENABLED: "true"
LOG_LEVEL: "info"
---
apiVersion: v1
kind: Pod
metadata:
name: envfrom-pod
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- configMapRef:
name: app-configSemua ConfigMap key jadi environment variable automatically.
Reference Secret data sebagai environment variable untuk sensitive information.
Contoh: Secret sebagai Environment Variable
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData:
username: "admin"
password: "secretpassword"
api-key: "abc123xyz789"
---
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
- name: API_KEY
valueFrom:
secretKeyRef:
name: db-credentials
key: api-keyContoh: Import Semua Secret Key
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
stringData:
DB_USERNAME: "admin"
DB_PASSWORD: "secretpassword"
API_KEY: "abc123xyz789"
---
apiVersion: v1
kind: Pod
metadata:
name: secret-envfrom-pod
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- secretRef:
name: app-secretsWarning
Security Note: Environment variable visible di Pod spec dan container inspect command. Untuk highly sensitive data, consider mounting Secret sebagai file instead.
Inject Pod dan container metadata sebagai environment variable.
Contoh: Pod Metadata sebagai Environment Variable
apiVersion: v1
kind: Pod
metadata:
name: downward-api-pod
labels:
app: myapp
version: v1.0
annotations:
description: "Example application"
spec:
containers:
- name: app
image: busybox:1.36
command:
- sh
- -c
- while true; do env | grep POD; sleep 10; done
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountNameContoh: Resource Limit sebagai Environment Variable
apiVersion: v1
kind: Pod
metadata:
name: resource-env-pod
spec:
containers:
- name: app
image: myapp:latest
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
env:
- name: MEMORY_REQUEST
valueFrom:
resourceFieldRef:
containerName: app
resource: requests.memory
- name: MEMORY_LIMIT
valueFrom:
resourceFieldRef:
containerName: app
resource: limits.memory
- name: CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: app
resource: requests.cpu
- name: CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: app
resource: limits.cpuMix different environment variable source.
Contoh: Mixed Environment Variable
apiVersion: v1
kind: Pod
metadata:
name: mixed-env-pod
spec:
containers:
- name: app
image: myapp:latest
env:
# Direct value
- name: ENVIRONMENT
value: "production"
# Dari ConfigMap
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database.host
# Dari Secret
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
# Dari Downward API
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
# Import semua dari ConfigMap
envFrom:
- configMapRef:
name: app-config
prefix: CONFIG_
# Import semua dari Secret
- secretRef:
name: app-secrets
prefix: SECRET_apiVersion: v1
kind: ConfigMap
metadata:
name: web-config
data:
APP_NAME: "MyWebApp"
APP_ENV: "production"
LOG_LEVEL: "info"
SESSION_TIMEOUT: "3600"
MAX_UPLOAD_SIZE: "10485760"
---
apiVersion: v1
kind: Secret
metadata:
name: web-secrets
type: Opaque
stringData:
JWT_SECRET: "your-jwt-secret-key"
ENCRYPTION_KEY: "your-encryption-key"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: mywebapp:latest
ports:
- containerPort: 8080
env:
# Pod metadata
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
# Secret
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: web-secrets
key: JWT_SECRET
- name: ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: web-secrets
key: ENCRYPTION_KEY
# Import semua ConfigMap
envFrom:
- configMapRef:
name: web-configapiVersion: v1
kind: ConfigMap
metadata:
name: db-config
data:
DB_HOST: "postgres.default.svc.cluster.local"
DB_PORT: "5432"
DB_NAME: "myapp"
DB_SSL_MODE: "require"
DB_MAX_CONNECTIONS: "20"
DB_TIMEOUT: "30"
---
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData:
DB_USERNAME: "appuser"
DB_PASSWORD: "securepassword123"
---
apiVersion: v1
kind: Pod
metadata:
name: app-with-db
spec:
containers:
- name: app
image: myapp:latest
env:
# Database host dan port dari ConfigMap
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: db-config
key: DB_HOST
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: db-config
key: DB_PORT
- name: DB_NAME
valueFrom:
configMapKeyRef:
name: db-config
key: DB_NAME
# Credential dari Secret
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_USERNAME
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_PASSWORD
# Build connection string
- name: DATABASE_URL
value: "postgresql://$(DB_USERNAME):$(DB_PASSWORD)@$(DB_HOST):$(DB_PORT)/$(DB_NAME)"# Development ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-dev
namespace: development
data:
ENVIRONMENT: "development"
LOG_LEVEL: "debug"
DEBUG_MODE: "true"
API_URL: "https://api-dev.example.com"
---
# Production ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-prod
namespace: production
data:
ENVIRONMENT: "production"
LOG_LEVEL: "warn"
DEBUG_MODE: "false"
API_URL: "https://api.example.com"
---
# Development Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: development
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- configMapRef:
name: app-config-dev
---
# Production Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- configMapRef:
name: app-config-prodapiVersion: v1
kind: ConfigMap
metadata:
name: feature-flags
data:
FEATURE_NEW_UI: "true"
FEATURE_BETA_API: "false"
FEATURE_ANALYTICS: "true"
FEATURE_DARK_MODE: "true"
FEATURE_NOTIFICATIONS: "true"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- configMapRef:
name: feature-flags
prefix: FEATURE_Gunakan environment variable dalam environment variable lain.
Contoh: Variable Substitution
apiVersion: v1
kind: Pod
metadata:
name: substitution-pod
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DB_HOST
value: "postgres.example.com"
- name: DB_PORT
value: "5432"
- name: DB_NAME
value: "myapp"
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
# Compose connection string menggunakan variable lain
- name: DATABASE_URL
value: "postgresql://$(DB_USERNAME):$(DB_PASSWORD)@$(DB_HOST):$(DB_PORT)/$(DB_NAME)?sslmode=require"Check environment variable di running container.
sudo kubectl exec <pod-name> -- envsudo kubectl exec <pod-name> -- printenv DATABASE_HOSTsudo kubectl exec <pod-name> -- env | grep DB_sudo kubectl describe pod <pod-name>Problem: Putting sensitive data directly di Pod spec.
Solusi: Gunakan Secret untuk sensitive data:
# Buruk: Hardcoded password
env:
- name: DB_PASSWORD
value: "mypassword123"
# Bagus: Reference Secret
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: passwordProblem: Pod fail start karena referenced ConfigMap/Secret tidak exist.
Solusi: Create ConfigMap/Secret sebelum create Pod:
# Check jika ConfigMap exist
sudo kubectl get configmap app-config
# Create jika missing
sudo kubectl create configmap app-config --from-literal=key=valueProblem: Reference non-existent key di ConfigMap/Secret.
Solusi: Verify key name:
# View ConfigMap key
sudo kubectl describe configmap app-config
# View Secret key
sudo kubectl describe secret db-credentialsProblem: YAML parsing issue dengan special character.
Solusi: Quote environment variable value:
# Buruk: Bisa cause parsing issue
env:
- name: SPECIAL_CHARS
value: @#$%^&*
# Bagus: Quoted value
env:
- name: SPECIAL_CHARS
value: "@#$%^&*"Problem: Logging environment variable expose secret.
Solusi: Avoid logging sensitive environment variable:
# Buruk: Log semua environment variable
command: ["sh", "-c", "env && ./app"]
# Bagus: Jangan log environment variable
command: ["./app"]Separate configuration dari code:
# Application setting di ConfigMap
configMapRef:
name: app-configProtect credential dan key:
# Credential di Secret
secretRef:
name: app-secretsPilih clear environment variable name:
# Bagus: Clear dan descriptive
- name: DATABASE_CONNECTION_TIMEOUT
- name: MAX_RETRY_ATTEMPTS
- name: LOG_LEVEL
# Hindari: Unclear abbreviation
- name: DBTIMEOUT
- name: MAXRET
- name: LLOrganize environment variable logically:
env:
# Database configuration
- name: DB_HOST
- name: DB_PORT
- name: DB_NAME
# Cache configuration
- name: CACHE_HOST
- name: CACHE_PORT
- name: CACHE_TTL
# Application setting
- name: LOG_LEVEL
- name: DEBUG_MODEImport semua key dari ConfigMap/Secret:
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secretsPrevent variable name collision:
envFrom:
- configMapRef:
name: app-config
prefix: APP_
- secretRef:
name: db-credentials
prefix: DB_Add comment explaining variable:
env:
# Maximum number dari database connection
- name: DB_MAX_CONNECTIONS
value: "20"
# Session timeout dalam second
- name: SESSION_TIMEOUT
value: "3600"Handle missing environment variable gracefully:
import os
# Python example dengan default value
db_host = os.getenv('DB_HOST', 'localhost')
db_port = int(os.getenv('DB_PORT', '5432'))
log_level = os.getenv('LOG_LEVEL', 'info')Environment variable set di container startup. Untuk update mereka:
sudo kubectl edit configmap app-configsudo kubectl edit secret app-secretsChange require Pod restart:
# Restart Deployment
sudo kubectl rollout restart deployment app
# Delete Pod (untuk standalone Pod)
sudo kubectl delete pod app-podImportant
Penting: Update ConfigMap atau Secret tidak automatically update environment variable di running container. Kalian harus restart Pod untuk apply change.
sudo kubectl exec <pod-name> -- envsudo kubectl get configmap <name> -o yamlsudo kubectl get secret <name> -o yamlsudo kubectl describe pod <pod-name>Look for error seperti:
Pada episode 23 ini, kita telah membahas Environment Variable di Kubernetes. Kita sudah belajar cara set environment variable, gunakan ConfigMap dan Secret, reference Pod metadata, dan best practice untuk configuration management.
Key takeaway:
valueEnvironment variable essential untuk configure application di Kubernetes. Dengan memahami different cara set dan manage environment variable, kalian bisa build flexible, secure, dan maintainable application.
Bagaimana, makin jelas kan tentang Environment Variable di Kubernetes? Jadi, pastikan tetap semangat belajar dan nantikan episode selanjutnya!
Catatan
Untuk kalian yang ingin melanjutkan ke episode selanjutnya, bisa click thumbnail episode 24 di bawah ini