Creating a ConfigMap using ‘kubectl create configmap’ is a straightforward operation. However, there is not a corresponding ‘kubectl apply’ that can easily update that ConfigMap.
As an example, here are the commands for the creation of a simple ConfigMap using a file named “ConfigMap-test1.yaml“.
$ cat ConfigMap-test1.yaml test1: foo: bar # create and then show ConfigMap $ kubectl create configmap test1 --from-file=ConfigMap-test1.yaml $ kubectl describe ConfigMap test1
But there is not a corresponding ‘apply’ or ‘update’ that can be run if you tweaked the file and wanted to update the ConfigMap. However, this can be achieved by using “–dry-run” and “kubectl replace”.
# file with change made $ cat ConfigMap-test1.yaml test1: foo: nowchanged # apply update to ConfigMap using dry-run and replace kubectl create configmap test1 --from-file=ConfigMap-test1.yaml -o yaml --dry-run | kubectl replace -f - # validate that change was made $ kubectl describe ConfigMap test1
And if you wanted to just update a portion of the content without using a file, then you could use jq/sed as described in one of my previous articles. Below is an example for replacing the DNS resolv.conf value embedded in ‘data.kubelet’ of the ConfigMap.
kubectl get cm -n kube-system kubelet-config -o=json | \ jq 'del(.metadata.resourceVersion,.metadata.uid,.metadata.selfLink,.metadata.creationTimestamp,.metadata.annotations,.metadata.generation,.metadata.ownerReferences,.status)' | \ sed -E 's#resolvConf: [^\n ]*\\n#resolvConf: /etc/kubeadm-resolv.conf\\n#' | \ kubectl replace -f -
Here is an example Ansible playbook “playbook-k8s-configmap-update.yaml” that registers a variable which controls creation versus update.
--- - hosts: localhost connection: local tasks: # make sure kubectl context already set - command: kubectl get nodes - name: does configmap exist? command: kubectl describe configmap test1 failed_when: not configmap_res.rc in [0,1] register: configmap_res - name: show configmap results, 0=found,1=not found debug: msg: "{{configmap_res.rc}}" - name: kubectl to create new configmap command: kubectl create configmap test1 --from-file=ConfigMap-test1.yaml when: configmap_res.rc != 0 - name: kubectl to update existing configmap shell: 'kubectl create configmap test1 --from-file=ConfigMap-test1.yaml -o yaml --dry-run | kubectl replace -f -' when: configmap_res.rc == 0 - name: show final configmap command: kubectl describe ConfigMap test1 register: final_output - debug: msg: "{{final_output.stdout_lines}}"
Which would be run with the following command:
ansible-playbook playbook-k8s-configmap-update.yml --connection=local
REFERENCES
stackoverflow, updating already existing ConfigMap using kubectl
stackoverflow, updating existing ConfigMap using kubectl dry-run and apply
atomist.com, updating a K8S ConfigMap or Secret
NOTES
replacing TLS secret using apply
kubectl -n kube-system create secret tls ingress-tls-cert --key $domain.key --cert $domain.crt --dry-run=client -o=yaml | kubectl apply -f -