Configurations via ConfigMap and Secret

Our demo app is a very simple application using no environment variables, but which real world application will work without any env variables? Moreover, we normally want our applications to be easily portable, hence decoupling environment-specific configurations from container images is advised.

Let’s use a new image which adds some variables to our application and update our current deployment via:

kubectl set image deployments/hello-world hello-world-app=vtrhh/hello-world-app:v3

⚠️ If you are a linux user, please use the the following command & image:

kubectl set image deployments/hello-world hello-world-app=vtrhh/hello-world-app:v3-amd64

When checking with kubectl get pods you will see Kubernetes is terminating our running Pods and starting up new ones. When they are up and running, select one of them in the Docker Desktop UI and check the logs:

DockerDesktop Logs

As you can see, we are outputting new logs, but the values for both are undefined.

In order to pass environment variables to the containers in our Pods, we will need to use the Kubernetes objects ConfigMap and Secret. While ConfigMap can be used for non-sensitive data, Secrets should be used for sensitive values such as a password, a token, or a key.

ConfigMap

Lets start with our ConfigMap. In your hello-world-app directory, open the manifest.yaml file and add the following configuration at the end of the file:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: hello-world-app-env-config
data:
  ENVIRONMENT: test

To let Kubernetes know this ConfigMap should be used for our containers, we also need to update our Deployment and reference the value from the Config map.

Please replace your deployment specification at the top of the manifest file with the following lines:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
  labels:
    app: hello-world-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-world-app
  template:
    metadata:
      labels:
        app: hello-world-app
    spec:
      containers:
        - name: hello-world-app
          image: vtrhh/hello-world-app:v3
          resources:
            requests:
              cpu: "100m"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
          env:
            - name: ENVIRONMENT
              valueFrom:
                configMapKeyRef:
                  name: hello-world-app-env-config
                  key: ENVIRONMENT

⚠️ If you are a linux user, please use the following in line 19:

image: vtrhh/hello-world-app:v3-amd64

Our Manifest file now includes a Deployment, a Service and a ConfigMap. As you can see, we are specifying env in our container specs and updated the image version to v3.

Apply your changes via

kubectl apply -f manifest.yaml

Kubernetes will again terminate the old Pods and start new ones. When the are up and running, check the logs in the Docker Desktop UI. We can see that our first env variable is now set to “test”.

Secret

Lets now take care of our super secret string. As the name suggests, this is a value we want to be careful with. Its time for Kubernetes Secret now :)

Let’s add the following configuration at the end of our manifest.yaml file:

---
apiVersion: v1
kind: Secret
metadata:
  name: hello-world-app-secret
type: Opaque
data:
  SUPER_SECRET_STRING: super_duper_secret_string

Of course we do not want to leave “super_duper_secret_string” as it is in our configuration file. Let’s encrypt it with base64 format via running

echo -n 'super_duper_secret_string' | base64

in your terminal. You will receive your encrypted string as an output. Please replace “super_duper_secret_string” in the Manifest file with the output from your terminal.

Again we need to update our deployment to let it know where to find the secret. Hence please replace your deployment specification at the top of the manifest file with the following lines:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
  labels:
    app: hello-world-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-world-app
  template:
    metadata:
      labels:
        app: hello-world-app
    spec:
      containers:
        - name: hello-world-app
          image: vtrhh/hello-world-app:v3
          resources:
            requests:
              cpu: "100m"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
          env:
            - name: ENVIRONMENT
              valueFrom:
                configMapKeyRef:
                  name: hello-world-app-env-config
                  key: ENVIRONMENT
            - name: SUPER_SECRET_STRING
              valueFrom:
                secretKeyRef:
                  name: hello-world-app-secret
                  key: SUPER_SECRET_STRING

⚠️ If you are a linux user, please use the following in line 19:

image: vtrhh/hello-world-app:v3-amd64

Apply your changes via

 kubectl apply -f manifest.yaml

Check the Docker Desktop UI after the new Pods are running - and there we now have both variables set 🎉