Kubernetes ConfigMaps: Managing Application Configuration

kubernetesdevopsconfigurationcontainers

Kubernetes ConfigMaps: Managing Application Configuration

What is a ConfigMap?

A ConfigMap is a Kubernetes API object that stores non-confidential configuration data in key-value pairs. It allows you to decouple configuration from your application code, making your containerized applications more portable and easier to manage.

Think of ConfigMaps as a way to store environment variables, configuration files, or any other configuration data that your applications need to run.

Why Use ConfigMaps?

🔄 Separation of Concerns

Keep configuration separate from application code, following the 12-Factor App methodology.

🚀 Environment Flexibility

Use the same container image across different environments (dev, staging, production) with different configurations.

🔧 Runtime Updates

Update configuration without rebuilding container images.

📦 Centralized Management

Manage all configuration data in one place within your Kubernetes cluster.

Creating ConfigMaps

Method 1: From Literal Values

kubectl create configmap app-config \
  --from-literal=database_host=mysql.example.com \
  --from-literal=database_port=3306 \
  --from-literal=app_env=production

Method 2: From Files

# Create from a single file
kubectl create configmap nginx-config --from-file=nginx.conf

# Create from multiple files
kubectl create configmap app-configs --from-file=config/

Method 3: YAML Manifest

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: default
data:
  # Simple key-value pairs
  database_host: "mysql.example.com"
  database_port: "3306"
  app_env: "production"
  
  # Multi-line configuration file
  app.properties: |
    server.port=8080
    server.servlet.context-path=/api
    logging.level.root=INFO
    spring.datasource.url=jdbc:mysql://mysql:3306/mydb
  
  # JSON configuration
  config.json: |
    {
      "api": {
        "version": "v1",
        "timeout": 30
      },
      "features": {
        "enableCache": true,
        "maxConnections": 100
      }
    }

Using ConfigMaps in Pods

As Environment Variables

apiVersion: v1
kind: Pod
metadata:
  name: webapp
spec:
  containers:
  - name: app
    image: myapp:latest
    env:
    # Single environment variable
    - name: DATABASE_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: database_host
    
    # All keys as environment variables
    envFrom:
    - configMapRef:
        name: app-config

As Volume Mounts

apiVersion: v1
kind: Pod
metadata:
  name: webapp
spec:
  containers:
  - name: app
    image: myapp:latest
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
      readOnly: true
  volumes:
  - name: config-volume
    configMap:
      name: app-config

Mounting Specific Keys

apiVersion: v1
kind: Pod
metadata:
  name: webapp
spec:
  containers:
  - name: app
    image: myapp:latest
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: app-config
      items:
      - key: app.properties
        path: application.properties
      - key: config.json
        path: app-config.json

Real-World Example: Laravel Application

Let's configure a Laravel application using ConfigMaps:

1. Create ConfigMap for Laravel

apiVersion: v1
kind: ConfigMap
metadata:
  name: laravel-config
data:
  APP_NAME: "PCJ Application"
  APP_ENV: "production"
  APP_DEBUG: "false"
  APP_URL: "https://pcj.example.com"
  
  DB_CONNECTION: "mysql"
  DB_HOST: "mysql-service"
  DB_PORT: "3306"
  DB_DATABASE: "pcj_db"
  
  CACHE_DRIVER: "redis"
  REDIS_HOST: "redis-service"
  REDIS_PORT: "6379"
  
  # Laravel configuration file
  database.php: |
    <?php
    return [
        'default' => env('DB_CONNECTION', 'mysql'),
        'connections' => [
            'mysql' => [
                'driver' => 'mysql',
                'host' => env('DB_HOST', '127.0.0.1'),
                'port' => env('DB_PORT', '3306'),
                'database' => env('DB_DATABASE', 'forge'),
                'username' => env('DB_USERNAME', 'forge'),
                'password' => env('DB_PASSWORD', ''),
            ],
        ],
    ];

2. Deploy Laravel Pod

apiVersion: apps/v1
kind: Deployment
metadata:
  name: laravel-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: laravel
  template:
    metadata:
      labels:
        app: laravel
    spec:
      containers:
      - name: laravel
        image: pcj/laravel:latest
        ports:
        - containerPort: 8000
        
        # Environment variables from ConfigMap
        envFrom:
        - configMapRef:
            name: laravel-config
        
        # Mount config files
        volumeMounts:
        - name: config-volume
          mountPath: /var/www/html/config/database.php
          subPath: database.php
          readOnly: true
      
      volumes:
      - name: config-volume
        configMap:
          name: laravel-config

Best Practices

Do's

  • Keep it Non-Sensitive: Only store non-confidential data (use Secrets for sensitive data)
  • Use Descriptive Names: Name your ConfigMaps clearly (app-config, nginx-config)
  • Version Your Configs: Include version info in ConfigMap names for rollbacks
  • Validate Data: Ensure configuration values are valid before creating ConfigMaps
  • Use Namespaces: Organize ConfigMaps by environment or application

Don'ts

  • Don't Store Secrets: Never put passwords, API keys, or certificates in ConfigMaps
  • Don't Make Them Too Large: Keep ConfigMaps under 1MB (Kubernetes limit)
  • Don't Hardcode Values: Use templating tools like Helm for dynamic values
  • Don't Ignore Updates: Remember that mounted ConfigMaps update automatically, but environment variables don't

Managing ConfigMaps

View ConfigMaps

# List all ConfigMaps
kubectl get configmaps

# Describe a specific ConfigMap
kubectl describe configmap app-config

# View ConfigMap data
kubectl get configmap app-config -o yaml

Update ConfigMaps

# Edit directly
kubectl edit configmap app-config

# Replace from file
kubectl replace -f configmap.yaml

# Update specific key
kubectl patch configmap app-config -p '{"data":{"database_host":"new-mysql.example.com"}}'

Delete ConfigMaps

kubectl delete configmap app-config

ConfigMaps vs Secrets vs Environment Variables

AspectConfigMapsSecretsEnvironment Variables
Data TypeNon-sensitive configSensitive dataSimple key-value pairs
StoragePlain textBase64 encodedIn container spec
Size Limit1MB1MBNo specific limit
UpdatesDynamic (volumes)Dynamic (volumes)Requires pod restart
Use CasesApp settings, config filesPasswords, certificatesSimple configuration

Conclusion

Kubernetes ConfigMaps are essential for managing application configuration in a cloud-native way. They provide:

  • Flexibility to run the same application in different environments
  • Maintainability by separating config from code
  • Scalability for managing configuration across multiple services

Start using ConfigMaps in your Kubernetes deployments to make your applications more portable and easier to manage!


Next Steps: