Appearance
标签与资源关系
Kubernetes 里的资源不是按“文件顺序”关联的,而是通过标签、选择器、名称引用和 ownerReference 建立关系。Deployment 管哪些 Pod、Service 转发到哪些 Pod、NetworkPolicy 作用在哪些 Pod、Prometheus 采集哪些 Service,本质上都依赖这些关联规则。
标签和资源关系写错时,API Server 不一定报错。Service selector 匹配不到 Pod,Service 仍然能创建成功;NetworkPolicy selector 写宽了,可能影响更多 Pod;ConfigMap 名称写错,Pod 到挂载阶段才暴露错误。排查时要把资源之间的连接线还原出来,而不是只看单个 YAML。
一、labels 和 annotations
labels 是可匹配的键值对,annotations 是附加说明和扩展参数。
yaml
metadata:
name: web
namespace: demo
labels:
app: web
env: prod
version: v1
annotations:
kubernetes.io/change-cause: "release web v1"| 字段 | 典型用途 |
|---|---|
labels | 被 selector 匹配,用来建立资源关系 |
annotations | 保存说明、变更记录、控制器扩展参数,不参与 selector 匹配 |
标签一般放稳定、低基数、可选择的维度,比如 app、env、tier、version。Pod IP、时间戳、请求 ID 这类高变化字段不适合做 label。监控和日志系统也会读取 Kubernetes label,高基数标签容易把 Prometheus、Loki 这类后端拖得很重。
二、selector 怎么选中对象
Deployment 通过 selector 找自己管理的 Pod:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
spec:
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web # Pod 模板标签必须和 selector 对上
spec:
containers:
- name: nginx
image: nginx:1.26Service 也通过 selector 找后端 Pod:
yaml
apiVersion: v1
kind: Service
metadata:
name: web
namespace: demo
spec:
selector:
app: web
ports:
- name: http
port: 80
targetPort: 80关系图如下:
Service 不直接保存 Pod IP。selector 选中 Pod 后,控制器生成 EndpointSlice,Service 转发时再走这些 endpoint。
bash
kubectl get pod -n demo --show-labels
kubectl get pod -n demo -l app=web
kubectl get svc web -n demo -o yaml
kubectl get endpointslice -n demo -l kubernetes.io/service-name=webkubectl get endpoints 在新版本里仍常见,但 EndpointSlice 才是更细粒度的后端对象。Service 不通时,EndpointSlice 为空通常说明 selector 没选中 Ready Pod,或者 Pod readiness 没通过。
三、matchLabels 和 matchExpressions
selector 不只有精确匹配。复杂场景可以用 matchExpressions:
yaml
selector:
matchExpressions:
- key: app
operator: In
values:
- web
- api
- key: env
operator: NotIn
values:
- test常见 operator:
| operator | 含义 |
|---|---|
In | key 的值在指定列表中 |
NotIn | key 的值不在指定列表中 |
Exists | 存在这个 key |
DoesNotExist | 不存在这个 key |
NetworkPolicy、PodDisruptionBudget、TopologySpreadConstraints、ServiceMonitor 都会用到 selector。写复杂 selector 时,先用 kubectl get pod -l ... 验证匹配范围,比直接 apply 后再猜影响面更清楚。
四、ownerReference——父子关系和垃圾回收
控制器创建子资源时会写入 ownerReference。Deployment 创建 ReplicaSet,ReplicaSet 创建 Pod:
查看 Pod 的 ownerReference:
bash
kubectl get pod <pod-name> -n demo -o yaml | grep -A12 ownerReferences典型输出:
yaml
ownerReferences:
- apiVersion: apps/v1
kind: ReplicaSet
name: web-6f7c9c9c9b
uid: 4d2b0c5e-1111-2222-3333-444455556666
controller: trueownerReference 影响垃圾回收。删除 Deployment 时,Kubernetes 能沿着 ownerReference 删除 ReplicaSet 和 Pod。直接删除 Pod 时,ReplicaSet 会发现实际副本数少了,再创建一个新的 Pod。
这种差异在排查“Pod 删了又回来”时很常见。Pod 自己不是根对象,背后的 ReplicaSet、Deployment、StatefulSet 或 DaemonSet 才是维持状态的控制器。
五、名称引用
有些资源关系不靠 selector,而是直接写对象名称。
| 关系 | 字段 |
|---|---|
| Pod 引用 ConfigMap | spec.containers[].envFrom[].configMapRef.name、spec.volumes[].configMap.name |
| Pod 引用 Secret | secretKeyRef.name、imagePullSecrets[].name、spec.volumes[].secret.secretName |
| Pod 引用 PVC | spec.volumes[].persistentVolumeClaim.claimName |
| Ingress 引用 Service | spec.rules[].http.paths[].backend.service.name |
| HTTPRoute 引用 Service | spec.rules[].backendRefs[].name |
| ServiceMonitor 引用 Service | spec.selector.matchLabels 匹配 Service label |
名称引用写错通常不会在 YAML 解析阶段失败,而是在运行阶段表现为挂载失败、镜像拉取失败、路由无后端或采集目标缺失。
bash
kubectl describe pod <pod-name> -n demo
kubectl get events -n demo --sort-by=.lastTimestampEvents 里常见 not found、failed to sync configmap cache、MountVolume.SetUp failed、secret not found。这类错误先核对 namespace,再核对名称。
六、资源关系图
一个常见 Web 服务会同时涉及配置、密钥、工作负载、Service 和入口资源:
按关系排查比直接翻全部 YAML 更稳:
| 现象 | 先看哪里 |
|---|---|
| 入口访问 404/503 | HTTPRoute/Ingress 是否指向正确 Service |
| Service 不通 | EndpointSlice 是否有 Ready 后端 |
| Pod 启动失败 | Events、镜像、挂载、探针 |
| 配置没生效 | Pod 挂载的 ConfigMap/Secret 名称和内容 |
| 监控没采到 | Service label、ServiceMonitor selector、端口名称 |
Kubernetes 资源关系的难点不在单个字段,而在这些字段把对象连成一张图。图上的某条线断了,表现出来可能是网络不通、Pod 不 Ready、日志采不到、告警没触发。