Skip to content

So far, our application is running, scalable, and exposed to the world. But we’ve hardcoded our configuration (like the Nginx version) directly into our YAML files. This isn’t flexible. What if we want to change a setting without rebuilding and redeploying the whole application?

So far, our application is running, scalable, and exposed to the world. But we’ve hardcoded our configuration (like the Nginx version) directly into our YAML files. This isn’t flexible. What if we want to change a setting without rebuilding and redeploying the whole application?

A core principle of building portable, cloud-native applications is to separate the application’s code from its configuration. You should be able to promote the exact same container image from a development environment to staging and then to production, with the only difference being the configuration it uses (e.g., the database URL, a feature flag, or an API key).

Kubernetes provides two primary objects for this purpose: ConfigMaps and Secrets.

A ConfigMap is a Kubernetes object used to store non-confidential configuration data in a key-value format. Think of it as a set of properties or environment variables that you manage within Kubernetes and can “inject” into your Pods at runtime.

This allows you to change your application’s behavior without ever touching the application code or its container image. For example, you could have a ConfigMap for your development environment with LOG_LEVEL=debug and another ConfigMap for production with LOG_LEVEL=info.

Your Pods can consume ConfigMap data in two main ways:

  1. As Environment Variables: Each key-value pair in the ConfigMap becomes an environment variable inside your container. This is the most common method.
  2. As Mounted Files: The ConfigMap can be mounted as a volume, where each key becomes a file name and the value becomes the file’s content. This is useful for legacy applications that expect to read configuration from a file (like a settings.xml or nginx.conf).

A Secret is very similar to a ConfigMap but is specifically intended for storing sensitive or confidential data, such as:

  • Database passwords
  • API tokens and keys
  • TLS certificates

Like ConfigMaps, Secrets are also consumed by Pods as either environment variables or mounted files.

What’s the difference? When you create a Secret, Kubernetes stores the values as base64-encoded strings. This is encoding, not encryption. It simply prevents someone from casually reading the password by looking over your shoulder or browsing the YAML file. However, it signals the intent that the data is sensitive, and Kubernetes can apply stricter policies to Secrets, such as limiting access and preventing them from being accidentally exposed.



  1. Create a ConfigMap We’ll create a ConfigMap to hold some non-sensitive display settings. We can do this easily from the command line.

    Terminal window
    kubectl create configmap my-app-config \
    --from-literal=APP_COLOR=blue \
    --from-literal=APP_GREETING="Hello from ConfigMap!"

    You can inspect the ConfigMap you created (the -o yaml flag shows the full object definition):

    Terminal window
    kubectl get configmap my-app-config -o yaml
  2. Create a Secret
    Next, let’s create a Secret for some dummy database credentials.

    Terminal window
    kubectl create secret generic my-db-credentials \
    --from-literal=DB_USER=my-admin-user \
    --from-literal=DB_PASSWORD='S3cr3tP@ssw0rd!!'

    If you inspect the secret with kubectl get secret my-db-credentials -o yaml, you’ll see the values are base64 encoded.

  3. Inject Configuration into the Deployment Now, we need to update our Deployment to use this ConfigMap and Secret. Create a new file named deployment-with-config.yaml with the following content. Pay close attention to the new envFrom section.

    deployment-with-config.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: my-webapp-deployment
    spec:
    replicas: 3
    selector:
    matchLabels:
    app: my-webapp
    template:
    metadata:
    labels:
    app: my-webapp
    spec:
    containers:
    - name: webserver-container
    image: nginx:1.21.6
    ports:
    - containerPort: 80
    # This new section injects our configuration
    envFrom:
    - configMapRef:
    name: my-app-config
    - secretRef:
    name: my-db-credentials

    Apply this updated Deployment configuration:

    Terminal window
    # The 'apply' command is smart enough to update the existing deployment
    kubectl apply -f deployment-with-config.yaml

    The Deployment will perform a rolling update to launch new Pods containing our configuration.