Skip to content

Removing a Field from a Template#

Deleting a line from a template does not remove that field from the resources already deployed. The live resource keeps the value it was last given. To remove a field, set it to null and keep the line in place.

Note

Two kinds of field are removed by deleting the line. The data keys of a ConfigMap or Secret, because the operator nulls any key that disappears from the template. And any field inside a list item, such as env or resources under containers, because the operator replaces the whole list. A null works in both places too.

Set the field to null#

apiVersion: templates.stakater.com/v1alpha1
kind: Template
metadata:
  name: app
resources:
  manifests:
    - apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: app
      spec:
        selector:
          matchLabels:
            app: app
        template:
          metadata:
            labels:
              app: app
          spec:
            securityContext:
              runAsNonRoot: true
              runAsUser: null      # was 65534
              seccompProfile:
                type: RuntimeDefault
            containers:
              - name: app
                image: registry.access.redhat.com/ubi9/ubi-minimal:latest

On the next sync the field is gone from the live resource:

kubectl get deployment app -o jsonpath='{.spec.template.spec.securityContext}'
{"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}

Removing a whole block#

A null on a parent key removes everything beneath it. This clears runAsNonRoot, runAsUser and seccompProfile in one edit:

spec:
  template:
    spec:
      securityContext: null

Note

Some fields are given a default once cleared, so the key may reappear as an empty value. A pod securityContext removed this way reads back as {}. The settings it held are gone.

Lists#

The operator replaces a whole list on every apply, so an entry is removed from a list by deleting it from the template:

env:
  - name: KEEP_ME
    value: "a"
  # DROP_ME deleted, no null needed

To remove a whole list, set the list field itself to null. Deleting the key only works for a list inside another list item, such as env under containers. For a list directly under a map, such as tolerations or volumes, a deleted key leaves the old list on the live resource.

spec:
  template:
    spec:
      tolerations: null

Apply the template with server-side apply#

A null only works if it reaches the cluster. Client-side kubectl apply cannot add a null to the stored template: it strips the null when it creates the template and when it updates one. The stored template then looks exactly like one with the line deleted, the field is never removed, and no error is reported. A null already stored by one of the other commands survives later client-side applies.

Command Null reaches the cluster
kubectl apply --server-side Yes
kubectl create Yes
kubectl replace Yes
kubectl apply No

Confirm what the cluster stored:

kubectl get template app -o yaml | grep -A3 securityContext
            securityContext:
              runAsNonRoot: true
              runAsUser: null

If the runAsUser line is absent, it was stripped on the way in. Apply again with kubectl apply --server-side or kubectl replace.

Argo CD uses client-side apply by default. For an Application that manages templates relying on a null, enable server-side apply:

spec:
  syncPolicy:
    syncOptions:
      - ServerSideApply=true

The instance needs sync enabled#

Removing a field takes effect on the next apply, so set sync: true on the TemplateInstance or ClusterTemplateInstance. With sync left off, the template is rendered once and never applied again, so a null added later never reaches the deployed resources. See Sync.

Note

A parameter can supply a null, but only in the ${{NAME}} form, which parses its value as YAML. With runAsUser: ${{UID}}, an empty value, null, ~, or a parameter left out of the instance with no default all remove the field, and the instance still reports Deployed. The plain ${NAME} form always renders a string, so it cannot supply a null, and on a numeric field like runAsUser the instance reports Failed. See Strings and expressions.