Label 与 Selector 资源管理
标签(label)是 Kubernetes 把对象关联起来的基础:Deployment 用选择器管理 Pod,Service 通过选择器找到后端,Node 用标签参与调度决策。本章讲清 Label/Annotation 的区别、选择器语法,以及标签如何驱动高级调度。
本篇目标:能区分 Label 与 Annotation,掌握等值与集合两种选择器语法,理解 nodeSelector、亲和性与污点容忍的调度分工。
1. Label 与 Annotation 的概念区别
| Labels | Annotations | |
|---|---|---|
| 用途 | 标识和选择对象(选择器匹配) | 存储元数据(不能被选择器匹配) |
| 典型值 | app.kubernetes.io/name: web | git-commit: a1b2c3d、updated-by: platform-team |
| 选择器可用 | ✅ | ❌ |
| 大小限制 | 名称 63 字符,值 63 字符 | 无硬限制(但不宜过大) |
把运维信息(构建号、部署时间、联系人)放 annotation,把分组和路由信息(应用名、组件、环境)放 label。
metadata:
labels:
app.kubernetes.io/name: web
app.kubernetes.io/part-of: learning
app.kubernetes.io/component: api
annotations:
git-commit: a1b2c3d
updated-by: platform-team
推荐使用 app.kubernetes.io/* 这组通用标签。选择器一旦与既有 Pod 不一致,Service 可能没有后端,Deployment 也可能无法正确识别它管理的副本。
kubectl label pod <pod> -n learning app.kubernetes.io/name=web
kubectl annotate pod <pod> -n learning git-commit=abc123
kubectl get pods -n learning -l app.kubernetes.io/name=web
2. Label Selector 语法
2.1 等值选择器(Equality)
# 单个相等
kubectl get pods -l app.kubernetes.io/name=web
# 多个条件(AND)
kubectl get pods -l app.kubernetes.io/name=web,app.kubernetes.io/part-of=learning
# 不等于
kubectl get pods -l 'app.kubernetes.io/name!=web'
# 存在性(只要该 key 存在)
kubectl get pods -l app.kubernetes.io/name
2.2 集合选择器(Set,matchExpressions)
在 YAML 的 selector 里,matchLabels 是等值简写,matchExpressions 支持更丰富的集合运算:
selector:
matchLabels:
app.kubernetes.io/name: web
matchExpressions:
- key: app.kubernetes.io/environment
operator: In # 值属于给定集合
values: ["prod", "staging"]
- key: tier
operator: NotIn # 值不属于给定集合
values: ["cache"]
- key: owner
operator: Exists # 该 key 存在
- key: owner
operator: DoesNotExist # 该 key 不存在
matchLabels 与 matchExpressions 同时出现时取 AND。
2.3 选择器失配的后果
选择器只在创建时决定绑定关系,之后不能随意改动:
- Service selector 不匹配任何 Pod → EndpointSlice 为空,服务不可达;
- Deployment selector 不匹配 Pod 模板 → 控制器无法识别副本,
kubectl get pods看不到期望副本数。
kubectl get endpointslice -n learning # 检查 Service 后端
kubectl describe service api -n learning
3. 高级调度:从 nodeSelector 到亲和性与污点
标签是调度的输入。三套机制解决不同问题:
| 机制 | 解决的问题 | 方向 |
|---|---|---|
nodeSelector | 简单地只允许调度到带某标签的节点 | Pod 选择节点 |
| node affinity | "必须"或"尽量"靠近某类节点,表达式更丰富 | Pod 选择节点 |
| pod affinity / anti-affinity | Pod 之间"靠近"或"远离" | Pod 之间相互影响 |
| taint / toleration | 节点主动排斥一般 Pod,只有被容忍的工作负载可进入 | 节点排斥 Pod |
| topology spread constraints | 在节点、可用区等拓扑域均匀分布副本 | Pod 之间按拓扑均匀分布 |
3.1 nodeSelector(最简单)
spec:
nodeSelector:
disk-type: ssd # 只调度到带此标签的节点
kubectl label node <node-name> disk-type=ssd
3.2 Node Affinity(更精细)
spec:
affinity:
nodeAffinity:
# 硬约束:必须在 GPU 节点上,且是 A100 型号
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: accelerator
operator: In
values:
- nvidia-a100
# 软偏好:优先选 ap-guangzhou-3 可用区
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- ap-guangzhou-3
requiredDuringScheduling:硬约束,不满足就不调度(Pod 一直 Pending);preferredDuringScheduling:软偏好,不满足退而求其次;IgnoredDuringExecution:已在跑的 Pod 不受后续节点标签变更影响。
3.3 Taint 与 Toleration
节点上的污点阻止不合规的 Pod 调度上来,Pod 上的容忍允许它"忍受"特定污点:
kubectl taint node gpu-node-01 accelerator=nvidia-a100:NoSchedule
kubectl describe node gpu-node-01 | grep Taints
三种 taint effect:
| effect | 行为 |
|---|---|
NoSchedule | 新 Pod 不会被调度到该节点;已有 Pod 不受影响 |
PreferNoSchedule | 尽量不调度,但不强制——是软约束 |
NoExecute | 新 Pod 不会调度,已在运行的 Pod 也会被驱逐(除非有对应 toleration 且 tolerationSeconds 未到期) |
spec:
tolerations:
- key: accelerator
operator: Equal
value: nvidia-a100
effect: NoSchedule
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
3.4 Pod Affinity / Anti-Affinity
spec:
affinity:
podAntiAffinity:
# 硬约束:同一 hostname 上不能有两个 api Pod(分散副本)
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: api
topologyKey: kubernetes.io/hostname
requiredDuringScheduling 是硬约束,副本数超过可用节点数时多余的 Pod 会 Pending;改为 preferredDuringScheduling 则是软偏好。更精确的均匀分布用 topologySpreadConstraints(见第 21 章)。
4. 练习
练习 A
- 给一个 Pod 添加 label
env=test,用等值选择器-l env=test和-l 'env!=prod'分别查询 - 用
kubectl get pods -l 'env in (test,dev)'验证集合语法 - 故意给 Service selector 加一个不匹配的 label,观察
kubectl get endpointslice无后端
练习 B
- 给一个节点打标签
disk-type=ssd,创建带nodeSelector的 Deployment,确认调度到该节点 - 给该节点打污点
test=value:NoSchedule,创建无 toleration 的 Pod,观察 Pending - 添加对应 toleration,观察 Pod 成功调度;移除污点后观察行为变化
下一篇:Kubernetes 资源故障排查。