Kubernetes – ConfigMaps

Kubernetes – ConfigMaps

February 20, 2019 3 By Eric Shanks

Sometimes you need to add additional configurations to your running containers. Kubernetes has an object to help with this and this post will cover those ConfigMaps.

ConfigMaps – The Theory

Not all of our applications can be as simple as the basic nginx containers we’ve deployed earlier in this series. In some cases, we need to pass configuration files, variables, or other information to our apps.

The theory for this post is pretty simple, ConfigMaps store key/value pair information in an object that can be retrieved by your containers. This configuration data can make your applications more portable.

For example, you could have a key value pair of “environment:dev” in a configmap for your development Kubernetes cluster. When you deploy your apps, you can key some of your logic off of the “environment” variable and do different things for production vs. development environments. I’m not sure this is necessary, but it’s just an example to get you thinking about it. Let’s see these ConfigMaps in action and I think you’ll get the picture.

ConfigMaps – In Action

For a ConfigMap example, we’ll take a simple two tier app (lovingly called hollowapp) and we’ll configure the database connection string through a ConfigMap object. Try to put out of your mind how insecure this is for the moment, it’s just an example to prove the point.

Here is a high level diagram of the lab we’ll be building. As you can see some of the items we’ve talked about in previous posts have been generalized. The main part is the App container using the ConfigMap to configure the connection string to the database service.

First, we’ll deploy the database container and service. The database container has already been configured with new database with the appropriate username and password. The manifest file to deploy the DB and service is listed below.

apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: hollowdb 
  labels: 
    app: hollowdb
spec: 
  replicas: 1 
  selector: 
    matchLabels:
      app: hollowdb 
  template: 
    metadata:
      labels: 
        app: hollowdb
    spec:
      containers:
      - name: mysql 
        image: theithollow/hollowapp-blog:dbv1 
        imagePullPolicy: Always
        ports:
        - containerPort: 3306 
---
apiVersion: v1 
kind: Service 
metadata: 
  name: hollowdb 
spec: 
  ports: 
  - name: mysql
    port: 3306
    targetPort: 3306
    protocol: TCP
  selector: 
    app: hollowdb

To deploy the manifests, we run our familiar command:

kubectl apply -f [manifest file].ymlCode language: CSS (css)

OK, the Database is deployed and ready to go. Now we need to deploy a ConfigMap with the database connection string.

The ConfigMap is listed below in another manifest file. Most of the configuration in the manifest should look familiar to you. The kind has been updated to a type of “ConfigMap”, but the important part is the data field. We have a key named. db.string and the value of that key is our connection string (yes, with the clear text super secret password).

apiVersion: v1
kind: ConfigMap
metadata:
  name: hollow-config
data: 
  db.string: "mysql+pymysql://hollowapp:Password123@hollowdb:3306/hollowapp" #Key Value pair Value being a database connection stringCode language: PHP (php)

Deploy the ConfigMap using the same apply command as before and change the manifest file name.

kubectl apply -f [manifest file].ymlCode language: CSS (css)

Now you can run a get command to list the ConfigMap.

kubectl get configmapCode language: JavaScript (javascript)

Now, before we deploy our app, lets deploy a test container to prove that we can read that key value pair from the ConfigMap.

The manifest below has an environment variable named DATABASE_URL and we’re telling it to get the value of that environment variable from the ConfigMap named hollow-config. Within the hollow-config ConfigMap, we’re looking for the key named db.string. The result that will be the value stored in our DATABASE_URL variable.

apiVersion: v1
kind: Pod
metadata:
  name: shell-demo
spec:
  containers:
  - name: nginx
    image: nginx
    env:
    - name: DATABASE_URL
      valueFrom: 
        configMapKeyRef:
          name: hollow-config
          key: db.stringCode language: CSS (css)

Deploy the test shell-demo container with the kubectl apply command.

kubectl apply -f [manifest file].ymlCode language: CSS (css)

Once it’s deployed, you can get an interactive shell into that container by running the following command.

kubectl exec -it shell-demo -- /bin/bashCode language: JavaScript (javascript)

Once we have a shell session, we can do an echo on our DATABASE_URL environment variable and it should show the string from our ConfigMap.

You can exit the shell session and then we’re ready to deploy our app. The manifest for the app is shown below. NOTE: it does require that you have your ingress controller running if you plan to access it through a browser.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
      app: hollowapp
  name: hollowapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hollowapp
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: hollowapp
    spec:
      containers:
      - name: hollowapp
        image: eshanks16/k8s-hollowapp:v2
        imagePullPolicy: Always
        ports:
        - containerPort: 5000
        env:
        - name: SECRET_KEY
          value: "my-secret-key"
        - name: DATABASE_URL
          valueFrom: 
            configMapKeyRef:
              name: hollow-config
              key: db.string
---
apiVersion: v1
kind: Service
metadata:
  name: hollowapp
  labels:
    app: hollowapp
spec:
  type: ClusterIP
  ports:
  - port: 5000
    protocol: TCP
    targetPort: 5000
  selector:
    app: hollowapp
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: hollowapp
  labels:
    app: hollowapp
spec:
  rules:
  - host: hollowapp.hollow.local
    http:
      paths:
      - path: /
        backend:
          serviceName: hollowapp
          servicePort: 5000Code language: PHP (php)

Deploy the app with the same command.

kubectl apply -f [manifest file].ymlCode language: CSS (css)

The result is that our app is communicating correctly with our back end database container all because of our ConfigMap.

Summary

So this isn’t the most secure way to pass connection information to your containers, but it is a pretty effective way of storing parameters that you might need for your applications. What will you think of to use ConfigMaps for?