<p>I am using Azure Kubernetes Services with K8S version 1.20.9 and have following K8S deployment</p>
<p>Version 1:</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: test
  name: busybox-deployment
  labels:
    app: busybox
spec:
  replicas: 1
  strategy: 
    type: RollingUpdate
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      containers:
      - name: busybox
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ['sh', '-c', 'echo Container 1 is Running ; sleep 3600']
        env:
          - name: KEY_1
            value: VALUE_1
</code></pre>
<p>I deploy with <code>kubectl apply</code> it and check the value of the <code>KEY_1</code> environment variable - it is correctly set to <code>VALUE_1</code>.</p>
<p>Then I deploy 2 more versions (again via <code>kubectl apply</code>) where I change the key-value pair in the env section like this effectively deleting the old environment variable and creating a new one:</p>
<p>Version 2:</p>
<pre><code>        env:
          - name: KEY_2
            value: VALUE_2
</code></pre>
<p>Version 3:</p>
<pre><code>        env:
          - name: KEY_3
            value: VALUE_3
</code></pre>
<p>After each deploy I check the environment variables and they are fine - version 2 contains the <code>KEY_2:VALUE_2</code> pair and version 3 contains the <code>KEY_3:VALUE_3</code> pair.</p>
<p>Now I rollback to version 2 by invoking</p>
<pre><code>kubectl rollout undo deployment ...
</code></pre>
<p>This is also correctly working and now we have the <code>KEY_2:VALUE_2</code> pair as environment variables.</p>
<p>However, if I deploy version 3 again the container and the deployment descriptor have both the <code>KEY_2:VALUE_2</code> and the <code>KEY_3:VALUE</code> as environment variables. This matches none of the deployed descriptors because they always contain only a single environment variable.
Subsequent deployments result in the same behavior until I manually edit and delete the unnecessary property.</p>
<p>I read some explanations like <a href="https://blog.atomist.com/kubernetes-apply-replace-patch/" rel="nofollow noreferrer">this nice article</a> where it is explained that <code>kubectl apply</code> would remove old properties, while patch would not.</p>
<p>However this does not happen when &quot;undo&quot; is performed. Any idea why?</p>
<p>Thank you.</p>

<p>This is a known problem with <code>rollout undo</code>, reported here <a href="https://github.com/kubernetes/kubernetes/issues/94698" rel="nofollow noreferrer">#94698</a>, here <a href="https://github.com/kubernetes/kubernetes/issues/25236" rel="nofollow noreferrer">#25236</a>, and here <a href="https://github.com/kubernetes/kubernetes/issues/22512" rel="nofollow noreferrer">#22512</a>.</p>
<p>In layman terms - <code>kubectl</code> incorrectly calculates differences and merges changes, becacuse <code>undo</code> does not properly load previous configuration.</p>
<p>More about how K8s calculates differences can be found in the <a href="https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/#how-apply-calculates-differences-and-merges-changes" rel="nofollow noreferrer">docs</a>.</p>
<p>Workaround is to update manually last-applied-configuration before re-applying another deployment from config file</p>
<pre class="lang-text prettyprint-override"><code>kubectl apply set-last-applied -f Deployment_v2.yaml -o yaml
</code></pre>
