apiVersion: apps/v1 kind: ReplicaSet metadata: name: rs-ml-demo spec: replicas: 3 selector: matchLabels: app: rs-ml-demo 我说的是这里 template: metadata: labels: app: rs-ml-demo spec: containers: - name: rs-ml-demo-container image: wangyanglinux/myapp:v1.0 env: - name: GET_HOSTS_FROM value: dns ports: - containerPort: 80
selector) 和 自身标签 (metadata.labels) 混在一起,容易让人产生“暗号就是自身标签”的错觉。matchLabels 只是用来找 Pod 的,RS 自己到底有没有标签,完全取决于最外层 metadata.labels 有没有写。在 RC 时代,selector 写得很随意:
selector: app: rc-demo 如果你不显式给 RC 贴标签,K8s 会默认把 selector 里的内容当作 RC 自己的标签。这就导致了你之前觉得“RC 的 selector 就是它自己的标签”。 到了 RS 时代,为了支持更高级的匹配(比如“包含”、“不包含”),K8s 强制要求必须套一层 matchLabels: selector: matchLabels: app: rs-ml-demo 彻底切断了“把 selector 当成自身标签”的默认行为,selector.matchLabels 纯粹就是 RS 的“寻人暗号”(匹配规则)。 因为你没有在 YAML 最外层的 metadata.labels 下写任何标签,所以 RS 自身真的没有任何标签(这就是为什么你敲 kubectl get rs --show-labels 看到的是 <none>)。
正是 Kubernetes 从 RC 进化到 RS 时,在底层逻辑上的一次“解耦”:
就像这样:
"deployment.yml" 19L, 312B 13,4 All apiVersion: apps/v1 kind: Deployment metadata: labels: app: myapp-deploy name: myapp-deploy spec: replicas: 1 selector: matchLabels: app: myapp-deploy template: metadata: labels: app: myapp-deploy spec: containers: - image: wangyanglinux/myapp:v1.0 name: myapp 这种就有标签
在这个 YAML 里,app: myapp-deploy 这个标签出现了整整三次。虽然它们看起来长得一模一样,但在 Kubernetes 内部,它们分别属于三个不同的对象,承担着完全不同的职责
Deployment 自身的标签(最外层)
metadata:
labels:
app: myapp-deploy
Deployment 这个控制器本身贴的标签。kubectl get deployments -l app=myapp-deploy 来快速筛选出它。Deployment 的“寻人暗号”(selector)
spec:
selector:
matchLabels:
app: myapp-deploy
app: myapp-deploy 这个标签,谁就归我管!”Pod 的“出厂铭牌”(template)
template:
metadata:
labels:
app: myapp-deploy
Pod 的“出厂铭牌”(template)这个label一般都要和上面的寻人label一致吧,不一致的话是不是就是不服管?
在 Kubernetes 中,如果 template 里的标签和 selector 里的标签不一致,Pod 确实会“不服管”,但 K8s 为了防止你写出这种“叛逆”的配置,直接在源头就把它给掐死了。当你执行 kubectl apply 时,K8s 会直接报错,根本不会创建这个 Deployment/RS。
“出厂铭牌”必须和“寻人暗号”完全一致!