Skip to content

YAML 与资源关系

Kubernetes 的资源最终都落成 API 对象。YAML 只是提交对象的一种写法,关键在于理解 apiVersionkindmetadataspecstatus 五个字段的含义,以及对象之间靠标签、选择器、名称引用和 ownerReference 建立的关系。

基本结构

通用骨架:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: demo
  labels:
    app: web
spec:
  replicas: 2
status:
  # 由 Kubernetes 控制器维护
字段说明
apiVersionAPI 组和版本,决定了资源有哪些字段
kind资源类型
metadata身份信息——名称、命名空间、标签、注解
spec期望状态——用户写的内容
status当前状态——控制器写的内容

kubectl apply 提交的是 spec。控制器运行后不断更新 status:Pod IP、Ready 状态、重启次数、Deployment 可用副本数都出现在 status 里。

API 组和版本

apiVersionkind 示例
v1Pod、Service、ConfigMap、Secret、PVC
apps/v1Deployment、StatefulSet、DaemonSet
batch/v1Job、CronJob
networking.k8s.io/v1Ingress、NetworkPolicy
gateway.networking.k8s.io/v1Gateway、HTTPRoute
storage.k8s.io/v1StorageClass
rbac.authorization.k8s.io/v1Role、ClusterRole、Binding

查看资源和字段:

bash
kubectl api-resources | grep -E 'deploy|ingress|gateway|storageclass'
kubectl explain deployment.spec        # 看字段结构,不用靠猜
kubectl explain gateway.spec

CRD 装好以后,kubectl explain 也能看到对应资源结构。

metadata、labels、annotations

metadata.name 是资源名,namespace 是命名空间。labels 用来选择和关联,annotations 用来放不适合选择的附加信息。

yaml
metadata:
  name: web
  namespace: demo
  labels:
    app: web
    env: prod
    version: v1
  annotations:
    kubernetes.io/change-cause: "release v1"
字段用途
labelsService selector、Deployment selector、监控发现、策略匹配
annotations变更说明、控制器特定参数、额外元数据

Ingress 时代很多控制器功能靠 annotations 实现(rewrite、canary、限流)。Gateway API 把这些放进标准资源字段,减少了控制器私有注解的迁移成本。

selector——资源关联的核心

Deployment 通过 selector 找自己的 Pod:

yaml
spec:
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web

Service 通过 selector 找后端 Pod:

yaml
spec:
  selector:
    app: web

关系图:

Deployment 的 selector 创建后基本不适合改。改错后控制器可能接管不到原来的 Pod,或者误接管其他 Pod——两个方向都是故障。

ownerReference——父子关系和垃圾回收

控制器创建子资源时写入 ownerReference。Deployment 创建 ReplicaSet,ReplicaSet 创建 Pod,形成层级:

bash
kubectl get pod <pod-name> -o yaml | grep -A10 ownerReferences

ownerReference 影响垃圾回收。删除 Deployment 时,ReplicaSet 和 Pod 跟着删除。直接删除 Pod 时,ReplicaSet 发现副本数少了,会创建新 Pod——两种"删除"的效果完全不同。

名称引用

有些关系不靠 selector,而是靠名称直接引用:

关系字段
Pod → PVCspec.volumes[].persistentVolumeClaim.claimName
Pod → ConfigMapconfigMap.nameconfigMapKeyRef.name
Pod → SecretsecretNamesecretKeyRef.name
Ingress → Servicebackend.service.name
HTTPRoute → ServicebackendRefs.name

名称引用错了,Events 里通常出现 not found、挂载失败、后端不存在。

apply 和 diff

bash
kubectl diff -f app.yaml        # 预览集群对象和本地 YAML 的差异
kubectl apply -f app.yaml       # 提交声明式配置
kubectl get deploy,svc -n demo  # 查看对象状态
kubectl describe deploy web -n demo

查看集群中的实际对象:

bash
kubectl get deploy web -n demo -o yaml

集群里返回的对象包含很多系统补充字段——resourceVersionuidmanagedFieldsstatus。这些字段不适合直接复制回 Git 作为源文件,YAML 源文件应该只保留 spec 层面的内容。

一次完整的资源关系

一个常见 Web 服务的资源关系图:

排查时就按这个关系走:Route/Ingress 是否指向 Service → Service 是否有 EndpointSlice → Deployment 是否创建了 Pod → Pod 是否挂载了配置和 Secret → Pod 自身是否 Ready。每一步对应不同的 kubectl 命令。