问题描述
Kubernetes 种类 Deployment
不允许在 spec.selector.matchLabels
中更改补丁,因此任何想要更改标签的新部署(由 Helm 或其他方式管理)都无法在部署中使用 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 upgrade release -f values .
我没有停机时间。同样在使用 helm 时,我注意到在 X/X 准备好新部署之前,它不会终止旧部署。我可以建议使用它。这样就可以尽可能地无痛。
同样来自 Kubernetes 文档的 Updating Deployment 部分据说, 当且仅当 Deployment 的 Pod 模板(即 .spec.template)发生更改时,才会触发 Deployment 的推出。
因此,您可以使用 helm 更改标签。
希望对我有所帮助。
当心!未尝试的方法:kubectl 有一个编辑子命令,它使我能够更新 ConfigMaps、PersistentVolumeClaims 等。也许您可以使用它来更新您的部署。 语法:
kubectl edit [resource] [resource-name]
但在此之前请选择合适的文本编辑器,因为您将处理 yaml 格式的文件。通过使用这样做,
export KUBE_EDITOR=/bin/{nano,vim,yourFavEditor}