[Kustomize series — Part 3]A DevOps perspective on application deployment using Kustomize in Kubernetes
By: Manish Joshi
Tags: Deployment, Kubernetes Deployment, Openshift, Kustomize, Kubernetes

So far in Part 1 and Part 2 of this deep-dive series, we already learned what Kustomize is and how it can help us in our CI and CD journey. Today in Part 3 we are going to look at how Kustomize can fit into our application config management strategy.

Applications usually have the requirement of config parameters that would change based on the environment in which the application is getting deployed. For example, an application that requires to perform a read query on the database will have a different database endpoint for dev, st1, and prod environment.

If not done already, it would be a good idea to separate these config values from the application code in a way that is compliant with The Twelve-Factor App design principle. There are various ways in which you can handle the above requirement. Let’s take a look into how Kustomize helps us to achieve the same by using its ConfigMapGenerator functionality.

Say, you have a Spring-Boot Java application, what you can do is refer to the database URL as a parameter something like shown below in your application.properties file:

spring.datasource.url = ${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/"nameofDB"

Now you can provide the above 2 variables, OPENSHIFT_MYSQL_DB_HOST and OPENSHIFT_MYSQL_DB_PORT as environment variables using configmap to your application at the startup time. To achieve this, let’s take a look back at the directory structure for CI(app1-github-repo) and CD (a-cd-github-repo with multiple environments folders) using Kustomize we had after part 2:

Higher env structure using kustomize

To provide the environment variables which can later be provided as configmap to the application, let’s add one app.env file in every environment directory. The content of the app.env file for st1 env will be something like:

OPENSHIFT_MYSQL_DB_HOST=st1.something.something

OPENSHIFT_MYSQL_DB_PORT=3306

and the content for the st2 environment will be something like:

OPENSHIFT_MYSQL_DB_HOST=st2.something.something

OPENSHIFT_MYSQL_DB_PORT=3306

So the above directory structure gets expanded to something like below:

Higher env structure together with cm using kustomize

Now to provide those environment variables as a configmap using kustomize we can include the following lines in our kustomization.yaml file:

configMapGenerator:

- name: app-configmap

behavior: merge

envs:

- app.env

Please note that the behavior: merge will only be used for CD environment deployments and not for CI environment kustomization.yaml.

This will create the configmap using the app.env file and the only thing left to do now is to modify the deployment.yaml to signal it to start using the environment variables from the configmap that just got created. So we will add the following lines of code in the deployment.yaml:

envFrom:

- configMapRef:

name: app-configmap

Now if you would run your deployments just like you were doing at the end of Part 2, you will have a configmap created and your application will have environment variables available to it based on the environment it got deployed to. So run the command as you were doing at the end of part 2 and you are done:

kustomize build | polaris audit — set-exit-code-below-score 90 — audit-path -kustomize build | kubectl -n st1 apply -f -

The best part is when creating the configmap, Kustomize adds a hash at the of the configmap name, and hence if at the next deployment cycle, if only the value of environment variables in the configmap is changing, Kustomize will create the configmap with a different hash and attach it to the deployment. This will ensure that the pods created from the deployment get recreated based on your defined strategy to use the new environment variable values.

Some of the readers may be wondering by now that usually, you will need a username and password to connect to the database as well, so should we follow the same approach for providing those values as environment variables via an app.env file?

The answer is since username and password are sensitive information it won’t be a good idea to make them visible in the app.env file. Also, sensitive information should be managed by Kubernetes secrets or ideally by a central secret management system like Vault. Don’t get me wrong, Kustomize does provide a way to manage your secrets via secretGenerator, but in my opinion, managing secrets via a sidecar that can talk to your central secret management system is a much cleaner solution. We will deep dive into how you can make your application get secrets via a sidecar in another series.

In the next article, we will look into GitOps using tools like ArgoCD and Flux and see with our current approach how effortlessly we can adopt GitOps principles.

STAY TUNED!