<p>(using kubernetes v1.15.7 in minikube and matching client version and minikube 1.9.0)</p>

<p>If I <code>kubectl apply</code> a secret like this:</p>

<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
data:
  MY_KEY: dmFsdWUK
  MY_SECRET: c3VwZXJzZWNyZXQK
kind: Secret
metadata:
  name: my-secret
type: Opaque
</code></pre>

<p>then subsequently <code>kubectl apply</code> a secret removing the MY_SECRET field, like this:</p>

<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
data:
  MY_KEY: dmFsdWUK
kind: Secret
metadata:
  name: my-secret
type: Opaque
</code></pre>

<p>The <code>data</code> field in the result is what I expect when I <code>kubectl get</code> the secret:</p>

<pre class="lang-yaml prettyprint-override"><code>data:
  MY_KEY: dmFsdWUK
</code></pre>

<hr>

<p>However, if I do the same thing using <code>stringData</code> instead <strong>for the first kubectl apply</strong>, it does not remove the missing key on the second one:</p>

<p>First <code>kubectl apply</code>:</p>

<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
stringData:
  MY_KEY: value
  MY_SECRET: supersecret
kind: Secret
metadata:
  name: my-secret
type: Opaque
</code></pre>

<p>Second <code>kubectl apply</code> (stays the same, except replacing <code>MY_KEY</code>'s value with <code>b2hubyEK</code> to show the configuration DID change)</p>

<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
data:
  MY_KEY: b2hubyEK
kind: Secret
metadata:
  name: my-secret
type: Opaque
</code></pre>

<p><code>kubectl get</code> result after applying the second case:</p>

<pre><code>data:
  MY_KEY: b2hubyEK
  MY_SECRET: c3VwZXJzZWNyZXQ=
</code></pre>

<p>The field also does not get removed if the second case uses <code>stringData</code> instead. So it seems that once <code>stringData</code> is used once, it's impossible to remove a field without deleting the secret. Is this a bug? Or should I be doing something differently when using <code>stringData</code>?</p>

<p>kubectl apply need to merge / patch the changes here. How this works is described in <a href="https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/#how-apply-calculates-differences-and-merges-changes" rel="nofollow noreferrer">How apply calculates differences and merges changes</a></p>

<p>I would recommend to use <em>kustomize</em> with <code>kubectl apply -k</code> and use the <strong><a href="https://kubectl.docs.kubernetes.io/pages/reference/kustomize.html#secretgenerator" rel="nofollow noreferrer">secretGenerator</a></strong> to create a unique secret name, for every change. Then you are practicing <em>Immutable Infrastructure</em> and does not get this kind of problems.</p>

<p>A brand new tool for config manangement is <a href="https://googlecontainertools.github.io/kpt/guides/consumer/apply/" rel="nofollow noreferrer">kpt</a>, and <code>kpt live apply</code> may also be an interesting solution for this.</p>
