Page Content

Tutorials

What are the Environment Variables in Kubernetes?

Environment Variables in Kubernetes

Environment Variables in Kubernetes help containerized apps configure. Key-value pairs injected into a container’s runtime environment let developers change application behavior without rewriting source code or container image. Modern cloud-native principles include isolating application settings from the container image and using a single protected image across development, testing, and production.

You can also read What is a Kubernetes ReplicaSet & Working with ReplicaSets

Methods of Injecting Environment Variables

Direct Definition (Hard-coding)

The simplest method to set an environment variable is to define it directly within the spec.containers.env block of a Pod or Deployment manifest. Despite being simple to use, this approach is thought to be the least flexible since it exposes configuration data in version control and necessitates manual updates to the manifest for each modification.

Example of Hard-coded Environment Variables:

apiVersion: v1
kind: Pod
metadata:
  name: direct-env-demo
spec:
  containers:
  - name: demo-container
    image: nginx
    env:
    - name: APP_COLOR
      value: "blue"
    - name: LOG_LEVEL
      value: "debug"

In this scenario, the application inside the container can access APP_COLOR and LOG_LEVEL as standard environment variables. You can verify this by running kubectl exec direct-env-demo -- printenv, which will list all variables active in the container.

Using ConfigMaps for Externalised Configuration

Hostnames, service ports, and account names are examples of non-sensitive configuration parameters that are stored in ConfigMaps, special Kubernetes objects. Data stored in a ConfigMap allows you to modify settings without regard to the Pod lifecycle. ConfigMaps can be used in two main ways for environment variables:

  • configMapKeyRef: Inserts a particular ConfigMap key-value pair.
  • envFrom: Injects each pair of keys and values from a ConfigMap as a separate environment variable, maybe with a prefix.

Example using ConfigMap References:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  database_url: "mysql-service"
  db_port: "3306"
---
apiVersion: v1
kind: Pod
metadata:
  name: configmap-env-demo
spec:
  containers:
  - name: demo-container
    image: nginx
    env:
    - name: DATABASE_URL
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: database_url
    envFrom:
    - configMapRef:
        name: app-config

Using envFrom is particularly useful when managing a large number of variables, as it reduces the verbosity of the Pod manifest.

You can also read What is Kubernetes Cloud Controller Manager?

Using Secrets for Sensitive Data

Kubernetes’ Secret resource stores passwords, API keys, and certificates. Despite resembling ConfigMaps, Secrets hide information with base64. To avoid plaintext exposure in manifests, it is recommended that any confidential data be stored in Secrets rather than ConfigMaps or hard-coded values.

Example using Secret References:

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  password: cGFzc3dvcmQxMjM= # "password123" in base64
---
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-demo
spec:
  containers:
  - name: demo-container
    image: nginx
    env:
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: password

Note that environment variables set via env or envFrom will override any environment variables specified in the container image.

Defining Dependent Environment Variables

You can define environment variables in Kubernetes that make reference to other variables declared inside the same container. This is accomplished via the $(VAR_NAME) syntax.

Important Rules for Dependencies:

  • Order Matters: Only environment variables earlier in the env list are “defined.”
  • Undefined Variables: Undefined variables are treated as literal strings (e.g., $(UNDEFINED) remains $(UNDEFINED)).
  • Escaping: Escape syntax with a double dollar sign ($$(VAR_NAME)) to prevent expansion.

Example of Dependent Variables:

apiVersion: v1
kind: Pod
metadata:
  name: dependent-env-demo
spec:
  containers:
  - name: demo-container
    image: nginx
    env:
    - name: PROTOCOL
      value: "https"
    - name: HOSTNAME
      value: "example.com"
    - name: SERVICE_ADDRESS
      value: "$(PROTOCOL)://$(HOSTNAME)"

In this example, SERVICE_ADDRESS will resolve to https://example.com.

You can also read What is a Kubernetes Controller Manager?

The Downward API and Resource References

With the help of the Downward API, containers can obtain data about the cluster or themselves without the user having to explicitly provide it. This covers container resource needs as well as pod metadata.

  • fieldRef: Used to inject metadata at the Pod level, such as the IP address, name, namespace, or node on which the Pod is operating.
  • resourceFieldRef: Used to inject resource restrictions and requests (CPU and RAM) at the container level.

Example using fieldRef and resourceFieldRef:

apiVersion: v1
kind: Pod
metadata:
  name: downward-api-demo
spec:
  containers:
  - name: demo-container
    image: nginx
    resources:
      limits:
        memory: "128Mi"
    env:
    - name: MY_POD_IP
      valueFrom:
        fieldRef:
          fieldPath: status.podIP
    - name: MEM_LIMIT
      valueFrom:
        resourceFieldRef:
          containerName: demo-container
          resource: limits.memory

Kubernetes resolves resource values into numeric bytes (e.g., 134217728 for 128Mi) before injecting them.

Loading Environment Variables from Files (v1.34+ Beta)

A new feature in Kubernetes v1.34 enables environment variables to be loaded from files created during runtime, usually by an initContainer. This is controlled by the fileKeyRef field.

How it works:

  • Environment variables are written by an initContainer to a file located in an emptyDir disk.
  • fileKeyRef is used by the main container to refer to this file.
  • These values are retrieved and exposed as environment variables by the Kubelet during container startup.

Env File Syntax Rules:

  1. VAR='value' is the required format for variables.
  2. Single quotes must surround values.
  3. Spaces surrounding the = symbol are disregarded.
  4. It is not permitted to use interpolation or double quotations.

You can also read What is Kube-Proxy in Kubernetes and it’s Lifecycle

Automatic Service Discovery Variables

Kubernetes injects environment variables into each Pod for all active services in a namespace. These variables are formatted as {SERVICE_NAME}_SERVICE_HOST and {SERVICE_NAME}_SERVICE_PORT. With a backend-api service, pods will automatically get:

  • BACKEND_API_SERVICE_HOST: The stable internal IP (ClusterIP).
  • BACKEND_API_SERVICE_PORT: The network port.

Note: In order for these variables to be injected, the Service must be built before the Pod; as a result, many contemporary systems choose employing Cluster DNS for service discovery.

Referencing Variables in Startup Commands

Environment variables allow container launch command modification. If environment variables are defined, they may be utilized in the command or args portion as $(VAR_NAME).

Example of Variables in Startup Commands:

spec:
  containers:
  - name: utility
    image: busybox
    env:
    - name: GREETING
      value: "Hello"
    - name: USER_NAME
      value: "Nigel"
    command: ["/bin/sh", "-c", "echo $(GREETING) $(USER_NAME)"]

When this container runs, it will print “Hello Nigel” to the logs.

Management, Lifecycle, and Best Practices

In Kubernetes, environment variables are unchangeable and static once a pod is operating. The operating container won’t reflect any changes made to a ConfigMap or Secret value. A rollout on a higher-level controller, such as a Deployment, is usually used to restart the Pod in order to apply updates.

Summary of Best Practices:

  • Security: Instead of using environment variables, mount Secrets as volumes for extremely sensitive data. Environment variables are sometimes available to anyone who may exec into the container, or they may be disclosed in logs.
  • Decoupling: To keep your container images generic and portable, always choose ConfigMaps and Secrets over hard-coding values.
  • Validation: If the optional field is set to false while using fileKeyRef, make sure the keys are present in the file because the container won’t start properly if the keys are absent.

You can also read Kind: A Practical Guide to Local Kubernetes Clusters