Skip to main content
There are 3 ways to set environment variables and secrets in Kubernetes:
  1. Key-value pair format — directly in the Pod spec
  2. ConfigMap — stored as a Kubernetes API object
  3. Secrets — for confidential data, base64-encoded

Key-Value Pair Format

pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-ubuntu
spec:
  containers:
    - name: my-ubuntu
      image: ubuntu
      env:
        - name: URL
          value: https://karchunt.com
        - name: APP_NAME
          value: karchunt-ubuntu

ConfigMap

ConfigMap stores configuration data as a Kubernetes API object, similar in concept to key-value pairs but more reusable across pods.
kubectl get configmap

Creating a ConfigMap

# From key-value pairs
kubectl create configmap <config-name> --from-literal=<key>=<value>
kubectl create configmap api-config --from-literal=port=8080

# From a file
kubectl create configmap <config-name> --from-file=<path-to-file>
kubectl create configmap api-config --from-file=.env
When creating from a file, each line must follow the format <name>=<value>:
.env
port=8080
env=prod

Using ConfigMap in a Pod

Inject all ConfigMap values as environment variables. The configMapRef.name must match the ConfigMap’s metadata.name.
api-party.yaml
apiVersion: v1
kind: Pod
metadata:
  name: api-party
spec:
  containers:
    - name: api-party
      image: api-party:0.1.0
      ports:
        - containerPort: 8080
      envFrom:
        - configMapRef:
            name: api-config

Secrets

  • Secrets are only encoded (base64) and not encrypted in etcd. Enable encryption at rest in kube-apiserver.
  • Consider external secrets providers like HashiCorp Vault or AWS Secrets Manager.
  • Don’t check in Secret objects with data to SCM like GitHub.
  • Remember to set up RBAC (least-privileged access) since anyone in the same namespace can access Secret objects.
Secrets store confidential information like passwords, keys, or tokens. How Kubernetes manages secrets:
  • A secret is only sent to a node if a pod requires it.
  • The kubelet stores a copy of the secret in tmpfs (RAM disk) — not written to disk storage.
  • The kubelet deletes its local copy when the pod that depends on the secret is deleted.
kubectl get secrets

Built-in Secret Types

TypeUsage
OpaqueArbitrary user-defined data
kubernetes.io/service-account-tokenServiceAccount token
kubernetes.io/dockerconfigjsonSerialized ~/.docker/config.json file
kubernetes.io/basic-authCredentials for basic authentication
kubernetes.io/ssh-authCredentials for SSH authentication
kubernetes.io/tlsData for a TLS client or server
bootstrap.kubernetes.io/tokenBootstrap token data

Creating Secrets

When using imperative commands, you don’t need to encode your data — the command handles it.
# Create generic (Opaque) secret from key-value pairs
kubectl create secret generic <secret-name> --from-literal=<key>=<value>
kubectl create secret generic api-secret --from-literal=token=yourtoken

# From a file
kubectl create secret generic <secret-name> --from-file=<path-to-file>
kubectl create secret generic api-secret --from-file=.env

# Container registry secret
kubectl create secret docker-registry secret-harbor \\
  [email protected] \\
  --docker-username=karchun \\
  --docker-password=mypassword \\
  --docker-server=harbor.registry.com

# Retrieve and decode registry secret
kubectl get secret secret-harbor -o jsonpath='{.data.*}' | base64 -d

# TLS secret
kubectl create secret tls <secret-name> --cert=<path-to-cert> --key=<path-to-key>
kubectl create secret tls tls-domain --cert="path.crt" --key="key.key"

Using Secrets in a Pod

api-party.yaml
apiVersion: v1
kind: Pod
metadata:
  name: api-party
spec:
  containers:
    - name: api-party
      image: api-party:0.1.0
      envFrom:
        - secretRef:
            name: api-secret  # Secret metadata name

Build docs developers (and LLMs) love