跳到主要内容

Kubernetes Pod Yaml文件解析

· 阅读需 8 分钟

Pod 是 Kubernetes 里最小的调度单元,几乎所有工作负载最终都会落到 Pod 的 YAML 定义上。这份笔记整理了 Pod YAML 的全字段注释,以 kubectl explain 查询结果为准,例如:kubectl explain pod.spec.volumes

为什么要读懂 Pod YAML

平时用 Deployment、StatefulSet 部署应用,它们的 spec.template 部分本质上就是一个 Pod 模板。排查容器起不来、探针失败、挂载路径不对这类问题,最后都要回到 Pod 定义上逐字段核对。与其每次翻文档,不如把常用字段的含义一次性过一遍。

字段拿不准的时候,最可靠的方式是问 API 本身:

# 查看某个字段的文档说明
kubectl explain pod.spec.containers.livenessProbe

# 递归列出某个字段下的全部子字段
kubectl explain pod.spec.volumes --recursive

kubectl explain 直接读取集群的 OpenAPI Schema,和当前集群版本严格一致,比任何抄来的注释表都准。

全字段注释参考

下面是带注释的完整参考(注释仅作速查,以 kubectl explain 为准):

apiVersion: v1 //版本
kind: pod //类型,pod
metadata: //元数据
name: String //元数据,pod的名字
namespace: String //元数据,pod的命名空间
labels: //元数据,标签列表
- name: String //元数据,标签的名字
annotations: //元数据,自定义注解列表
- name: String //元数据,自定义注解名字
spec: //pod中容器的详细定义
containers: //pod中的容器列表,可以有多个容器
- name: String //容器名称
image: String //容器中的镜像名称
imagesPullPolicy: [Always|Never|IfNotPresent]//获取镜像的策略,一直拉取,从不拉取,本地有镜像不拉取
command: [String] //容器的启动命令列表(不配置的话使用镜像打包时使用的启动命令)
args: [String] //容器启动参数列表
workingDir: String //容器的工作目录
volumeMounts: //挂载到到容器内部的存储卷设置
- name: String //应用Pod定义的共享存储卷名称,需要使用volumes[]部分定义的共享存储卷名称
mountPath: String //存储卷在容器内Mount的绝对路径,应少于512个字符
readOnly: boolean //是否为只读模式,默认为读写模式
ports: //容器需要暴露的端口号列表
- name: String //端口的名称
containerPort: int //容器要暴露的端口
hostPort: int //容器所在主机监听的端口(容器暴露端口映射到宿主机的端口),默认与containerPort相同,设置hostPort时,同一台主机将无法启动该容器的第二个副本
protocol: String //端口协议,支持TCP和UDP,默认为TCP
env: //容器运行前要设置的环境列表
- name: String //环境变量的名称
value: String //环境变量的值
resources: //资源限制和资源请求的设置
limits: //资源限制的设置
cpu: Srting //CPU限制,单位为core数,将用于docker run --cpu-shares参数
memory: String //内存限制,单位可以为MiB,GiB等,将用于docker run --memory参数
requeste: //资源请求设置
cpu: String //cpu请求,单位为core数,容器启动的初始可用数量
memory: String //内存请求,单位为MiB或GiB,容器启动的初始可用数量
livenessProbe: //pod内容器健康检查的设置,探测几次无反应后,将自动重启该容器,探测方式包括:exec,httpGet,tcpSocket
exec: //exec探测方式
command: [String] //exec方式需要指定的命令或脚本
httpGet: //通过httpget检查健康,需要指定path,port
path: String //网址URL路径(去除对应的域名或IP地址的部分)
port: number //对应端口
host: String //域名或IP地址
scheme: Srtring //对应的检测协议,如http
httpHeaders: //指定报文头部信息
- name: Stirng //头部信息名称
value: String //头部信息值
tcpSocket: //通过tcpSocket检查健康
port: number //探测端口的端口号
initialDelaySeconds: 0//容器启动完成后首次探测的时间,单位为s
timeoutSeconds: 0 //探测等待响应超时时间,单位为s,默认为1,超时认为容器不健康,容器将重启
periodSeconds: 0 //定期探测时间设置,单位为s,默认为10
successThreshold: 0 //探测几次成功后认为成功
failureThreshold: 0 //探测几次失败后认为失败
securityContext: //安全配置
privileged: false //
restartPolicy: [Always|Never|OnFailure]//重启策略,终止定会重启,除正常结束(退出码为0)外其他非0退出码终止才重启,Pod终止后退出码报告给master不重启Pod
nodeSelector: object //设置Node的Label,key:value格式指定,Pod将被调度到具有这些Label的Node上
imagePullSecrets: //pull镜像时使用Secrets名称,以name:sercretkey格式指定
- name: String //参照物名称
hostNetwork: false //是否使用主机网络模式,默认为false,设置为true,表示使用宿主机网络,不使用docker网桥,此Pod无法在同一台机上启动第2个副本
volumes: //在该pod上定义共享存储卷列表
- name: String //共享存储卷名称,一个Pod内,每个存储卷定义一个名称,供spec[].containers[].volumeMounts[].name应用,其类型很多,:emptyDir,hostPath等
emptyDir: {} //emptyDir类型的存储卷,零时目录,与Pod同生命周期,空对象
hostPath: //hostPath类型的存储卷,表示挂载Pod所在主机的目录,通过volumes[].hostNetwork.path指定
path: string //Pod所在主机的目录,将用于容器中的mount的目录
secret: //类型为secret的存储卷,表示挂载集群预定义的secret对象到容器的内部
secretName: String //存储卷名称
items: //当仅需挂载一个Secret对象中的指定Key时使用
- key: String //key值
path: String //映射文件的相对路径
configMap: //类型为configMap的存储卷,表示挂载集群预定义的configMap对象到容器的内部
name: String //使用configMap的名称
items: //当仅需挂载一个ConfigMap对象中的指定Key时使用
- key: String //定义key
path: String //映射文件的相对路径

几个重点字段的展开说明

1) command 与 args

command 对应容器运行时的 entrypoint,args 对应传给它的参数。两者都不写时,使用镜像自带的 ENTRYPOINT 和 CMD;只写 args 时,镜像的 ENTRYPOINT 保留,CMD 被覆盖;写了 command 则镜像里的 ENTRYPOINT 和 CMD 都不再生效。排查"容器一启动就退出"时,先确认这两个字段有没有意外覆盖镜像的默认启动命令。

2) resources:requests 与 limits

requests 是调度依据——调度器按它判断节点剩余资源够不够;limits 是运行时上限——内存超过 limit 容器会被 OOMKill,CPU 超过 limit 则被限流(不会杀容器)。两者都不填,Pod 会以 BestEffort 的 QoS 等级运行,节点资源紧张时最先被驱逐。生产环境建议至少填 requests。

3) 健康探针

livenessProbe 判定容器是否还活着,失败达到 failureThreshold 次后 kubelet 会重启容器。除它之外还有 readinessProbe(判定是否就绪,失败只会把 Pod 从 Service 端点摘除,不重启容器),字段结构完全相同。initialDelaySeconds 要留够应用启动时间,否则应用还没起来就被探针判死,陷入反复重启的循环。

4) volumes 与 volumeMounts

存储是"两段式"声明:先在 spec.volumes 里定义卷(emptyDir、hostPath、secret、configMap 等类型),再在容器的 volumeMounts 里通过 name 引用并指定挂载路径。两边的 name 必须完全一致,这是新手最常见的报错来源之一。emptyDir 随 Pod 删除而销毁,只适合临时数据;hostPath 直接挂宿主机目录,Pod 换节点后数据就"丢"了,一般只用于日志采集这类节点级场景。

踩坑与注意

上面这份注释表在圈内流传很广,但抄写版本里混入了几处拼写问题,直接照抄会导致 apply 报错或字段被静默忽略:

  • kind: pod 应为 kind: Pod,资源类型首字母大写;
  • imagesPullPolicy 正确字段名是 imagePullPolicy,没有 s;
  • resources 下的 requeste 正确写法是 requests;
  • hostPath 的路径字段就是 volumes[].hostPath.path,注释里写的 hostNetwork.path 是笔误。

字段名拼错时,取决于集群的校验策略,可能直接被拒绝,也可能被当作未知字段忽略——后者更隐蔽,配置看似生效实际没有。所以再强调一次:动手前用 kubectl explain 核对字段名,或者用 kubectl apply --dry-run=server -f pod.yaml 让 API Server 先做一遍校验。

提示

YAML 里的注释应使用 # 而不是 //。上表的 // 注释只是速查用的标注,直接拷贝进真实的 YAML 文件前需要删掉或改成 #

小结

Pod YAML 的字段虽多,常用的其实集中在几块:metadata 的 labels、containers 的镜像与启动命令、resources、三类探针、volumes 挂载。注释表适合快速定位字段位置,但字段名和默认值一律以 kubectl explain 的输出为准——它读的是当前集群的 Schema,不会过期,也不会有抄写错误。

评论 / COMMENTS