Kubernetes 101 – Application Configuration
This is the fifth in a series of blog posts that will explain the different components of Kubernetes. Primarily because if I can explain it here, I’ll have learned it quite well myself.
The first part is about Pods and can be found here.
The second part is about Controllers and can be found here.
The third part is about Services and can be found here.
The fourth part is about Volumes and can be found here.
Typically most applications require some configuration before they’ll run in the manner that is intended. This is usually to ensure portability of the codebase and to avoid hard coding configuration within the application.
How exactly do you get configuration into an application when it is running in an ephemeral pod? That configuration will need to be set every time the application starts.
Kubernetes has a number of methods to achieve this.
Traditional Configuration Options
Usually to configure your traditional application you’d be looking at one of the below options:
- Pass command line arguments when starting the application
- Use environment variables
- Use a configuration file
If you continue to think along the same lines, these are all possible with a cloud native application. They’re also possible within Kubernetes. They do require configuration being added to a kubernetes manifest everytime you move the application to a different environment. Depending where you store your manifests this is potentially a security concern as well.
Let’s take a quick look at how you might configure these.
Command Line Arguments
To pass arguments into your application you can take two different approaches with command line arguments.
- Hardcode the arguments into the dockerfile when you build the application.
- Add the arguments into the kubernetes manifest for the pod (by whichever method you’re deploying pods)
I’m sure you can see the downsides to both of these. In the first one, you’d need a different dockerfile and therefore a different container for every different environment. Hardly portable is it? For the second option, you’d need to manually change the pod manifest everytime you moved environment.
While both of these would work, they’re both prone to human error and require additional configuration every time you move environments. Can you imagine the times an application is moved from development into staging and for it to not work?
Kubernetes enables you to set environment variables in each container. At this point they need to be set at each container within a pod, there’s no way to set them at the pod level and have them inherited in each pod. While using environment variables enables simpler configuration within the pod manifest, it’s still manual configuration that needs to be performed between every different environment.
If you applied traditional thinking to a configuration file, you’d mount a static configuration file via a volume in each pod. This would absolutely work, but it would still be very easy to point a development application at a production configuration file.
To further decouple the application configuration and to remove an element of typing Kubernetes has an object called a configMap. This enables you to put the application configuration into a kubernetes manifest and reference it from the pod manifest. An important part of this is that a configMap is a namespaced resource. Meaning that you can have the same name for the configMap but have different values in it. Moving an application from development to production suddenly doesn’t have the risk factor as you’re not touching the configuration. It also enables you to keep applications & configuration separate, which means they can be kept in separate repositories.
A configMap can still be transformed into configuraiton files, environment variables or command line arguments so you’re still retaining that flexibility. If you expose the configuration as a volume, you’ve also got the option to update configuration without restarting the pod. This is application specific and you should consider your use case, but it’s possible!
The object we’re going to look at is secrets. These work in a very similar way to a configMap but are designed for sensitive data. That’s not to say it’s secure, but that is a topic for a future blog post. So what is the difference between configMaps & secrets? Secrets came first for a start, configMaps came about because working with secrets was a bit annoying. This is down to the two main differences:
- Secrets are base64 encoded. So have to be decoded everytime they need to be read.
- Secrets have a 1MB limit. Not a problem most of the time, but you can be sure it is a problem sometimes.
So you’ll see that there are plenty of options to get your application configuration into your containerised application running on Kubernetes. As with everything it’s important to consider the trade offs against the use case before making a call as to which one to use.