Why a Kubernetes Secret created with stringData is "changed" on every Ansible run

The API server rewrites stringData into data, so kubernetes.core.k8s sees a difference each time. Use data with b64encode. Also: omit does not work inside a nested definition, so merge optional keys with combine.

My role creates a Secret from a vaulted value. First run: changed, as expected. Second run: changed again, and a third. Nothing was actually different.

The module compares what you send with what the server has. If you send stringData, the API server converts it into base64 data and drops the original field, so the stored object never matches your definition.

Use data

definition:
  apiVersion: v1
  kind: Secret
  metadata:
    name: sops-age
    namespace: flux-system
  data:
    age.agekey: "{{ key | b64encode }}"

I checked all three states: create reports changed, an immediate rerun doesn’t, and a delete reports changed again.

Optional keys

Related surprise from the same role: omit doesn’t work inside a nested definition. I wanted a secretRef only when credentials are given, and omit there doesn’t drop the key the way it does for a module argument. Build the optional part separately and merge it:

spec: "{{ base_spec | combine(extra_spec) }}"

where extra_spec is {} when there is nothing to add.