需要帮助理解 kubernetes 中的标签覆盖行为

需要帮助理解 kubernetes 中的标签覆盖行为

我正在通过kubernetes 教程. 在完成练习的同时模块 4,我在覆盖标签时观察到 Kubernetes 的奇怪行为。我需要一些解释,因为我看到的内容与教程、文档或我的期望不符。

作为参考,我的运行环境如下:

dfvsmdev@gotham:~/workspace/kube$ minikube version
minikube version: v1.10.0
commit: f318680e7e5bf539f7fadeaaf198f4e468393fb9
dfvsmdev@gotham:~/workspace/kube$ kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.2", GitCommit:"52c56ce7a8272c798dbc29846288d7cd9fbae032", GitTreeState:"clean", BuildDate:"2020-04-16T11:56:40Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.1", GitCommit:"7879fc12a63337efff607952a323df90cdc7a335", GitTreeState:"clean", BuildDate:"2020-04-08T17:30:47Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
dfvsmdev@gotham:~/workspace/kube$ uname -a
Linux gotham 4.15.0-72-generic #81~16.04.1-Ubuntu SMP Tue Nov 26 16:34:21 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
dfvsmdev@gotham:~/workspace/kube$

另外,为了方便起见,我写了一个小脚本,名为get-pod-labels

#!/bin/sh
REGEX=[-A-Za-z0-9._/]+
kubectl describe pods | egrep "(^Name: .+$|^.+ ${REGEX}=${REGEX}$)"

当我运行该脚本时,它会产生以下输出:

dfvsmdev@gotham:~/workspace/kube$ ./get-pod-labels
Name:         hello-node-7bf657c596-xr8dk
Labels:       app=hello-node
              pod-template-hash=7bf657c596
Name:         kubernetes-bootcamp-86656bc875-nz9f6
Labels:       app=kubernetes-bootcamp
              kb=true
              pod-template-hash=86656bc875
Name:         kubernetes-bootcamp-86656bc875-wlqnw
Labels:       app=kubernetes-bootcamp
              kb=true
              pod-template-hash=86656bc875

现在我正处于教程的一部分,他们希望我们执行命令kubectl label pod POD_NAME app=v1。教程中此步骤的重点是修改现有标签。正如所写,命令给出错误。error: 'app' already has a value (kubernetes-bootcamp), and --overwrite is false所以我添加了--overwrite标志并再次尝试。

dfvsmdev@gotham:~/workspace/kube$ kubectl label pods --overwrite kubernetes-bootcamp-86656bc875-nz9f6 app=v1
pod/kubernetes-bootcamp-86656bc875-nz9f6 labeled

但当我检查 pod 标签来验证修改时,我发现了一些奇怪的事情:

dfvsmdev@gotham:~/workspace/kube$ ./get-pod-labels
Name:         hello-node-7bf657c596-xr8dk
Labels:       app=hello-node
              pod-template-hash=7bf657c596
Name:         kubernetes-bootcamp-86656bc875-48frs
Labels:       app=kubernetes-bootcamp
              pod-template-hash=86656bc875
Name:         kubernetes-bootcamp-86656bc875-nz9f6
Labels:       app=v1
              kb=true
              pod-template-hash=86656bc875
Name:         kubernetes-bootcamp-86656bc875-wlqnw
Labels:       app=kubernetes-bootcamp
              kb=true
              pod-template-hash=86656bc875
dfvsmdev@gotham:~/workspace/kube$

app=v1正如预期的那样,kubernetes 修改了给定 pod 名称的标签。但它还创建了一个新的 pod 实例,这是我没有想到的。教程中提到的新 pod 也不是。新的 pod 实例似乎是 pod 的全新安装,因为它没有kb=true我添加到其他 kubernetes-bootcamp pod 的自定义标签()。

所以让我们把教程放在一边,因为坦率地说它有很多错别字。让我们只关注修改标签的预期行为。kubectl 标签的手册页像这样解释覆盖标志:

--overwrite=false
    If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.

该文档未提及创建 pod 的新实例。这背后的原理是什么?创建未修改的 pod 是否是 Kubernetes 的一个特性?还是一个 bug?我对这种行为感到很惊讶。如果我需要修改数百个 pod 的标签怎么办?Kubernetes 会创建数百个新 pod 吗?

请为我解释一下这种行为。

附录

针对下面 KoopaKiller 的回答,这里做一个澄清。以下跟踪日志遵循了他的步骤。请注意,一开始有两个“kubernetes-bootcamp”pod。

dfvsmdev@gotham:~/workspace/kube$ kubectl get pods --show-labels
NAME                                   READY   STATUS    RESTARTS   AGE     LABELS
hello-node-7bf657c596-xr8dk            1/1     Running   1          3d18h   app=hello-node,pod-template-hash=7bf657c596
kubernetes-bootcamp-86656bc875-nz9f6   1/1     Running   0          2d22h   app=kubernetes-bootcamp,kb=true,pod-template-hash=86656bc875
kubernetes-bootcamp-86656bc875-wlqnw   1/1     Running   0          2d22h   app=kubernetes-bootcamp,kb=true,pod-template-hash=86656bc875

dfvsmdev@gotham:~/workspace/kube$ kubectl label pods --overwrite kubernetes-bootcamp-86656bc875-nz9f6 app=v1
pod/kubernetes-bootcamp-86656bc875-nz9f6 labeled

dfvsmdev@gotham:~/workspace/kube$ kubectl get pods --show-labels
NAME                                   READY   STATUS    RESTARTS   AGE     LABELS
hello-node-7bf657c596-xr8dk            1/1     Running   1          3d18h   app=hello-node,pod-template-hash=7bf657c596
kubernetes-bootcamp-86656bc875-jh9ml   1/1     Running   0          2m9s    app=kubernetes-bootcamp,pod-template-hash=86656bc875
kubernetes-bootcamp-86656bc875-nz9f6   1/1     Running   0          2d22h   app=v1,kb=true,pod-template-hash=86656bc875
kubernetes-bootcamp-86656bc875-wlqnw   1/1     Running   0          2d22h   app=kubernetes-bootcamp,kb=true,pod-template-hash=86656bc875

如您所见,执行 label/overwrite 命令后确实创建了一个新的第三个“kubernetes-bootcamp”pod。

鉴于 KoopaKiller 的反例中没有出现相同的结果,我认为我看到的可能是 minikube 实现中的一个错误。这可能是最好的解释。

答案1

我已经在实验室中进行了测试并得出结论:应用/修改标签后,pod 不会重新创建。

任何修改之后都不要kind: Pod重新创建 pod。

您可以让测试执行一个简单的 pod,应用标签并使用标志更改标签,然后使用 comamnf--overwrite检查 pod 。AGEkubectl get pods

例子:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    command:
      - sleep
      - "3600"
EOF
  1. 贴上豆荚标签并检查 AGE:
$ kubectl label pod nginx app=nginx
pod/nginx labeled

$ kg pods --show-labels
NAME    READY   STATUS    RESTARTS   AGE    LABELS
nginx   1/1     Running   0          2m4s   app=nginx

可以看到,pod pode的年龄是2m4s。

  1. 修改标签并检查年龄:
$ kubectl label pod nginx app=my-nginx --overwrite
pod/nginx labeled

$ kg pods --show-labels
NAME    READY   STATUS    RESTARTS   AGE     LABELS
nginx   1/1     Running   0          3m28s   app=my-nginx

其他考虑因素:

  • 在 Kubernetes 环境中,很少会创建一个可用于生产的 Pod,因为任务完成后,Pod 将被终止,正如本文中提到的关联

    Pod 本身无法自我修复。如果将 Pod 调度到发生故障的节点,或者调度操作本身失败,Pod 将被删除;同样,由于资源不足或节点维护不足,Pod 也无法在驱逐后存活下来。

例如,您需要使用能够确保您的 pod 具有弹性和高可用性的部署。

答案2

复制控制器或类似的东西可能会使用该标签来选择其控制下的 Pod。当您更改标签的值时,复制控制器会突然发现 Pod 少了一个,因为它不再与选择器的标签值匹配,因此它会创建另一个 Pod。这对您来说有意义吗?

相关内容