Kubernetes Pod
本文最后更新于 2025年8月8日 下午
pod 是Kubernetes集群中的最小管理单元,其中包含一个或多个应用容器,可被看作面向应用的“逻辑主机”,是Kubernetes中核心的资源对象
标准格式
1 | |
| 字段路径 | 类型 | 说明 | 示例 / 可选值 |
|---|---|---|---|
apiVersion |
string | API版本 | v1 |
kind |
string | Kubernetes 资源类型 | Pod |
metadata.name |
string | Pod 名称 | my-pod |
metadata.namespace |
string | 所属命名空间 | default |
metadata.labels |
map<string,string> | 标签键值对,用于选择器等 | app: nginx |
metadata.annotations |
map<string,string> | 注解信息,不参与选择器 | prometheus.io/scrape: "true" |
spec.containers |
array | 容器数组,定义一个或多个容器 | - |
spec.containers[].name |
string | 容器名称 | web |
spec.containers[].image |
string | 容器镜像 | nginx:1.25 |
spec.containers[].imagePullPolicy |
string | 镜像拉取策略 | Always,IfNotPresent,Never |
spec.containers[].command |
array[string] | 容器启动命令(替代 ENTRYPOINT) | ["/bin/sh"] |
spec.containers[].args |
array[string] | 容器启动参数(替代 CMD) | ["-c", "echo Hello"] |
spec.containers[].workingDir |
string | 工作目录 | /app |
spec.containers[].volumeMounts |
array | 挂载卷信息 | - |
spec.containers[].volumeMounts[].name |
string | 要挂载的卷名称 | data-volume |
spec.containers[].volumeMounts[].mountPath |
string | 容器内挂载路径 | /data |
spec.containers[].volumeMounts[].readOnly |
boolean | 是否只读挂载 | true/false |
spec.containers[].ports |
array | 容器端口暴露 | - |
spec.containers[].ports[].name |
string | 端口名称(可选) | http |
spec.containers[].ports[].containerPort |
int | 容器内部监听端口 | 80 |
spec.containers[].ports[].hostPort |
int | 宿主机端口映射 | 8080 |
spec.containers[].ports[].protocol |
string | 协议类型 | TCP、UDP |
spec.containers[].env |
array | 环境变量列表 | - |
spec.containers[].env[].name |
string | 变量名 | ENV_MODE |
spec.containers[].env[].value |
string | 变量值 | production |
spec.containers[].resources |
object | 资源限制与请求 | - |
spec.containers[].resources.limits.cpu |
string | 最大 CPU 限制 | 500m |
spec.containers[].resources.limits.memory |
string | 最大内存限制 | 512Mi |
spec.containers[].resources.requests.cpu |
string | 预留 CPU 请求 | 250m |
spec.containers[].resources.requests.memory |
string | 预留内存请求 | 256Mi |
spec.containers[].livenessProbe |
object | 存活探针 | - |
spec.containers[].livenessProbe.exec.command |
array | 执行命令探针 | ["cat", "/tmp/healthy"] |
spec.containers[].livenessProbe.httpGet |
object | HTTP 探针 | - |
spec.containers[].livenessProbe.httpGet.path |
string | 探测路径 | /healthz |
spec.containers[].livenessProbe.httpGet.port |
int/string | 端口号或端口名 | 8080 |
spec.containers[].livenessProbe.httpGet.host |
string | 请求主机 | localhost |
spec.containers[].livenessProbe.httpGet.scheme |
string | 请求协议 | HTTPor HTTPS |
spec.containers[].livenessProbe.httpGet.httpHeaders |
array | 头部设置 | [{ name: "X-Custom", value: "123" }] |
spec.containers[].livenessProbe.tcpSocket.port |
int | TCP 端口探测 | 3306 |
spec.containers[].livenessProbe.initialDelaySeconds |
int | 初始延迟秒数 | 10 |
spec.containers[].livenessProbe.timeoutSeconds |
int | 超时时间 | 2 |
spec.containers[].livenessProbe.periodSeconds |
int | 探测周期 | 5 |
spec.containers[].livenessProbe.successThreshold |
int | 成功次数阈值 | 1 |
spec.containers[].livenessProbe.failureThreshold |
int | 失败次数阈值 | 3 |
spec.containers[].securityContext.privileged |
bool | 是否启用特权模式 | true/false |
spec.restartPolicy |
string | Pod 重启策略 | Always,OnFailure,Never |
spec.nodeSelector |
map<string,string> | 节点选择器 | { "disktype": "ssd" } |
spec.imagePullSecrets |
array | 镜像拉取凭证 | [{ name: "my-registry-key" }] |
spec.hostNetwork |
bool | 是否使用主机网络 | true/false |
spec.volumes |
array | 卷定义 | - |
spec.volumes[].name |
string | 卷名称 | data-volume |
spec.volumes[].emptyDir |
object | 空目录卷(临时数据) | {} |
spec.volumes[].hostPath.path |
string | 主机路径挂载 | /data/host |
spec.volumes[].secret.secretName |
string | 绑定的 secret 名称 | my-secret |
spec.volumes[].secret.items[] |
object | 指定映射的 key/path | { key: "token", path: "token.txt" } |
spec.volumes[].configMap.name |
string | 引用的 ConfigMap 名称 | app-config |
spec.volumes[].configMap.items[] |
object | 指定映射的 key/path | { key: "app.properties", path: "conf/app.properties" } |
当存在两个应用紧密耦合,并组合为一个整体进行对外服务时,应将这两个容器应用封装为一个Pod
1 | |
应用通过localhost:6379 对redis进行访问
静态Pod
静态Pod是由kubelet管理的仅存在于kubelete所在Node上的Pod,不需要通过Kubernetes的Master管理。kubelet负责监控由它创建的静态Pod,并在失效时重建pod。静态Pod无法被Master管理,以及无法使用普通Pod可以使用的其他资源
1.基于本地配置文件
在kubelet的主配置文件中设置 staticPodPath。kubelet会定期扫描该目录
配置目录为 /etc/kubernetes/manifests 配置参数为staticPodPath:/etc/kubernetes/manifests
在/etc/kubelet.d 目录下设置配置文件
1 | |
- 网络配置
通过 —manifest-url 获取yaml 文件作为配置信息
Pod容器共享Volume
在tomcal容器中设置将命名为app-logs的volume 挂在到/usr/local/tomcat/logs中
设置volumes ,而在busybox 将该目录挂在为/logs 。
1 | |
Pod的配置管理
ConfigMap用于保存应用程序运行时需要的配置数据,通过明文及K:V存储
ConfigMap 一般用于
1.生成容器内的环境变量
2.设置容器启动命令的命令参数
3.以Volume的形式挂在为容器内的文件或目录
1 | |
在env 下使用configmap , configmap会以文件进行挂载
1 | |
使用envfrom 配置为环境变量
1 | |
容器内获取Pod信息
Downward API
通过Downward API 将Pod的信息注入到容器的环境变量中
1 | |
在文件中不是直接写入而是通过valueFrom指定对应的数据字段获取值
将Container配置信息设置为容器内的环境变量
1 | |
Volume挂载
将Pod信息挂载为容器内的文件
1 | |
将容器的配置信息挂载为容器内的文件
1 | |
支持设置的信息
- 由fieldRef设置的字段
metadata.name: Pod名称
metadata.namespace: Pod所在的命名空间名称
metadata.uid: Pod的UID
metadata.labels[’<KEY>’]: Pod某个Label的值,通过<KEY>引用
metadata.annotations[‘<KEY>’]: Pod某个Annotations的值,通过<KEY>引用 - Pod的以下元数据信息可以被设置为容器内的环境变量,
spec.serviceAccountName: Pod使用的ServiceAccount名称
spec.nodeName: Pod所在Node的名称
status.hostIP: Pod所在Node的IP地址
status.hostIPs: Pod所在Node的双栈IP地址
status.IP: Pod的IP地址
status.IPs: Pod的双栈IP地址 - 设置downwardAPI为存储卷类型时,可以在器fieldRef字段设置以下信息
metadata.labels : Pod的label列表
metadata.annotations : Pod的annotation列表 - 通过resourceFieldRef 设置的字段
limits.cpu # 容器可使用的最大 CPU 数量(上限),单位为核心(如 1、500m 等),超出会被限制
requests.cpu # 容器调度时请求的最小 CPU 数量,调度器据此分配节点资源,单位同上
limits.memory # 容器可使用的最大内存(上限),单位如 Mi、Gi,超出将触发 OOMKilled
requests.memory # 容器调度时请求的最小内存,调度器据此分配节点资源
limits.hugepages-* # 容器可使用的最大 HugePages 限额,例如 limits.hugepages-2Mi
requests.hugepages-* # 容器调度时请求的 HugePages 数量,例如 requests.hugepages-1Gi
limits.ephemeral-storage # 容器使用的最大临时存储空间(如 emptyDir、写入容器层),超出会被限制
requests.ephemeral-storage # 容器调度时请求的最小临时存储空间,用于调度决策。
生命周期
Pod的生命周期
Pending 创建Pod的请求已被Master接受,但有一个或多个容器没有创建也没有运行
Running Pod已完成调度到特定Node,其包含的所有容器均已创建,并且至少由一个容器处于正在运行状态
Succeeded Pod内的所有容器君子成功执行后终止,不会重启
Failed Pod内的所有容器均已终止,但至少有一个容器未退出失败状态,即退出码不是0
Unknown 由于某种原因无法获得Pod的状态
Pod的状况
PodScheduled 已将Pod调度到某个Node
PodReadyToStartContainers Pod已创建,并完成网络配置,可以启动容器。
ContainersReady Pod中的全部容器都达到Ready状态
Initialized Pod中的全部初始化容器都成功运行
Ready Pod达到Ready状态,可以被加入相应Service的负载均衡后端列表中
容器状态
Waiting :Kubernetes在能够运行该容器之前通常需要执行某些操作,例如下载容器镜像,为容器设置存储卷,等待依赖资源达到就绪状态,因此系统设置容器的状态为等待运行
Running :表示容器处于正常的运行过程中,并没有发生错误
Terminated : 运行结束,可能是正常运行结束,也可能是因为失败结束
Pod的重启策略
- Always : 当容器启动失败后总是由kubelet尝试自动重启容器
- OnFailure : 当容器终止运行且退出码不为0时,由kubelet自动重启容器
- Never: 不论容器处于哪种运行状态,kubelet不会重启该容器
控制权与重启策略
Deployoment/StatuefulSet/DaemonSet/RC : 必须设置为Always
Job : OnFailure或Never
kubelet : 在静态Pod失效时自动重启它
Pod的终止过程
- 通过kubectl delete pod
命令手动删除一个Pod,优雅终止的宽限期默认为30s - 控制平面会更新Pod的状态,通过kubectl get 或describe命令可以看到Pod状态为”Terminating”。在Pod运行的Node上,kubelet一旦探测到Pod状态为”Terminating”就开始对Pod进行以下终止操作
如果容器配置了preStop回调钩子,并且配置了非0的终止宽限期,kubelet就调用preStop回调钩子。如果preStop回调钩子在终止宽限期之后还未完成,会向宽限期增加时间(默认2s)
如果容器没配置preStop,或者终止宽限期已过,kubelet就调用容器运行时给容器的主进程发送TERM信息,也可能发送容器镜像中STOPSIGNAL变量配置的信号 - 在kubelet启动Pod的优雅终止过程的同时,控制平面会评估是否将正在终止的Pod从对应服务的后端列表中移除。
- 超过优雅终止宽限期之后,kubelet首先会启动强制终止容器进程的操作,通过容器运行时向剩余的进程发送KILL信号,kubelet也会删除Pod的基础Pause容器。然后kubelet将Pod的阶段设置为Succeeded或Failed。并设置宽限期为0,表示立刻删除。最后控制平面从etcd中彻底删除该Pod资源对象
Pod的垃圾清理机制
Kubernetes的控制平面提供了一个Pod垃圾清理器PodGC(Garbage Collector),在监控到Pod数量超过阈值时,会进行删除已终止Pod的操作。GC会清理以下条件的Pod
- 孤儿Pod : 已完成调度,但Node 不再存在
- 在计划外终止的Pod
- 终止过程中的Pod
探针和健康检查机制
- LivenessProbe 探针
用于判断容器是否存活,如果LivenesProbe探针探测到容器不健康,则杀掉该容器,并根据容器的重启策略做相应的处理,如果容器未设置LivenessProbe探针,那么kubelet认为该容器的LivenessProbe探针返回的值永远是Success
- ReadinessProbe探针
用于判断容器服务是否处于Ready状态,处于Ready状态的Pod才可以接收请求。ReadinessProbe定期触发,存在于Pod的整个生命周期内
- StartupProbe探针
某些应用会遇到一些情况,例如应用程序在启动时需要与远程服务器建立网络连接,或者网络访问较慢等,导致容器启动缓慢,可以由StartupProbe持续检查Pods状态,在此期间LivenessProbe探针和ReadinessProbe探针均被禁用,直到StartupProbe 返回成功
探测策略
- exec : 在容器内运行指定的命令,如果该命令运行的返回码未0,则说明探测成功
- tcpSocket : 通过容器的IP地址和端口号执行TCP检查,如果能够建立TCP连接,则说明探测成功
- httpGet:通过容器的IP地址,端口号及路径调用HTTP Get方法,如果响应的状态码大于等于200且小于400 说明探测成功。
- grpc:通过gRPC执行一个Health Check的远程调用,要求应用程序实现gRPC健康检查协议,如果响应的status为SERVING
字段配置
- initalDelaySecondes: 启动容器后进行首次探测的等待时间,单位为s,默认值为0,最小值为0.
- periodSecondes: 周期性执行探测的时间间隔,单位为s,默认为10,最小值为1
- timeoutSeconds: 发出探测请求后等待结果的超时时间,单位为s。当超时发生时,kubelet认为探测失败
- successThreshold: 探测失败后,判定为探测成功的最小连续探测成功的次数,默认值为1
- failureThreshold: 判定为探测失败的连续探测失败的次数,达到整个数量后,kubelet会认为容器不健康或者服务未就绪,并将基于重启策略对容器进行重启操作
- terminationGracePeriodSecondes: 探测失败后,kubelet触发终止容器命令之后等待容器自行结束的宽限期,单位为s,默认值为30,最小值为1
HTTP类型探针的配置
- host: 主机名,默认为Pod的IP地址
- scheme: 连接协议
- path: 访问路径,默认为“/”
- httpHeaders: 自定义HTTP头,允许重复
- port: 容器的端口号或端口名称
探测结果
- Success 探测成功
- Failure 探测失败
- Unknown 探测失败
exec机制配置LivenessProbe
1 | |
tcpSocket机制配置LivenessProbe
1 | |
httpGet机制配置LivenessProbe
1 | |
gRPC机制配置LivenessProbe
1 | |
设置startupProbe保护探针保护需要启动很长时间的容器
1 | |
如果300s后仍未成功启动,kubelet会尝试重启策略
设置ReadinessProbe探针保护暂时无法提供服务的容器
1 | |
kubelet 在探测到容器服务不在就绪时,会通知控制平面,以调整对应的Service,将不健康的后端Pod暂时隔离,不再将请求转发到这个Pod,从而避免出现大量的失败状况
初始化容器
初始化容器是一种特殊的容器
初始化容器的运作方式与应用容器不同:初始化容器必须先于应用容器运行成功,在设置了多个初始化容器时,将按顺序逐个运行初始化容器,并且只有前一个初始化容器运行成功,才能运行其之后的一个初始化容器。在所有初始化容器运行成功后,才会初始化Pod的各种信息,并开始创建和运用容器
初始化容器的定义中可以设置资源限制,Volume的使用和安全策略,等待。
- 如果多个初始化容器定义了资源请求或者资源限制,则取最大的值为所有初始化容器的资源请求值或资源限制值
- Pod的有效资源请求值或资源限制取值以下二者的较大值
- 所有应用容器的资源请求值或资源限制值之和
- 初始化容器的有效资源请求或资源限制值
- 调度算法将基于Pod的有效资源请求致或资源限制值进行计算,也就是说,初始化容器可以为初始化操作预留系统资源,即使后续的应用容器 无须使用这些资源
- Pod的有效QoS等级适用于初始化容器和应用容器
- 资源配额和限制将根据Pod的有效资源请求值或者资源限制值计算且生效
- Pod级别的Cgroup将基于Pod的有效资源请求或限制,与调度机制一致
初始化容器不支持对生命周期和健康检查机制进行配置
可能重启的场景
- Pod的infrastructure容器更新,此时Pod会重启
- Pod中的所有应用容器都终止,此时Pod会重启
初始化容器的实现原理
通过initContainers字段配置初始化容器,以实现在启动应用容器之前运行初始化容器,并且允许配置一个或多个初始化容器,已完成应用容器所需的预置条件。系统会在Pod的状态信息的initContainerStatuses字段中显示初始化容器的运行信息
通过初始化容器为应用容器准备数据
1 | |
通过初始化容器等待应用容器依赖的一个服务处于Ready状态
1 | |
通过初始化容器将Pod作为一个服务实例注册到外部的某个服务中心
1 | |
设置两个初始化容器
1 | |
注意事项
- 如果初始化容器运行失败,系统会根据Pod的重启策略进行重启。
- 在所有初始化容器都进入运行完毕之前,Pod不会进入Ready状态
- 在重启Pod时会重启所有初始化容器
- 在创建之后,如果需要修改初始化容器的定义,则只允许修改image字段
- Kubernetes在创建Pod时,会强制检查在初始化容器的定义中是否存在ReadinessProbe,如果存在,则将拒绝创建
- 如果Pod设置了activeDeadlineSeconds , 则可以避免初始化容器持续运行失败并且无限重启
- 在Pod中,每个容器的名称都必须唯一
pod 是Kubernetes集群中的最小管理单元,其中包含一个或多个应用容器,可被看作面向应用的“逻辑主机”,是Kubernetes中核心的资源对象