#Day35 : Day 35: Mastering ConfigMaps and Secrets in Kubernetes🔒🔑🛡️

#Day35 : Day 35: Mastering ConfigMaps and Secrets in Kubernetes🔒🔑🛡️

Table of contents

No heading

No headings in the article.

Hello folks!

Today, I am going to talk about and implement ConfigMaps and Secrets in Kubernetes.

In this article, I have discussed

  • ConfigMaps and Secrets in layman language

  • Created a ConfigMap and set it in the pod at environment variable level

  • Created a ConfigMap and mounted it in the pod using volume mounts

  • Created a Secrets file and mounted it in the pod using volume mounts.

Lets dive in straight to the topic:

ConfigMaps

In a Kubernetes cluster, different applications need to talk to each other. For example: There is a backend application that needs to talk to the DB to retrieve information and provide it back to the user.

For retrieving information, the application needs to have certain info such as port, password for DB. This cannot be hardcoded as there is a possibility, it might be changed by DB admins at certain points.

For this reason, all the information for communication must be stored in configMaps or secrets and the configMap needs to be mounted to the pod, so that the pod can retrieve the information from the file.

Secrets

If this is the case, then what is the use of secrets?

Secrets store sensitive information such as ID, passwords in the encrypted format so that this data is secure and not accessible by hackers at the etcd level or using kubectl describe or edit.

Hands-on:

Lets check for any open deployments:

kubectl get deploy

There are no current deployments present.

Lets create a ConfigMap first named cm.yml

vim cm.yml

Type the following in the cm.yml file :

apiVersion: v1
kind: ConfigMap
metadata:
  name: test-cm
data:
  db-port: "3306"

No need to remember it as you can get the format on kubernetes official documentation website.

Now create it using:

kubectl apply -f cm.yml

ConfigMap file is now created. Check it using

kubectl get cm

test-cm is the congfigmap that we created just now.

You can check the contents using

kubectl describe cm test-cm

This is the configmap that I created.

Now my aim will be to use the fields containing port data from configmap and use them as environment variables inside my Kubernetes pod. For that we will need to create a pod.

We already have a Python Django application that we are using from the public Github Repo: https://github.com/iam-veeramalla/Docker-Zero-to-Hero.git

Lets create a deployment file now

vim deployment.yml

We will just use the deployment format from Kubernetes official documentation and edit the fields according to our app

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-python-app
  labels:
    app: sample-python-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-python-app
  template:
    metadata:
      labels:
        app: sample-python-app
    spec:
      containers:
      - name: python-app
        image: abhishekf5/python-sample-app-demo:v1
        ports:
        - containerPort: 8000

Lets create the deployment for the following

kubectl apply -f deployment.yml

Now, that the pod is up and running lets exec into the pod and check for env variables -

We cannot see any env variables as it does not have information of any database port. But, I want to know the port of db.

For that I have to edit the deployment.yml file and modify it.

We need to provide something called as env so it reads the value as environment variable -

For this, make the following changes in deployment.yml file:

Below image tag, add the following

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-python-app
  labels:
    app: sample-python-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-python-app
  template:
    metadata:
      labels:
        app: sample-python-app
    spec:
      containers:
      - name: python-app
        image: abhishekf5/python-sample-app-demo:v1
        env:
         - name: DB-PORT
           valueFrom:
            configMapKeyRef:
             name: test-cm
             key: db-port
        ports:
        - containerPort: 8000

In this, we have added the env variable in which we have specified -

valueFrom: It will take the required value from

configMapKeyRef: Specify the details of the configmap configured

name: Name of the configmap

key: Inside the configmap, the key to which value is defined.

Now, again re-apply the deployment file so that it is configured.

kubectl apply -f deployment.yml

Now lets check again whether we can find the DB port inside the pod.

kubectl exec -it <pod_name> -- /bin/bash

Once inside the pod -

env | grep DB

Now we can see the port -

But in this case, if we change the port in the cm.yml file, the container will not take the new port but continue using the port specified as containers cannot be given new ports one they are assigned before, which will lead to failure connecting to the DB.

Hence, the approach of Volume Mounts is used.

To implement this open the deployment.yml file again, remove the env mounts and make the following changes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-python-app
  labels:
    app: sample-python-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-python-app
  template:
    metadata:
      labels:
        app: sample-python-app
    spec:
      containers:
      - name: python-app
        image: abhishekf5/python-sample-app-demo:v1
        volumeMounts:
        - name: db-connection
          mountPath: /opt
        ports:
        - containerPort: 8000
      volumes:
      - name: db-connection
        configMap:
          name: test-cm
kubectl get pods

Now to check whether the defined DB port is present inside the pod -

kubectl exec -it <pod-name> -- /bin/bash

Since, in the volume format, ConfigMap is present inside file systems.

Now lets try to change the port number in the ConfigMap file.

vim cm.yml

We have changed the port to 3307. Now lets re-apply the cm.yml file.

kubectl apply -f cm.yml

Now, lets exec into the pod and without re-running it and check whether the port number has changed.

kubectl exec -it <pod-name> -- /bin/bash

Now when inside the pod,

cat /opt/db-port | more

Thus, the port has changed from 3306 to 3307.

Now lets check how to configure secrets -

Another way of creating config files or secrets is using create command. Lets create a secret using the same -

kubectl create secret generic test-secret --from-literal=db

Since it is a secret and is designed to hold sensitive information, it will not show the info when asked to describe. Lets try to edit the secrets file

kubectl edit secrets test-secret

You can see that the db-port that is specified as a secret is shown in base 64 encrypted format. But base 64 encryption is not that great, so we can encrypt in our own way.

As base 64 encryption can be easily decoded using

echo MzMwNg== | base64 --decode

It will give value as 3306. Hence Kubernetes does not provide great encryption and hence we can use other apps or vaults for encryption.

So for mounting it in the pod, go to the deployment.yml file

Add the secrets to volume and volume mounts as shown below

vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-python-app
  labels:
    app: sample-python-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-python-app
  template:
    metadata:
      labels:
        app: sample-python-app
    spec:
      containers:
      - name: python-app
        image: abhishekf5/python-sample-app-demo:v1
        volumeMounts:
        - name: db-connection
          mountPath: /opt
        - name: db-secrets
          readOnly: true
          mountPath: /opt/secrets
        ports:
        - containerPort: 8000
      volumes:
      - name: db-connection
        configMap:
          name: test-cm
      - name: db-secrets
        secret:
          secretName: test-secret

As you can see, we have added the db-secrets in volumes and stored the secrets in /opt/secrets.

Lets check whether it is present in /opt/secrets

kubectl exec -it <pod-name> -- /bin/bash

Inside the pod,

cat /opt/secrets/db-port

It will show the secret stored in the pod.