Appearance
YAML 与资源关系
Kubernetes 的资源最终都落成 API 对象。YAML 只是提交对象的一种写法,关键在于理解 apiVersion、kind、metadata、spec、status 五个字段的含义,以及对象之间靠标签、选择器、名称引用和 ownerReference 建立的关系。
基本结构
通用骨架:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
labels:
app: web
spec:
replicas: 2
status:
# 由 Kubernetes 控制器维护| 字段 | 说明 |
|---|---|
apiVersion | API 组和版本,决定了资源有哪些字段 |
kind | 资源类型 |
metadata | 身份信息——名称、命名空间、标签、注解 |
spec | 期望状态——用户写的内容 |
status | 当前状态——控制器写的内容 |
kubectl apply 提交的是 spec。控制器运行后不断更新 status:Pod IP、Ready 状态、重启次数、Deployment 可用副本数都出现在 status 里。
API 组和版本
| apiVersion | kind 示例 |
|---|---|
v1 | Pod、Service、ConfigMap、Secret、PVC |
apps/v1 | Deployment、StatefulSet、DaemonSet |
batch/v1 | Job、CronJob |
networking.k8s.io/v1 | Ingress、NetworkPolicy |
gateway.networking.k8s.io/v1 | Gateway、HTTPRoute |
storage.k8s.io/v1 | StorageClass |
rbac.authorization.k8s.io/v1 | Role、ClusterRole、Binding |
查看资源和字段:
bash
kubectl api-resources | grep -E 'deploy|ingress|gateway|storageclass'
kubectl explain deployment.spec # 看字段结构,不用靠猜
kubectl explain gateway.specCRD 装好以后,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"| 字段 | 用途 |
|---|---|
| labels | Service selector、Deployment selector、监控发现、策略匹配 |
| annotations | 变更说明、控制器特定参数、额外元数据 |
Ingress 时代很多控制器功能靠 annotations 实现(rewrite、canary、限流)。Gateway API 把这些放进标准资源字段,减少了控制器私有注解的迁移成本。
selector——资源关联的核心
Deployment 通过 selector 找自己的 Pod:
yaml
spec:
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: webService 通过 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 ownerReferencesownerReference 影响垃圾回收。删除 Deployment 时,ReplicaSet 和 Pod 跟着删除。直接删除 Pod 时,ReplicaSet 发现副本数少了,会创建新 Pod——两种"删除"的效果完全不同。
名称引用
有些关系不靠 selector,而是靠名称直接引用:
| 关系 | 字段 |
|---|---|
| Pod → PVC | spec.volumes[].persistentVolumeClaim.claimName |
| Pod → ConfigMap | configMap.name 或 configMapKeyRef.name |
| Pod → Secret | secretName 或 secretKeyRef.name |
| Ingress → Service | backend.service.name |
| HTTPRoute → Service | backendRefs.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集群里返回的对象包含很多系统补充字段——resourceVersion、uid、managedFields、status。这些字段不适合直接复制回 Git 作为源文件,YAML 源文件应该只保留 spec 层面的内容。
一次完整的资源关系
一个常见 Web 服务的资源关系图:
排查时就按这个关系走:Route/Ingress 是否指向 Service → Service 是否有 EndpointSlice → Deployment 是否创建了 Pod → Pod 是否挂载了配置和 Secret → Pod 自身是否 Ready。每一步对应不同的 kubectl 命令。