What I learned about Kubernetes when trying to mount config maps into a docker container that already have an existing file in the same directory.
A few weeks ago, I made a simple application named tweetor that was about a simple tutorial to create Kubenernetes Clusters in Google Cloud Platform (GCP). It was the part of a project I made called “Kube X-mas”. This project is a series of article written in Bahasa Indonesia to create a live application in Kubernetes at GCP, you could see the series here: https://medium.com/easyread/christmas-tale-of-sofware-engineer-project-kube-xmas-9167ebca70d2
In that project, I will deploy a Golang application into a Kubernetes cluster in GCP. As we know, when developing an application, it must separate its config file, whether it’s in Environment variable, or just in a config file ( .json, .yaml, .toml, etc). So it can be more flexible, we can change the environment staging, production or testing.
In my case, I will dockerize my application in a Docker image, then when deploying it to Kubernetes, I will use Kubernetes controller to inject the configuration file, so it can run with the injected configuration file.
So, basically, in Kubernetes, we can inject (mount) file into a container. In my case, I will mount a config file of my application into my docker containers. To do this, I can use the Kubernetes ConfigMap and Volumes, it allows us to inject configuration files into our docker application containers.
To be clear, I have a Go (Golang) application that builds and containerized in a docker image. This application already compiled and build and saved in a docker image.
This is my Dockerfile.
So it will create a Docker image that will contain the compiled go application in /app/engine. But this application will need a config file, so it can run and live. I need to inject the config file so it can run.
inject the config to docker container
And then, I use the Kubernetes config maps to inject my application config file.
But, the issue then happen. What I expect is, when injecting this config file on the same path. Let’s say my working directory in the container is /app
app<br><code class="markup--code markup--pre-code">└──</code> engine
What I expect after injected the config maps with mount volume:
app<br><code class="markup--code markup--pre-code">├── config.toml<br>└──</code> engine
What it really happens:
app<br><code class="markup--code markup--pre-code">└──</code> config.toml
Instead of adding a new file, the Kubernetes mount volume will replace all the file, and it removes the existing file.
I’m stuck in this issue for 4 hours because I don’t realize it first. My pods keep crashing and restarted. Until then, I try to debug it slowly and realized that if I mount a file that will also delete the existing file if it has the same directory.
After realizing the issue, there are two options I can choose.
Separate my working directory in Docker container with the directory of my application in the container. So, instead use the /app as my working directory in the container, I will create a new directory that will my WORKDIR. And I will put my config file in that folder.Trying to figure out it until it solved.
Option 1 is really obvious, and it solves the problems. At the time, when facing this issue, I use option 1. But a few days later, just out of curiosity, I try to solve option 2. I try to read again many resources (official documentation) and blog post if any kind of this issue ever happens to anyone and how to fix it.
But, I found nothing, except this https://blog.sebastian-daschner.com/entries/multiple-kubernetes-volumes-directory. In this article, he explains about multiple Kubernetes volumes directory. So I’m curious if this will also can solve my problem.
In that article, he said to use subPath, and so be it, then I try to use the subPath too in my applications deployment for Kubernetes.
- name: configs <br> mountPath: /app
And changed into:
- name: configs<br> mountPath: /app/config.toml<br> subPath: config.toml
And voila, it works. It does not replace and delete my existing file in the container anymore. And it can run smoothly.
My full Kubernetes deployment.yaml file:
Well, when solving this, I learn something important. Even I stuck for 4–6 hours when solving this “alone”, but I learned a valuable lesson here. And can’t look forward to the next adventure.
Anyway, if you find this useful would you mind to share this story, so everyone will not fall to the same hole. And follow me to keep updates to my learning journey in Software Engineering :)
Translated to Bahasa Indonesia here: https://medium.com/easyread/mount-file-ke-kubernetes-pod-tanpa-menghapus-existing-file-1d9fc444c91a