Elevating IaC Workflows with Spacelift Stacks and Dependencies 🛠️

Register for the July 23 demo →

Kubernetes

Kubernetes Environment Variables – Setting & Managing

kubernetes environment variables

A best practice when deploying applications in a Kubernetes environment is to securely handle sensitive data by utilizing environment variables and mounting secrets from external sources rather than hard-coding them within the application code or container image.

In this guide, we’ll walk through how to set and manage Kubernetes environment variables so you can properly configure your deployments. We’ll showcase a few different ways in which you can populate environment variable values and make them available to your Pods. Let’s dig in.

What we will cover:

  1. What are Kubernetes environment variables?
  2. Use cases for environment variables in Kubernetes
  3. How do environment variables work in Kubernetes?
  4. Guide: How to define environment variables in the Kubernetes
  5. Should I use the Kubernetes environment variable for Secret data?
  6. How to pass environment variables in a Kubernetes deployment YAML file
  7. Environment variables in Infrastructure as Code

What are Kubernetes environment variables?

Kubernetes environment variables are key-value pairs that provide configuration information to containers running in Kubernetes pods. When they are injected into containers, the containerized processes can retrieve the values as they run. Setting environment variables is one of the main ways to supply config parameters to your apps running in Kubernetes.

Environment variables are an ideal way to configure container deployments because they don’t require anything to be injected into your container’s filesystem. This ensures your workloads remain stateless so they can still be easily scaled across your Kubernetes Nodes, without requiring any complicated volume mounts.

Use cases for environment variables in Kubernetes

Kubernetes environment variables can be used to supply any external values that your containerized apps depend on. Some of the most common scenarios include:

  • Setting database connection and remote server credentials — Apps that need to communicate with external services can access environment variables to learn the IP address, port number, and credentials to use.
  • Identifying Pod details at runtime — You can use environment variables to access Pod metadata values from inside the container, such as the assigned IP address.
  • Customizing app config values — Environment variables are often used to enable app feature flags and apply customized settings. Examples include the domain name an app is served on or the URI of the API server instance it should connect to.
  • Use per-environment configuration — Environment variables decouple configuration from code. Using environment variables instead of hardcoded values lets you easily deploy multiple instances of your app to your Kubernetes cluster, such as staging and production versions with different sets of features enabled.

Environment variables are only useful when your containerized app knows how to read them. If you’re creating your own apps and container images, then it’s best practice to prefer environment variables for configuration because this helps make your deployments more portable. When you’re working with third-party images, you should check the vendor’s documentation to learn which environment variables are supported and the values that they accept.

How do environment variables work in Kubernetes?

Kubernetes environment variables are defined at the container level within your Kubernetes Pod manifests. Different containers within the Pod can, therefore, use their own sets of environment variables.

You can set environment variables in the env and envFrom manifest fields. env is used to write key-value pairs with hardcoded values, whereas envFrom lets you populate environment variables from the contents of ConfigMaps, Secrets, and runtime Pod properties.

When you start a Pod that defines some environment variables for its containers, Kubernetes will automatically set those variables in the configuration file when it creates the Pod’s containers. The process running inside each container can then access the variables using any available mechanism, such as process.env.DEMO_VAR in Node.js or $DEMO_VAR in Bash.

How to change environment variables after a Pod has been created?

Kubernetes doesn’t allow you to change environment variables after a Pod has been created. You must terminate the Pod and then create a replacement with the updated values. If you’re using a higher-level object such as a Deployment or ReplicaSet, you can update the Pod’s template in that object and scale down the Pod replica count to zero. Once you scale back up again, the new Pods will use the environment variables set in the current template version.

Guide: How to define environment variables in the Kubernetes

There are three ways to define Kubernetes environment variables

  1. Directly in a Kubernetes Pod or container configuration file using the env field
  2. From external sources like ConfigMaps using the envFrom field
  3. Using Kubernetes secrets

Let’s walk through some examples of how to set environment variables for your Kubernetes Pods. Make sure you’ve got Kubectl installed and connected to a cluster so you can follow along below.

1. Set environment variables with env in a Kubernetes configuration file

The env field is the simplest way to set a Kubernetes environment variable. It needs to be nested within the spec.containers section of your Pod manifest.

env lets you define an environment variable as named key-value pair:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:alpine-slim
      env:
        - name: DEMO_VAR
          value: foobar

Let’s prove that this example successfully sets the DEMO_VAR environment variable inside the container. Copy the YAML file, save it as pod.yaml in your working directory, and use Kubectl to create a Pod in your cluster:

$ kubectl apply -f pod.yaml
pod/nginx created

Next, use the kubectl exec command to start an interactive shell session inside the container:

$ kubectl exec -it nginx -- sh

Finally, try echoing out the value of the $DEMO_VAR variable — you’ll see it’s set to foobar, as defined in your Pod manifest:

/ # echo $DEMO_VAR
foobar

This demonstrates the environment variable was successfully set in the container.

2. Set environment variables using ConfigMap values

Kubernetes ConfigMaps are API objects that are purpose-built to store key-value data. It can be easier and more convenient to set a large number of environment variables using a ConfigMap, as this decouples their values from your Pod’s manifest.

Here’s a simple ConfigMap that contains two keys:

apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-config
data:
  debug_mode: "1"
  log_level: "verbose"

You can make the contents stored in the ConfigMap available as Pod environment variables using the envFrom field in your Pod manifest’s spec.containers section:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:alpine-slim
      envFrom:
        - configMapRef:
            name: demo-config

Now, the container’s environment will include the $debug_mode and $log_level environment variables defined by the ConfigMap’s key-value data pairs.

In some situations, you might want to select a subset of values from a ConfigMap or rename their keys before they’re set as environment variables. To do this, replace the envFrom field with its env.valueFrom alternative:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:alpine-slim
      env:
        - name: ENABLE_DEBUG_MODE
          valueFrom:
            configMapKeyRef:
              name: demo-config
              key: debug_mode

In this example, the container receives an environment variable called $ENABLE_DEBUG_MODE that’s set to the value of the ConfigMap’s debug_mode key.

3. Set environment variables using Kubernetes Secrets

Environment variables can also be used to inject data from Kubernetes Secrets. Secrets should be used to store sensitive data, such as any passwords and API tokens that your apps require. They provide greater security and privacy protections, including support for encrypted storage within the Kubernetes control plane.

Below is an example of a Kubernetes Secret file:

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: database-credentials
data:
  DB_USER: YWRtaW4K
  DB_PASSWORD: UEAzMDQ5MTU1dzByZAo=

Note: Values in Secrets must be base64-encoded, as shown in the example above.

You can populate environment variables from Secrets by using the env and envFrom Pod manifest fields in the same way as you reference a ConfigMap. Simply change envFrom.configMapRef to envFrom.secretRef and env.valueFrom.configMapKeyRef to env.valueFrom.secretKeyRef:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:alpine-slim
      env:
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: database-credentials
              key: DB_PASSWORD

4. Set environment variables to pod values

So far, we’ve seen how Kubernetes environment variables let you inject known values into your containers. However, they can also be made to reference certain properties of the Pod the container belongs to, including its name, annotations, host Node, and IP address.

This is achieved using the env.valueFrom.fieldRef.fieldPath field. The following example sets the APP_URL environment variable to the IP address that Kubernetes assigns to the Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:alpine-slim
      env:
        - name: APP_URL
          valueFrom:
            fieldRef:
              fieldPath: status.podIP

You can find a list of all the supported fieldPath values in the Kubernetes documentation.

5. Set environment variables to container resource requests and limits

Finally, environment variables can reference container-level resource requests and limits, too. For example, you might want to set an environment variable that configures your application’s runtime to cap its memory usage to the limit that’s available to the Pod.

This functionality is enabled using the env.valueFrom.resourceFieldRef field. Note that within this field, you must set the containerName property to match the name of the container you’re targeting:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:alpine-slim
      env:
        - name: APP_MEMORY_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: nginx
              resource: limits.memory
      resources:
        requests:
          memory: "100Mi"
        limits:
          memory: "100Mi"

In the example above, the container’s APP_MEMORY_LIMIT environment variable will have the value 104857600. Kubernetes injects the value after resolving it into a numeric bytes quantity instead of using the human-readable form written into your manifest.

Should I use the Kubernetes environment variable for Secret data?

Although Secrets can be injected into containers as environment variables, it’s often safer to access them as mounted files in a volume instead. Data from Secrets will always be visible at the container level, but using files instead of environment variables helps protect you from malicious processes that collect environment variables after compromising a container, preventing further security risks.

Environment variables can be used to supply secrets to your containers, provided their values are actually sourced from Kubernetes Secret objects. It’s not recommended to set secrets as hardcoded env entries or plain ConfigMap keys — this will cause your data to be stored in plaintext.

How to pass environment variables in a Kubernetes deployment YAML manifest

In this guide, we’ve been working with individual Pods. However, it’s best practice to avoid using bare Pods to run real workloads in your cluster. It’s recommended to use Deployment objects instead so you can scale multiple Pod replicas using declarative configuration.

Deployment environment variables are set in the same way as Pods. You should use the familiar env and envFrom fields, but nested under the Pod template section of your Deployment manifest file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
        - name: nginx
          image: nginx:alpine-slim
          env:
            - name: DEMO_VAR
              value: foobar

You can see the full path to the env field is spec.template.spec.env. It specifies that all containers created from the Deployment’s Pod template will be started with the DEMO_VAR variable set to foobar.

Environment variables in Infrastructure as Code

Environment variables are critical to other DevOps tools, too, not just Kubernetes. For example, they’re used by IaC providers like Terraform and Pulumi to enable customization and reuse of your config files. You can use Spacelift to centrally manage environment variables across the IaC systems that you use, ensuring consistent configuration is applied without any duplication.

Mounted files

Every now and then, an environment variable is not what you need – you need a file instead. Terraform Kubernetes provider is a great example. One of the common ways of configuring it involves setting a KUBECONFIG variable pointing to the actual config file, which needs to be present in your workspace as well.

It’s almost like creating an environment variable, though instead of typing (or pasting) the value, you’ll be uploading a file:

kubernetes container environment variables

Similar to environment variables, mounted files can have different visibility settings—you can learn more about them here. One thing to note here is that plaintext files can be downloaded back straight from the UI or API, while secret ones will only be visible to the run executed for the stack.

If you want to learn more about Spacelift, create a free account today or book a demo with one of our engineers.

Key points

In this article, we’ve looked at how you can use environment variables in your Kubernetes applications’ configuration file with any runtime values they require. Environment variables are frequently used to customize app settings and supply required credentials, making your containers more portable across environments.

You can set Kubernetes environment variables using the env and envFrom fields in your Pod manifests. When you’re managing a large number of environment variables, it’s often easiest to create a ConfigMap, but this isn’t a hard requirement.

However, it’s important to use Secrets in conjunction with environment variables when you’re working with sensitive information. Using the same environment variables across multiple applications in the same environment can lead to maintenance issues and potential exposure of sensitive information. Kubernetes secrets can be a solution to this problem.

Manage Kubernetes Faster and More Easily

Spacelift allows you to automate, audit, secure, and continuously deliver your infrastructure. It helps overcome common state management issues and adds several must-have features for infrastructure management.

Start free trial

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide