5月28日 03:53

Kubernetes YAML 怎么写?核心字段和常见配置模式详解

Kubernetes 用 YAML 声明式描述资源期望状态——你告诉 K8s"我要什么结果",它负责把集群调到那个状态。一个合法的 K8s YAML 只有四个必填顶层字段:apiVersionkindmetadataspec。所有资源都是这四件套的排列组合,区别只在 spec 里填什么。

追问

apiVersion 怎么选?选错了会怎样?

按资源类型对照:核心资源 v1(Pod、Service、ConfigMap、Secret),工作负载 apps/v1(Deployment、StatefulSet、DaemonSet),网络 networking.k8s.io/v1(Ingress、NetworkPolicy),批处理 batch/v1(Job、CronJob),权限 rbac.authorization.k8s.io/v1。拿不准就跑 kubectl api-resources 查。

选错版本有两种后果:用了废弃版本(如 extensions/v1beta1 的 Deployment),K8s 1.16 之后直接报错拒绝创建;用了太新的版本但集群版本低,同样报错。生产环境升级 K8s 前必须检查 API 废弃公告,否则 kubectl apply 一跑全挂。

metadata 里 labels 和 annotations 分别干什么?

labels 是给 K8s 的选择器用的——Service 找 Pod、Deployment 管 ReplicaSet 全靠 label 匹配,值要短、要稳、要有层次(比如 app: order-service, tier: backend, env: prod)。annotations 不参与选择器,存给人看的信息:Git commit hash、变更原因、负责人邮箱、监控配置等。一条原则:selector 需要匹配的放 labels,纯描述放 annotations。

踩坑提醒:label 值一旦写进 selector 就别随便改,改了会导致 Deployment 丢失 Pod、Service 断流。annotations 随便改,不影响运行。

spec 里 replicas、selector、template 三者什么关系?为什么经常报错?

这是 Deployment 最容易出错的地方。replicas 决定跑几个 Pod,selector 声明"我管哪些 Pod"(通过 matchLabels),template 定义"Pod 长什么样"。铁律:selector.matchLabels 必须是 template.metadata.labels 的子集,否则 Deployment 创建了 Pod 却认不出它们,replicas 永远对不上,Pod 会被反复创建又丢弃。

实战中最常犯的错:改了 template 里的 label 却忘了同步改 selector,或者 Deployment 和 Service 的 selector 对不上,导致 Service 发现不了 Pod。排查时 kubectl get pods -l app=myapp 看 selector 能不能匹配到 Pod。

多资源写一个文件用 --- 分隔,什么场景该合什么场景该拆?

--- 把多个资源塞进一个 YAML 文件,kubectl apply -f app.yaml 一次全部署。同一个应用的所有资源(Deployment + Service + ConfigMap)适合合在一起,变更追踪和回滚都方便。不同应用的资源必须拆开,否则一个文件改坏全挂,kubectl diff 也看不出谁改了什么。

更复杂的场景用 Kustomize 的 overlay 机制或 Helm chart 管理,别在单文件里堆几十个资源。

资源限制 requests 和 limits 都要设吗?不设会怎样?

都要设,尤其是生产环境。requests 是调度依据,K8s 据此决定 Pod 放哪个节点;limits 是硬上限,超过就被 OOMKill 或 CPU 节流。不设 requests:调度器不知道 Pod 需要多少资源,可能把重负载 Pod 全堆到一个节点,节点撑爆。不设 limits:一个 Pod 可以吃光节点资源,邻居全受影响(Noisy Neighbor 问题)。

常见策略:requests 设为实际用量的 70-80%,limits 设为 requests 的 1.5-2 倍。用 kubectl top pods 观察实际用量,定期调整。

YAML 常见报错怎么排查?

缩进错误最常见:必须用空格不能用 Tab,同一层级严格对齐,嵌套加两个空格。类型错误:端口号别加引号(80 不是 "80"),布尔值用 true/false 不用 yes/no(YAML 1.2 规范不认后者)。必填字段漏了:Deployment 必须有 selector,Service 必须有 port 和 targetPort。

排查三板斧:kubectl apply --dry-run=client 先试跑看语法错误,yamllint 检查格式规范,kubevalkubeconform 校验字段是否合法。CI 流水里加上这几步,能挡住 90% 的低级错误。

标签:YAML