Skip to main content

[SOLVED] How to set dynamic values with Kubernetes yaml file - kubernetes

[SOLVED] Mastering Dynamic Values in Kubernetes YAML Files

In Kubernetes, managing settings in a smart way is important. This helps us build strong and flexible applications. In this chapter, we will look at different ways to set dynamic values in Kubernetes YAML files. This will help us change our deployments for different situations easily. We will check out several methods so that we have the right tools to manage settings in our Kubernetes environment.

In this chapter, we will talk about these solutions:

  • Solution 1: Using Environment Variables for Dynamic Configuration
  • Solution 2: ConfigMaps for Managing Dynamic Values
  • Solution 3: Secrets for Sensitive Dynamic Data
  • Solution 4: Helm Charts for Parameterized YAML Files
  • Solution 5: Kustomize for Overriding Configuration Values
  • Solution 6: Using the Downward API for Pod Metadata

By the end of this chapter, we will understand how to use these methods well. If you want to learn more about Kubernetes settings, you may like our article about how to set multiple commands in Kubernetes. Also, learning how to handle sensitive data is very important, so check out our guide on Secrets for Sensitive Dynamic Data. Let’s jump into each solution to improve our skills in Kubernetes configuration!

Solution 1 - Using Environment Variables for Dynamic Configuration

Environment variables are a simple way to set dynamic values in Kubernetes YAML files. We can use them to inject configuration data into our containers while they run. This method lets us have flexible and dynamic setups. We do not need to change the container image or the YAML file.

Setting Environment Variables in Pod Specifications

We can define environment variables right in the spec section of our Pod or Deployment YAML file. Here is how we can do it:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app-container
          image: my-app-image:latest
          env:
            - name: DATABASE_URL
              value: "mongodb://my-mongo-service:27017"
            - name: APP_MODE
              value: "production"

In this example:

  • The DATABASE_URL and APP_MODE are environment variables for the container my-app-container.
  • We can access these variables in our application code. This allows us to change the setup based on the environment.

Using ConfigMap for Environment Variables

If we have many environment variables or want to manage them separately from our deployment, we can use a ConfigMap. This helps us to keep configuration apart from the deployment.

  1. Create a ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config
data:
  DATABASE_URL: "mongodb://my-mongo-service:27017"
  APP_MODE: "production"
  1. Reference the ConfigMap in our Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app-container
          image: my-app-image:latest
          env:
            - name: DATABASE_URL
              valueFrom:
                configMapKeyRef:
                  name: my-app-config
                  key: DATABASE_URL
            - name: APP_MODE
              valueFrom:
                configMapKeyRef:
                  name: my-app-config
                  key: APP_MODE

In this setup:

  • The ConfigMap called my-app-config holds the environment variables. We refer to them in the Deployment.
  • This way is easier to update configuration values. When we change the ConfigMap, it will update the environment variables in the Pods.

Accessing Environment Variables in Your Application

In our application, we can use standard methods to access these environment variables. For example, in Python, we would write:

import os

database_url = os.getenv('DATABASE_URL')
app_mode = os.getenv('APP_MODE')

Conclusion

Using environment variables in Kubernetes is a good way to manage dynamic configurations. We can do this directly in our YAML files or through ConfigMaps. This makes our applications flexible and easy to manage. For more details on how to manage configurations, please check this article on how to set dynamic values in Kubernetes YAML files.

Solution 2 - ConfigMaps for Managing Dynamic Values

We can use ConfigMaps in Kubernetes to manage changing configuration data apart from our application code. This helps us change configuration values easily without rebuilding our container images or redeploying our apps. ConfigMaps hold key-value pairs. Our pods can use this data in different ways.

Creating a ConfigMap

To create a ConfigMap, we can write it in a YAML file or use the kubectl command line tool. Here is an example of how we can create a ConfigMap using a YAML file.

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  DATABASE_URL: "postgres://user:password@hostname:5432/dbname"
  API_KEY: "12345-abcde-67890"

We can apply this config with this command:

kubectl apply -f configmap.yaml

Using ConfigMaps in Pods

After we create a ConfigMap, we can use it in our pods in a few ways. We can use it as environment variables, command-line arguments, or files in a volume.

1. Using ConfigMaps as Environment Variables

We can use ConfigMap values as environment variables in our pod specs:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: my-app-image
          env:
            - name: DATABASE_URL
              valueFrom:
                configMapKeyRef:
                  name: my-config
                  key: DATABASE_URL
            - name: API_KEY
              valueFrom:
                configMapKeyRef:
                  name: my-config
                  key: API_KEY

2. Using ConfigMaps as Volume Mounts

We can also mount a ConfigMap as a volume. This gives us configuration data as files:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: my-app-image
          volumeMounts:
            - name: config-volume
              mountPath: /etc/config
      volumes:
        - name: config-volume
          configMap:
            name: my-config

In this way, the entries in the ConfigMap will show as files in the /etc/config folder of the container.

Updating ConfigMaps

We can update a ConfigMap with the kubectl command. Our pods can reload changes automatically without restarting. But we should remember that we might need to change our application logic to pick up these updates.

To update the ConfigMap, we can use:

kubectl create configmap my-config --from-literal=NEW_KEY=new_value --dry-run=client -o yaml | kubectl apply -f -

For more details on managing ConfigMaps and their best practices, we should check the official Kubernetes documentation.

Using ConfigMaps well lets us manage changing values in Kubernetes apps easily. For more insights on Kubernetes configurations, we can look at this article on how to set dynamic values with Kubernetes YAML files.

Solution 3 - Secrets for Sensitive Dynamic Data

Kubernetes gives us a strong way to manage sensitive information. This includes passwords, OAuth tokens, and SSH keys. We use Secrets for this. Secrets help us store and manage sensitive data more safely than putting it directly in our application code or in configuration files.

Creating a Secret

To create a Secret, we can use a YAML file or the command line. Here is an example of creating a Secret with a YAML file.

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: YWRtaW4= # base64 encoded value of 'admin'
  password: cGFzc3dvcmQ= # base64 encoded value of 'password'

We can create this Secret by saving it in a file called secret.yaml. Then we run this command:

kubectl apply -f secret.yaml

We can also create a Secret directly from the command line:

kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=password

Using Secrets in Pods

After we created a Secret, we can use it in our pods as environment variables or as files in a volume.

Using Secrets as Environment Variables:

Here is how we can use Secrets as environment variables in a Pod definition:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
    - name: my-container
      image: my-image
      env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: username
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: password

Using Secrets as Volumes:

We can also mount Secrets as files inside the container. Here is an example:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
    - name: my-container
      image: my-image
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secret
  volumes:
    - name: secret-volume
      secret:
        secretName: my-secret

With this setup, username and password will be files in /etc/secret/username and /etc/secret/password inside the container.

Benefits of Using Secrets

  • Security: Secrets are base64 encoded. They are not in plain text in our configuration files.
  • Fine-Grained Access Control: We can control who can access Secrets using Kubernetes RBAC (Role-Based Access Control).
  • Ease of Management: We can change Secrets without needing to rebuild or redeploy our application’s container images.

For more details on how to manage sensitive data in Kubernetes, you can check the Kubernetes documentation on Secrets. This way, we keep our sensitive information safe while still allowing our applications to access it easily.

Solution 4 - Helm Charts for Parameterized YAML Files

Helm is a strong tool for Kubernetes. It helps us deploy and manage applications more easily. Helm uses charts. Charts are packages with ready-made Kubernetes resources. With Helm, we can set dynamic values using templates. This makes it simpler to handle settings in our Kubernetes YAML files.

Creating a Helm Chart

To begin using Helm, we first need to create a Helm chart. We can do this by running this command:

helm create my-chart

This command makes a folder called my-chart. It will have all the files and structure we need.

Parameterizing Values

In the my-chart folder, we will see a file named values.yaml. This file holds the default values for our settings. We can change this file to add dynamic values. For example:

replicaCount: 1

image:
  repository: my-app
  tag: latest
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

resources: {}

Using Templates in Deployment YAML

Helm uses Go templates to help us add parameters to our Kubernetes YAML files. For example, in the templates/deployment.yaml file, we can use the values from values.yaml with the {{ .Values }} format:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
  labels:
    app: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Release.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
            - containerPort: {{ .Values.service.port }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}

Installing the Chart

After we set up our chart with dynamic values, we can install it with this command:

helm install my-release my-chart

We can also change the default values when we install by using a custom values.yaml file:

helm install my-release my-chart -f custom-values.yaml

Benefits of Using Helm for Dynamic Values

  • Version Control: We can version Helm charts and save them in repositories. This helps us manage application versions well.
  • Reusability: We can use charts in different environments by changing the values.yaml file.
  • Simplified Management: Helm gives us commands to upgrade, roll back, and delete releases. This makes managing our applications in Kubernetes easier.

For more details on using Helm for Kubernetes settings, we can check the official Helm documentation. By using Helm charts, we can make it easier to manage dynamic values in our Kubernetes YAML files.

Solution 5 - Kustomize for Overriding Configuration Values

Kustomize is a helpful tool that we use with kubectl. It helps us manage Kubernetes YAML files with easy customization. We can create a base setup and then apply changes to specific values without changing the original files. This is great when we have different environments like development, testing, and production that need different settings.

Getting Started with Kustomize

  1. Install Kustomize: Kustomize is included with kubectl. So, we need to have the latest version of kubectl. We can check our version by running:

    kubectl version --short
  2. Directory Structure: We should organize our YAML files in a clear way. Here is an example of how to do it:

    my-k8s-app/
    ├── base/
    │   ├── deployment.yaml
    │   ├── service.yaml
    │   └── kustomization.yaml
    └── overlays/
        ├── dev/
        │   └── kustomization.yaml
        └── prod/
            └── kustomization.yaml

Base Configuration

In the base/kustomization.yaml, we define the resources that are common for all environments:

resources:
  - deployment.yaml
  - service.yaml

Our deployment.yaml might look like this:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app-container
          image: my-app-image:latest
          ports:
            - containerPort: 80

Overlay Configuration

For each environment, we create an overlay kustomization.yaml.

Development Overlay

In overlays/dev/kustomization.yaml, we can change values for the development environment:

bases:
  - ../../base

patchesStrategicMerge:
  - deployment-patch.yaml

We create a deployment-patch.yaml in the same folder to change the deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2 # Increase replicas for dev
  template:
    spec:
      containers:
        - name: my-app-container
          image: my-app-image:dev # Use a different image for dev

Production Overlay

In overlays/prod/kustomization.yaml, we may want to change the image and replicas:

bases:
  - ../../base

patchesStrategicMerge:
  - deployment-patch.yaml

And the deployment-patch.yaml for production:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3 # Higher replicas for production
  template:
    spec:
      containers:
        - name: my-app-container
          image: my-app-image:prod # Use production image

Building and Applying Kustomize Configuration

To build and apply our configuration for a specific environment, we use these commands:

For development:

kubectl apply -k overlays/dev

For production:

kubectl apply -k overlays/prod

Benefits of Using Kustomize

  • Separation of Concerns: We keep a clear separation of base and environment-specific configurations.
  • Easy Management: We can manage changes across multiple environments without making duplicate YAML files.
  • Version Control: We keep our base configuration consistent and version-controlled while allowing changes in overlays.

Kustomize is a great way to manage different configurations in Kubernetes. It makes the deployment process easier and follows best practices in Kubernetes resource management. For more details on Kustomize, we can check the Kubernetes documentation.

Solution 6 - Using the Downward API for Pod Metadata

The Downward API in Kubernetes is a strong tool. It helps us show pod and container information to apps running in our pods. This is very helpful for apps that need to know about their surroundings. They might need info like the pod name, namespace, labels, annotations, and more. The Downward API lets us set changing values right into our container’s environment variables or as files in a volume.

Setting Pod Metadata Using Environment Variables

We can use the Downward API to set environment variables in our container that show pod information. Here is an example of how to do this in our Kubernetes YAML setup.

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: my-app
spec:
  containers:
    - name: my-container
      image: my-image:latest
      env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP

In this setup:

  • POD_NAME will show the name of the pod.
  • POD_NAMESPACE will have the namespace where the pod is running.
  • POD_IP will keep the IP address given to the pod.

Using Downward API to Mount Metadata as Files

We can also use the Downward API to write information to files in a volume. This is good for apps that read settings from files instead of environment variables. Here is how we can do it:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: my-container
      image: my-image:latest
      volumeMounts:
        - name: podinfo
          mountPath: /etc/podinfo
  volumes:
    - name: podinfo
      downwardAPI:
        items:
          - path: "name"
            fieldRef:
              fieldPath: metadata.name
          - path: "namespace"
            fieldRef:
              fieldPath: metadata.namespace
          - path: "labels"
            fieldRef:
              fieldPath: metadata.labels

In this example:

  • We create a volume called podinfo using the Downward API.
  • The pod name, namespace, and labels are saved to files in /etc/podinfo/ inside the container.
  • For example, the file /etc/podinfo/name will have the pod’s name.

Using the Downward API in Kubernetes helps us set changing values that our apps can use. This lets them adjust based on where they are running. This feature is very helpful for apps that need to know their running environment.

For more details on getting Kubernetes information, we can look at this guide. In conclusion, we looked at different ways to set dynamic values in Kubernetes YAML files. We talked about using environment variables, ConfigMaps, Secrets, Helm Charts, and Kustomize. These methods make our Kubernetes setups more flexible and safe. They also help us manage applications better.

By learning these tricks, we can improve our Kubernetes deployment. For more helpful info, we can read articles on subjects like how to set multiple commands in Kubernetes and how to pull environment variables.

Comments