Kubernetes: adding and removing pod template annotations using kubectl

Although ‘kubectl annotate‘ will set an annotation on a  object directly, it will not set the annotation on the more deeply nested pod template for a Deployment or Daemonset.

If you want to quickly set the annotation on a pod template (.spec.template.metadata.annotations) without modifying the full manifest, you can  use the ‘patch‘ command.  As a quick example:

kubectl patch deployment nginx -p '{"spec": {"template":{"metadata":{"annotations":{"sidecar.istio.io/inject":"false"}}}} }'

As a full example, let’s create an nginx deployment.

# create deployment
$ kubectl create deployment nginx --image=nginx:1.21.3-alpine --replicas=1

# direct annotation only has revision
$ kubectl get deployment nginx -o=jsonpath="{.metadata.annotations}"
{"deployment.kubernetes.io/revision":"1"}

# annotation of pod template is empty
$ kubectl get deployment nginx -o=jsonpath="{.spec.template.metadata.annotations}"

Now let’s use the ‘annotate’ command on the deployment.  Notice the annotation of the deployment itself is modified, but not the pod template annotation.

# will only annotate deployment directly
# not its pod template annotation
$ kubectl annotate deployment nginx "test=true"

# annotation added directly to deployment
$ kubectl get deployment nginx -o=jsonpath="{.metadata.annotations}" | jq
{
"deployment.kubernetes.io/revision": "1",
"test": "true"
}

# but annotation of pod template is still empty
$ kubectl get deployment nginx -o=jsonpath="{.spec.template.metadata.annotations}"

In order to modify the deeper pod template annotation, use ‘patch’.

# this will set deep annotation on pod template
$ kubectl patch deployment nginx -p '{"spec": {"template":{"metadata":{"annotations":{"sidecar.istio.io/inject":"false"}}}} }'

# now pod template successfully shows annotation!
$ kubectl get deployment nginx -o=jsonpath="{.spec.template.metadata.annotations}" | jq
{
"sidecar.istio.io/inject": "false"
}

If you want to remove the pod template annotation, you cannot use patch like before because it uses a merge strategy that can only append.  But if you use the jsonpatch specification, then you can specify a “remove” operation.

# use jsonpath to do a "remove" operation
$ kubectl patch deployment nginx --type=json -p='[{"op":"remove","path":"/spec/template/metadata/annotations/sidecar.istio.io~1inject"}]'
deployment.apps/nginx patched

# the pod template annotation is now empty again
$ kubectl get deployment nginx -o=jsonpath="{.spec.template.metadata.annotations}"

Notice that the forward slash had to be escaped as “~1” per the jsonpatch spec.

To delete the deployment:

kubectl delete deployment/nginx

REFERENCES

github issue, annotate does not do template annotation

stackoverflow, specify remove operation with jsonpath

NOTES

Set revision history limit or else they will build up during rolling restarts

# .spec.revisionHistoryLimit=1
kubectl patch deployment nginx -p '{"spec": {"revisionHistoryLimit":1} }'

rolling restart of deployment

$ kubectl rollout restart deployment/nginx
deployment.apps/nginx restarted