为什么 "kubectl apply" 在回滚后合并部署描述符

Why does "kubectl apply" merge deployment descriptors after rollback

我正在将 Azure Kubernetes 服务与 K8S 版本 1.20.9 一起使用,并进行了以下 K8S 部署

版本 1:

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

我使用 kubectl apply 进行部署并检查 KEY_1 环境变量的值 - 它已正确设置为 VALUE_1.

然后我又部署了 2 个版本(再次通过 kubectl apply),我在其中更改了 env 部分中的键值对,这样有效地删除了旧的环境变量并创建了一个新的:

版本 2:

        env:
          - name: KEY_2
            value: VALUE_2

版本 3:

        env:
          - name: KEY_3
            value: VALUE_3

每次部署后,我都会检查环境变量,它们都很好 - 版本 2 包含 KEY_2:VALUE_2 对,版本 3 包含 KEY_3:VALUE_3 对。

现在我通过调用

回滚到版本 2
kubectl rollout undo deployment ...

这也能正常工作,现在我们有 KEY_2:VALUE_2 对作为环境变量。

但是,如果我再次部署版本 3,容器和部署描述符会将 KEY_2:VALUE_2KEY_3:VALUE 作为环境变量。这匹配 none 的已部署描述符,因为它们始终只包含一个环境变量。 后续部署导致相同的行为,直到我手动编辑和删除不必要的 属性.

我读了一些解释,比如 this nice article,其中解释说 kubectl apply 会删除旧属性,而补丁不会。

然而,执行“撤消”时不会发生这种情况。知道为什么吗?

谢谢。

这是 rollout undo 的已知问题,已在此处报告 #94698, here #25236, and here #22512

通俗地说 - kubectl 错误地计算差异并合并更改,因为 undo 没有正确加载以前的配置。

有关 K8s 如何计算差异的更多信息,请参阅 docs

解决方法是在从配置文件重新应用另一个部署之前手动更新上次应用的配置

kubectl apply set-last-applied -f Deployment_v2.yaml -o yaml