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.