Chart per service approach

Use a Helm chart per microservice approach if you seek to achieve flexible, simple versioning and low complexity charts to package your application. Be careful, this technique might bring:

  • huge amount of duplication

  • difficulty to keep consistent many templates

  • hardship to introduce global changes

Goal of this section: customize the configuration of the tutorial microservice with another template and deploy it using Helm charts in a different namespace/project.

Inject configurations from a configmap template

When working with a microservice it is likely that you will inject and manage configurations using other Kubernetes resources, like ConfigMap or Secret.

Let’s inject a configuration from a ConfigMap for the tutorial microservice. Navigate to the templates folder and create a configmap.yaml. Open the configmap.yaml you just created and add the following:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.configmap.region | quote }}
  labels:
    {{- include "faq.labels" . | nindent 4 }}
data:
  region: {{.Values.configmap.region | upper | quote }} (1)
1 Change the value for region to uppercase.

Now add the default value for a region in values.yaml:

configmap:
  key: region
  region: cee

And configure the deployment.yaml template to use the new configmap:

          env:
            - name: POSTGRES_SERVER
              value: {{ .Values.postgresql.server | default (printf "%s-postgresql" ( .Release.Name )) | quote }}
            - name: POSTGRES_USERNAME
              value: {{ .Values.postgresql.postgresqlUsername | quote }}
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.postgresql.secretName | default (printf "%s-postgresql" ( .Release.Name )) | quote }}
                  key: {{ .Values.postgresql.secretKey }}
            - name: REGION
              valueFrom:
                configMapKeyRef:
                  name: {{ .Values.configmap.region }}
                  key: {{ .Values.configmap.key }}

Automatically roll out Deployments when a ConfigMap/Secret changes

Configmaps and Secrets are often used as configuration files, but when values change in these files they are not automatically picked up by a running application unless the deployment spec itself changes. This can potentially result in inconsistent deployments where the values have been updated but the application is actually still running with the old configuration wich is not what we want.

A solution to this problem is to use a sha256sum function which can be used to ensure a deployment’s annotation section is updated if another file changes:

Don’t change the deployment.yaml file. This next snippet is just an example.
kind: Deployment
spec:
  template:
    metadata:
      annotations:
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}

We can make this change even more elegant, because helm autogenerated the inclusion of annotations in deployment.yaml when we initialized our Chart:

  template:
    metadata:
      {{- with .Values.podAnnotations }}
      annotations:
        {{- toYaml . | nindent 8 }}
      {{- end }}

The above states the following: only if .Values.podAnnotations is defined, then get the yaml definition from there.

We can thus modify the values.yaml accordingly:

The podAnnotations key might already be present in the values.yaml. Update it if it exists, or create a new entry if it’s missing.
podAnnotations:
  checksum/config: '{{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}'

As the above value contains both YAML and a Go template, we need to parse the yaml (toYaml) and use the template (tpl) in deployment.yaml with:

  template:
    metadata:
      {{- with .Values.podAnnotations }}
      annotations:
      {{ tpl (toYaml .) $ | nindent 8 }}
      {{- end }}

Upgrade the release

Update the existing release with the newly added configurations:

helm upgrade simple ./chart/faq

Run the following commands to verify the CEE output:

export POD_NAME=$(oc get pods -l app.kubernetes.io/instance=simple -o jsonpath={.items[0]..metadata.name})
kubectl exec $POD_NAME -- /bin/curl -s localhost:8080/ask/CEE

The output should be a JSON Array that contains an Object with the region set to a capitalized version of cee from the configmap in values.yaml.

Uninstall a release

Simply run the following command to uninstall your previous releases:

helm uninstall simple
helm uninstall faq-db

Replicate the installation in a different namespace

Let’s create a different namespace:

  • Minikube

  • OpenShift

kubectl create ns qa

#permanently save the namespace for all subsequent kubectl commands
kubectl config set-context --current --namespace=qa
oc create project qa

And define a set of values for this namespace by making a copy of values.yaml. Name the copy values.qa.yaml. Modify the region inside values.qa.yaml:

configmap:
  key: region
  region: benelux

And now install the charts:

  • Minikube

  • OpenShift

helm install faq-db \
--set postgresqlUsername=faq-default,postgresqlPassword=postgres,postgresqlDatabase=faq,persistence.enabled=false,securityContext.enabled=false,containerSecurityContext.enabled=false \
bitnami/postgresql (1)

helm install simple ./chart/faq --values ./chart/faq/values.qa.yaml (2)
helm install faq-db --set postgresqlUsername=faq-default,postgresqlPassword=postgres,postgresqlDatabase=faq,persistence.enabled=false,securityContext.enabled=false,containerSecurityContext.enabled=false,primary.podSecurityContext.enabled=false,primary.containerSecurityContext.enabled=
false --version 12.1.2 bitnami/postgresql (1)

helm install simple ./chart/faq --values ./chart/faq/values.qa.yaml (2)
1 Install the PostgreSQL Helm chart in the new namespace/project.
2 Install the faq Helm chart in the qa namespace using the values dedicated to this namespace.

Clean-Up

Clean-Up the namespace to have it prepared for the following section:

helm uninstall simple
helm uninstall faq-db