Kubernetes Configmap with files to deploy Rails apps

Rahul Mahale

By Rahul Mahale

on May 25, 2017

This post assumes that you have basic understanding of Kubernetes terms like pods and deployments.

We deploy our Rails applications on Kubernetes and frequently do rolling deployments.

While performing application deployments on kubernetes cluster, sometimes we need to change the application configuration file. Changing this application configuration file means we need to change source code, commit the change and then go through the complete deployment process.

This gets cumbersome for simple changes.

Let's take the case of wanting to add queue in sidekiq configuration.

We should be able to change configuration and restart the pod instead of modifying the source-code, creating a new image and then performing a new deployment.

This is where Kubernetes's ConfigMap comes handy. It allows us to handle configuration files much more efficiently.

Now we will walk you through the process of managing sidekiq configuration file using configmap.

Starting with configmap

First we need to create a configmap. We can either create it using kubectl create configmap command or we can use a yaml template.

We will be using yaml template test-configmap.yml which already has sidekiq configuration.

1apiVersion: v1
2kind: ConfigMap
3metadata:
4  name: test-staging-sidekiq
5  labels:
6    name: test-staging-sidekiq
7  namespace: test
8data:
9  config: |-
10    ---
11    :verbose: true
12    :environment: staging
13    :pidfile: tmp/pids/sidekiq.pid
14    :logfile: log/sidekiq.log
15    :concurrency: 20
16    :queues:
17      - [default, 1]
18    :dynamic: true
19    :timeout: 300

The above template creates configmap in the test namespace and is only accessible in that namespace.

Let's launch this configmap using following command.

1
2$ kubectl create -f  test-configmap.yml
3configmap "test-staging-sidekiq" created
4

After that let's use this configmap to create our sidekiq.yml configuration file in deployment template named test-deployment.yml.

1---
2apiVersion: extensions/v1beta1
3kind: Deployment
4metadata:
5  name: test-staging
6  labels:
7    app: test-staging
8  namespace: test
9spec:
10  template:
11    metadata:
12      labels:
13        app: test-staging
14    spec:
15      containers:
16      - image: <your-repo>/<your-image-name>:latest
17        name: test-staging
18        imagePullPolicy: Always
19       env:
20        - name: REDIS_HOST
21          value: test-staging-redis
22        - name: APP_ENV
23          value: staging
24        - name: CLIENT
25          value: test
26        volumeMounts:
27            - mountPath: /etc/sidekiq/config
28              name: test-staging-sidekiq
29        ports:
30        - containerPort: 80
31      volumes:
32        - name: test-staging-sidekiq
33          configMap:
34             name: test-staging-sidekiq
35             items:
36              - key: config
37                path:  sidekiq.yml
38      imagePullSecrets:
39        - name: registrykey
40

Now let's create a deployment using above template.

1
2$ kubectl create -f  test-deployment.yml
3deployment "test-pv" created
4

Once the deployment is created, pod running from that deployment will start sidekiq using the sidekiq.yml mounted at /etc/sidekiq/config/sidekiq.yml.

Let's check this on the pod.

1
2deployer@test-staging-2766611832-jst35:~$ cat /etc/sidekiq/config/sidekiq_1.yml
3---
4:verbose: true
5:environment: staging
6:pidfile: tmp/pids/sidekiq_1.pid
7:logfile: log/sidekiq_1.log
8:concurrency: 20
9:timeout: 300
10:dynamic: true
11:queues:
12  - [default, 1]
13

Our sidekiq process uses this configuration to start sidekiq. Looks like configmap did its job.

Further if we want to add one new queue to sidekiq, we can simply modify the configmap template and restart the pod.

For example if we want to add mailer queue we will modify template as shown below.

1apiVersion: v1
2kind: ConfigMap
3metadata:
4  name: test-staging-sidekiq
5  labels:
6    name: test-staging-sidekiq
7  namespace: test
8data:
9  config: |-
10    ---
11    :verbose: true
12    :environment: staging
13    :pidfile: tmp/pids/sidekiq_1.pid
14    :logfile: log/sidekiq_1.log
15    :concurrency: 20
16    :queues:
17      - [default, 1]
18      - [mailer, 1]
19    :dynamic: true
20    :timeout: 300

Let's launch this configmap using following command.

1
2$ kubectl apply -f  test-configmap.yml
3configmap "test-staging-sidekiq" configured
4

Once the pod is restarted, it will use new sidekiq configuration fetched from the configmap.

In this way, we keep our Rails application configuration files out of the source-code and tweak them as needed.

Stay up to date with our blogs. Sign up for our newsletter.

We write about Ruby on Rails, ReactJS, React Native, remote work,open source, engineering & design.