Belajar Kubernetes - Episode 23 - Environment Variable

Belajar Kubernetes - Episode 23 - Environment Variable

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.

Arman Dwi Pangestu
Arman Dwi PangestuMarch 29, 2026
0 views
9 min read

Pendahuluan

Catatan

Untuk kalian yang ingin membaca episode sebelumnya, bisa click thumbnail episode 22 di bawah ini

Episode 22Episode 22

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.

Apa Itu Environment Variable?

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:

  • Configuration injection - Pass setting ke application
  • Runtime configuration - Set di container startup
  • No code change - Configure tanpa rebuild image
  • Environment-specific - Different value per environment
  • Twelve-factor app - Standard configuration method
  • Secure secret - Bisa reference encrypted Secret

Kenapa Gunakan Environment Variable?

Environment variable solve beberapa configuration challenge:

  • Portability - Same image work di different environment
  • Security - Keep secret out dari code dan image
  • Flexibility - Change configuration tanpa rebuild
  • Separation of concern - Decouple config dari code
  • Dynamic configuration - Inject Pod metadata di runtime
  • Standard practice - Industry-standard configuration method
  • Easy debugging - View configuration tanpa inspect code

Tanpa environment variable, kalian butuh different image untuk setiap environment atau hardcode configuration, making deployment inflexible dan insecure.

Setting Environment Variable

Ada beberapa cara untuk set environment variable di Kubernetes.

Direct Value Assignment

Set environment variable directly di Pod spec.

Contoh: Basic Environment Variable

Kubernetesbasic-env.yml
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

Kubernetesmultiple-env.yml
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"

Menggunakan ConfigMap

Reference ConfigMap data sebagai environment variable.

Contoh: ConfigMap sebagai Environment Variable

Kubernetesconfigmap-env.yml
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.level

Contoh: Import Semua ConfigMap Key

Kubernetesconfigmap-envfrom.yml
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-config

Semua ConfigMap key jadi environment variable automatically.

Menggunakan Secret

Reference Secret data sebagai environment variable untuk sensitive information.

Contoh: Secret sebagai Environment Variable

Kubernetessecret-env.yml
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-key

Contoh: Import Semua Secret Key

Kubernetessecret-envfrom.yml
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-secrets

Warning

Security Note: Environment variable visible di Pod spec dan container inspect command. Untuk highly sensitive data, consider mounting Secret sebagai file instead.

Downward API

Inject Pod dan container metadata sebagai environment variable.

Contoh: Pod Metadata sebagai Environment Variable

Kubernetesdownward-api-env.yml
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.serviceAccountName

Contoh: Resource Limit sebagai Environment Variable

Kubernetesresource-env.yml
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.cpu

Combining Multiple Source

Mix different environment variable source.

Contoh: Mixed Environment Variable

Kubernetesmixed-env.yml
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_

Contoh Praktis

Contoh 1: Web Application Configuration

Kubernetesweb-app-config.yml
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-config

Contoh 2: Database Connection Configuration

Kubernetesdatabase-config.yml
apiVersion: 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)"

Contoh 3: Multi-Environment Configuration

Kubernetesmulti-env-config.yml
# 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-prod

Contoh 4: Feature Flag

Kubernetesfeature-flags.yml
apiVersion: 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_

Environment Variable Substitution

Gunakan environment variable dalam environment variable lain.

Contoh: Variable Substitution

Kubernetesenv-substitution.yml
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"

Melihat Environment Variable

Check environment variable di running container.

View Semua Environment Variable

Kubernetesbash
sudo kubectl exec <pod-name> -- env

View Specific Environment Variable

Kubernetesbash
sudo kubectl exec <pod-name> -- printenv DATABASE_HOST

View Environment Variable dengan Grep

Kubernetesbash
sudo kubectl exec <pod-name> -- env | grep DB_

Describe Pod untuk Lihat Environment Variable

Kubernetesbash
sudo kubectl describe pod <pod-name>

Kesalahan Umum dan Pitfall

Kesalahan 1: Hardcoding Secret

Problem: Putting sensitive data directly di Pod spec.

Solusi: Gunakan Secret untuk sensitive data:

Kubernetesyml
# Buruk: Hardcoded password
env:
    - name: DB_PASSWORD
      value: "mypassword123"
 
# Bagus: Reference Secret
env:
    - name: DB_PASSWORD
      valueFrom:
          secretKeyRef:
              name: db-credentials
              key: password

Kesalahan 2: Missing ConfigMap atau Secret

Problem: Pod fail start karena referenced ConfigMap/Secret tidak exist.

Solusi: Create ConfigMap/Secret sebelum create Pod:

Kubernetesbash
# Check jika ConfigMap exist
sudo kubectl get configmap app-config
 
# Create jika missing
sudo kubectl create configmap app-config --from-literal=key=value

Kesalahan 3: Wrong Key Name

Problem: Reference non-existent key di ConfigMap/Secret.

Solusi: Verify key name:

Kubernetesbash
# View ConfigMap key
sudo kubectl describe configmap app-config
 
# View Secret key
sudo kubectl describe secret db-credentials

Kesalahan 4: Tidak Gunakan Quote untuk Value

Problem: YAML parsing issue dengan special character.

Solusi: Quote environment variable value:

Kubernetesyml
# Buruk: Bisa cause parsing issue
env:
    - name: SPECIAL_CHARS
      value: @#$%^&*
 
# Bagus: Quoted value
env:
    - name: SPECIAL_CHARS
      value: "@#$%^&*"

Kesalahan 5: Expose Secret di Log

Problem: Logging environment variable expose secret.

Solusi: Avoid logging sensitive environment variable:

Kubernetesyml
# Buruk: Log semua environment variable
command: ["sh", "-c", "env && ./app"]
 
# Bagus: Jangan log environment variable
command: ["./app"]

Best Practice

Gunakan ConfigMap untuk Non-Sensitive Data

Separate configuration dari code:

Kubernetesyml
# Application setting di ConfigMap
configMapRef:
    name: app-config

Gunakan Secret untuk Sensitive Data

Protect credential dan key:

Kubernetesyml
# Credential di Secret
secretRef:
    name: app-secrets

Gunakan Descriptive Name

Pilih clear environment variable name:

Kubernetesyml
# Bagus: Clear dan descriptive
- name: DATABASE_CONNECTION_TIMEOUT
- name: MAX_RETRY_ATTEMPTS
- name: LOG_LEVEL
 
# Hindari: Unclear abbreviation
- name: DBTIMEOUT
- name: MAXRET
- name: LL

Organize environment variable logically:

Kubernetesyml
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_MODE

Gunakan envFrom untuk Multiple Variable

Import semua key dari ConfigMap/Secret:

Kubernetesyml
envFrom:
    - configMapRef:
          name: app-config
    - secretRef:
          name: app-secrets

Add Prefix untuk Avoid Conflict

Prevent variable name collision:

Kubernetesyml
envFrom:
    - configMapRef:
          name: app-config
          prefix: APP_
    - secretRef:
          name: db-credentials
          prefix: DB_

Document Environment Variable

Add comment explaining variable:

Kubernetesyml
env:
    # Maximum number dari database connection
    - name: DB_MAX_CONNECTIONS
      value: "20"
    # Session timeout dalam second
    - name: SESSION_TIMEOUT
      value: "3600"

Gunakan Default Value di Application

Handle missing environment variable gracefully:

python
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')

Update Environment Variable

Environment variable set di container startup. Untuk update mereka:

Update ConfigMap

Kubernetesbash
sudo kubectl edit configmap app-config

Update Secret

Kubernetesbash
sudo kubectl edit secret app-secrets

Restart Pod

Change require Pod restart:

Kubernetesbash
# Restart Deployment
sudo kubectl rollout restart deployment app
 
# Delete Pod (untuk standalone Pod)
sudo kubectl delete pod app-pod

Important

Penting: Update ConfigMap atau Secret tidak automatically update environment variable di running container. Kalian harus restart Pod untuk apply change.

Troubleshooting Environment Variable

Check Environment Variable

Kubernetesbash
sudo kubectl exec <pod-name> -- env

Verify ConfigMap

Kubernetesbash
sudo kubectl get configmap <name> -o yaml

Verify Secret

Kubernetesbash
sudo kubectl get secret <name> -o yaml

Check Pod Event

Kubernetesbash
sudo kubectl describe pod <pod-name>

Look for error seperti:

  • ConfigMap not found
  • Secret not found
  • Invalid key reference

Penutup

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:

  • Environment variable configure application tanpa code change
  • Set variable directly di Pod spec dengan value
  • Reference ConfigMap untuk non-sensitive configuration
  • Reference Secret untuk sensitive data seperti password
  • Gunakan Downward API untuk inject Pod metadata
  • envFrom import semua key dari ConfigMap/Secret
  • Add prefix untuk avoid variable name conflict
  • Variable substitution allow composing value
  • Environment variable set di container startup
  • Restart Pod untuk apply ConfigMap/Secret change
  • Gunakan descriptive name untuk clarity
  • Document environment variable dengan comment
  • Handle missing variable dengan default value di code
  • Never hardcode secret di Pod spec

Environment 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

Episode 24Episode 24

Related Posts