如何在不停机的情况下更改k8s Deployment的matchLabels?

9

Kubernetes的Deployment不允许在spec.selector.matchLabels中进行补丁更改,因此任何想要更改标签的新部署(由Helm或其他方式管理)都不能使用Deployment内的RollingUpdate功能。有什么最好的方法可以在不造成停机时间的情况下实现新的部署滚动升级?

最小示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: foo
  template:
    metadata:
      labels:
        app: foo
    spec:
      containers:
        - name: foo
          image: ubuntu:latest
          command: ["/bin/bash", "-ec", "sleep infinity"]

执行此操作,然后编辑标签(包括matchLabels和metadata.labels),将其更改为foo2。如果您尝试应用此新部署,k8s将会报错(按设计)。Deployment "foo" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app":"foo2"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable

目前唯一想到的方法是使用新的部署名称,以便新部署不会尝试修改旧部署,然后删除旧部署,并交由入口/负载均衡资源处理过渡。之后我们可以重新部署旧名称,然后删除新名称,完成迁移。

有没有一种更少的k8s CLI步骤的方法?也许我可以编辑/删除某些内容,使旧Pod在相同名称下滚动出新Pod的同时保持活动状态?


如果它是由Helm管理的,那么最好再次使用Helm部署并设置您需要的新值。有多少个实例正在运行? - Manuel
Pod的数量是不确定的,但只有一个Helm发布。无论使用Helm(3)部署,具有matchLabels(Jobs、Deployments)的Kinds都无法更新,需要重新创建(删除+创建)。我已经添加了一个最小示例来说明这个问题。 - snugghash
2个回答

2

我刚刚完成了这个,按照你描述的四步流程进行。我认为答案是否定的,没有更好的方法。

我的服务由Helm管理。为此,我实际上创建了四个需要按顺序推出的合并请求:

  1. 添加相同的部署“foo-temp”,只是名称不同。
  2. 删除部署 foo。
  3. 重新创建带有所需标签选择器的 foo 部署。
  4. 删除 foo-temp 部署。

我尝试了简化该流程 (将步骤1和2合并),但它不起作用 - Helm 在创建另一个部署之前会删除一个部署,然后会有停机时间。

好消息是:在我的情况下,我不需要更改任何其他描述符(图表),所以情况并不太糟糕。所有关系(流量路由等)都是通过标签匹配完成的。由于 foo-temp 具有相同的标签,关系自动工作。唯一的问题是我的 HPA 引用的是名称而不是标签。我没有修改它,而是让 foo-temp 没有 HPA,并为其指定了大量副本。在第2步和第3步之间,当其目标不存在时,HPA 不会抱怨。


-2

根据我的经验,在使用helm时,当我使用

helm upgrade release -f values .

我没有停机时间。同时,当使用helm时,我注意到在新部署准备好之前,旧部署不会终止直到X/X。我建议使用它。这样可以尽可能地无痛。

另外,从Kubernetes文档的更新部署部分中指出, 仅当更改了部署的Pod模板(即.spec.template)时,才会触发部署的滚动升级。

因此,您可以使用helm进行标签更改。

希望我能有所帮助。

注意!未经尝试的方法:kubectl具有编辑子命令,使我能够更新ConfigMaps、PersistentVolumeClaims等。也许您可以使用它来更新您的部署。 语法:

kubectl edit [resource] [resource-name]

但在此之前,请选择一个适当的文本编辑器,因为您将处理yaml格式的文件。可以使用以下方式进行选择:

export KUBE_EDITOR=/bin/{nano,vim,yourFavEditor}

1
我的问题更多地涉及同一文档下面的限制:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#label-selector-updates我知道这是一个罕见的升级,但是有一个标准的流程会很好,这样我就不会感觉像是在穿越 k8s 的丛林来完成任务了。 - snugghash
1
我认为如果它能正常工作并给你所需的,你就不需要有那种感觉。而且这种变化是经常发生的。只是我不知道有没有简单的一行解决方案。就是这样。这种方法几乎与应用更改后的yaml文件而不删除相同,这会强制kubernetes重新配置部署。 - Catastrophe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接