'How to trigger change in sha256sum of rendered configmap in helm?

I have a setting in my configmap.yaml

---
apiVersion: V2.23
kind: ConfigMap
metadata:
   name: my-configmap
data: 
   image.tag: {{ .Values.image.tag }}

Then in deployment.yaml I have this line:

  annotations:
    checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}

Then in values.yaml I have this line:

image:
  repository: myrepo
  tag: latest
  pullPolicy: IfNotPresent

If I have the following helm command in my Jenkinsfile

        sh """
          helm upgrade --install --force \
          --namespace=default \
          --values=values.yaml \
          --set image.tag=${output_of_git-describe} \
          --set image.pullPolicy=Always \
          myimage kubernetes/myimage
       """

Question

  1. Will the sha256 for configmap.yaml actually get changed based on the helm command I have in my Jenkinsfile?
  2. Is there a helm command I can run to display the sha256 of configmap.yaml?


Solution 1:[1]

  1. Will the sha256 for configmap.yaml actually get changed based on the helm command I have in my Jenkinsfile?

Yes. The include function will render the configmap.yaml template using the current helm values.

  1. Is there a helm command I can run to display the sha256 of configmap.yaml?

Yes. This is what the helm template command does. For example:

$ helm template --set image.tag=foo mychart | grep checksum
        checksum/config: bd280ed35fb0f343eb93837290a67e26423f0aa247f48b522f574a711fa35e11
$ helm template --set image.tag=bar mychart | grep checksum
        checksum/config: 152533d214421480233406153edcde673f4ce072fba940cb7cfbab96954f7201

Solution 2:[2]

As you've written it (from here), Helm will calculate the SHA-256 hash of the unrendered template file, which won't change as you update the value.

If your ConfigMap will only ever contain this single value, you could use a hash of that value instead:

checksum/config: {{ sha256sum .Values.image.tag }}

You could break out the contents of the ConfigMap into a separate renderable template:

{{/* _config_map.tpl */}}
{{- define "config-map-contents" -}}
image.tag: {{ .Values.image.tag }}
{{- end -}}
{{/* my-configmap.yaml */}}
apiVersion: v1
kind: ConfigMap
metadata:
   name: my-configmap
data: {{ include "config-map-contents" | nindent 2 }}
{{/* in the pod spec */}}
checksum/config: {{ include "config-map-contents" | sha256sum }}

At the end of the day, you need something in the pod spec to change to cause Kubernetes to redeploy it. In Helm you can more directly put the value in an environment variable without going via a ConfigMap, which will have the right effect:

env:
  - name: IMAGE_TAG
    value: {{ .Values.image.tag }}

Or if it actually is the image tag, simply changing the target image of a container in a pod will cause it to redeploy:

image: {{ printf "%s/%s:%s" .Values.image.repository (.Values.image.image | default "myimage") .Values.image.tag | quote}}

Solution 3:[3]

Here is my example first I have created the content to values.yaml

#values.yaml
configMap:
  content: |
    #!/bin/bash
    echo "Hello World"'

Here you can see I am referring to the example script from values.yaml

#config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
   name: my-configmap
data: 
  key: {{ .Values.secret.content | b64enc }}

Then the actual deployment

***
  template:
    metadata:
      annotations:
        checksum/apache-config: {{ printf .Values.configMap.content | sha256sum  }}
***

Now you can see in action

$ helm upgrade --install example-helm ./example-helm
Release "example-helm" does not exist. Installing it now.
NAME: example-helm
LAST DEPLOYED: Sun Mar 20 22:46:09 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=example-helm,app.kubernetes.io/instance=example-helm" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace default port-forward $POD_NAME 8080:80

After I did deploy then I did small changes to the script content

configMap:
  content: |
    #!/bin/bash
    echo "Hello World to Stack Overflow"'

Now you can see its getting updated

$ kubectl get pod                                             
NAME                              READY   STATUS              RESTARTS   AGE
example-helm-5bf5457b4-wgsx7    1/1     Running             0          26s
example-helm-668b4d7d78-9bh2g   0/1     ContainerCreating   0          1s

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Eric
Solution 2 austin_ce
Solution 3 Farkhod Sadykov