Pod 资源详解

Pod 是 Kubernetes 集群中的最小管理单元,其中包含一个或多个应用容器,它们在 Pod 内共享网络配置和存储卷配置。可被看作面向应用的“逻辑主机”,是 Kubernetes 中核心的资源对象。

1. Pod 定义详解

yaml 格式的 Pod 配置文件的标准示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: string
  namespace: strinig
  labels:
  - name: string
  annotations:
  - name: string
spec:
  containers:
  - name: string
    image: string
    imagePullPolicy: [Always | Never | IfNotPresent]
    command: [string]
    args: [string]
    workingDir: string
    volumeMounts:
    - name: string
      mountPath: string
      readOnly: boolean
    ports:
    - name: string
      containerPort: int
      hostPort: int
      protocol: string
    env:
    - name: string
      value: string
    resources:
      limits:
        cpu: string
        memory: string
      requests:
        cpu: string
        memory: string
    livenessProbe:
      exec:
        command: [string]
      httpGet:
        path: string
        port: number
        host: string
        scheme: string
        httpHeaders:
        - name: string
          value: string
      tcpSocket:
        port: number
      initialDelaySeconds: 0
      timeoutSeconds: 0
      periodSeconds: 0
      successThreshold: 0
      failureThreshold: 0
    securityContext:
      privileged: false
  restartPolicy: [Always | Never | OnFailure]
  nodeSelector: object
  imagePullSecrets:
  - name: string
  hostNetwork: false
  volumes:
  - name: string
    emptyDir: {}
    hostPath:
      path: string
    secret:
      secretName: string
      items:
      - key: string
        path: string
    configMap:
      name: string
      items:
      - key: string
        path: string
YAML

上述 yaml 文件中各字段的详细说明见下表:

属性名称取值类型是否必选取值说明
versionStringRequiredAPI 版本号,v1
kindStringRequired资源类型,pod
metadataObjectRequired元数据
metadata.nameStringRequiredPod 的名称,命名需要符合 RFC 1035 规范
metadata.namespaceStringRequiredPod 所属的命名空间,默认值为 default
metadata.labels[]List自定义标签列表
metadata.annotations[]List自定义注解列表
specObjectRequiredPod 的详细配置定义
spec.containers[]ListRequiredPod 中的容器列表
spec.containers[].nameStringRequired容器的名称,命名需要符合 RFC 1035 规范
spec.containers[].imageStringRequired容器的镜像名称
spec.containers[].imagePullPolicyString镜像拉取策略,可选值包括:Always、Never、IfNotPresent,默认值为Always。
(1) Always:表示每次都尝试重新拉取镜像。
(2) IfNotPresent:表示若本地镜像已存在,则使用本地的镜像,否则拉取镜像。
(3) Never:表示仅使用本地镜像。

另外,如果包含以下设置,系统则将默认设置
“imagePullPolicy=Always”:
(1) 不设置imagePullPolicy,也未指定镜像的 tag;
(2) 不设置imagePullPolicy,镜像 tag 为 latest;
(3) 启用了名为“AlwayspPlllmages” 的准入控制器 (Admission Controller)
spec.containers[].commandList容器的启动命令列表,如果不指定,则使用镜像内置的启动命令
spec.containers[].argsList容器的启动命令参数列表
spec.containers[].workingDirString容器的工作目录
spec.containers[].volumeMounts[]List挂载到容器内的存储卷配置
spec.containers[].volumeMounts[].nameString引用 Pod 定义的共享存储卷的名称,需要使用volumes[] 部分定义的共享储存卷名称
spec.containers[].volumeMounts[].mountPathString存储卷在容器内挂载的绝对路径,应少于512个字符
spec.containers[].volumeMounts[].readOnlyBoolean是否为只读模式,默认为读写模式
spec.containers[].ports[]List容器需要暴露的端口号列表
spec.containers[].ports[].nameString端口的名称
spec.containers[].ports[].containerPortInt容器需要监听的端口号
spec.containers[].ports[].hostPortInt容器所在主机需要监听的端口号,默认与containerPort 相同。在设置 hostPort 时,同一台宿主机将无法启动
该容器的第2个副本。
spec.containers[].ports[].protocolString端口协议,支持 TCP 和UDP,默认值为TCP
spec.containers[].env[]List在容器运行前需要设置的环境变量列表
spec.containers[].env[].nameString环境变量的名称
spec.containers[].env[].valueString环境变量的值
spec.containers[].resourcesObject资源限制和资源请求的设置
spec.containers[].resources.limitsObject资源限制的设置
spec.containers[].resources.limits.cpuStringCPU 限制,单位为 core数,将用于 docker run –cpu-shares 参数
spec.containers[].resources.limits.memoryString内存限制,单位可以为MiB、GiB 等,将用于docker run –memory 参数
spec.containers[].resources.requestsObject资源请求的设置
spec.containers[].resources.requests.cpuStringCPU 请求,单位为 core数,即容器启动时的初始可用数量
spec.containers[].resources.requests.memoryString内存请求,单位可以为MiB、GiB 等,即容器启动的初始可用数量
spec.containers[].livenessProbeObject对 Pod 内各容器健康检查的设置,在周期性健康检查无响应几次之后,系统将自动重启该容器。可以设置的方法包括:exec、 httpGet和tcpSocket。对一个容器仅需设置一种健康检查方法。
spec.containers[].livenessProbe.execObject对 Pod 内各容器健康检查的设置,采用exec方式
spec.containers[].livenessProbe.exec.command[]String采用 exec 方式时需要指定的命令或者脚本
spec.containers[].livenessProbe.httpGetObject对 Pod 内各容器健康检查的设置,采用 httpGet 方式,需要指定 path、port
spec.containers[].livenessProbe.tcpSocketObject对 Pod 内各容器健康检查的设置,采用 tcpSocket 方式
spec.containers[].livenessProbe.initialDelaySecondsNumber容器启动完成后首次探测的时间,单位为 s
spec.containers[].livenessProbe.timeoutSecondsNumber对容器进行健康检查等特响应的超时时间设置,单位为 s,默认值为 1s 。若超过该超时时间,则认为容器不健康
spec.containers[].livenessProbe.periodSecondsNumber对容器健康检查的定期检查时间设置,单位为 s ,默认 10s 检查一次
spec.restartPolicyStringPod 的重启策略,可选值为 Always、OnFailure
默认值为 Always。
(1)Always:Pod 一旦终止运行,则无论容器是如何终止的,kubelet都将重启它。
(2)OnFailure:只有Pod 以非零退出码终止时,kubelet 才会重启该容器。如果容器正常结束(退出码为0),kubelet 则不会重启它。
(3) Never:在 Pod 终止后,kubelet 会将退出码报告给 Master,不会再重启该 Pod。
spec.nodeSelectorObject设置 Node 的 Label,以key : value 格式指定,Pod 将被调度到具有这些 Label 的Node上。
spec.imagePullSecretsObject拉取镜像时使用的Secret 名称,以name : secretkey 格式指定。
spec.hostNetworkBoolean是否使用主机网络模式,默认值为 false。设置为”true”时,表示容器使用宿主机网络,不再使用 CNI 网络插件
spec.volumes[]List在该 Pod 中定义的存储卷列表
spec.volumes[].nameString存储卷的名称,在一个Pod 中,每个存储卷都定义了一个名称,命名应符合 RFC 1035 规范。容器定义部分的 spec.containers[].volumeMounts[].name 将引用该共享存储卷的名称。

Volume 的类型包括:
emptyDir、hostPath、
gcePersistentDisk、
awsElasticBlockStore、gitRepo、secret、nfs、 iscsi、glusterfs、persistentVolumeClaim、rbd、flexVolume、
cinder、cephfs、flocker、downwardAPI、fc、azureFile、configMap、
vsphereVolume,可以定义多个 Volume,每个Volume 的 name 都保持唯一。
spec.volumes[].emptyDirObject类型为 emptyDir 的存储卷,表示与 Pod 同生命周期的一个临时目录,其值为一个空对象: emptyDir:{}
spec.volumes[].hostPathObject类型为 hostPath 的存储卷,表示 Pod 容器挂载的宿主机目录,通过 spec.volumes[].hostPath.path 指定
spec.volumes[].hostPath.pathString类型为 hostPath 的存储卷的宿主机目录
spec.volumes[].secretObject类型为 secret 的存储卷,表示挂载集群预定义的 secret 对象到容器内
spec.volumes[].configMapObject类型为 configMap 的存储卷,表示挂载集群预定义的 configMap 资源对象的数据到容器内

2. Pod 的基本用法

Pod 可以由一个或多个容器组成,在下面的示例中,名为“frontend”的 Pod 只由一个容器组成:

# frontend-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: frontend
  labels:
    name: frontend
spec:
  containers:
  - name: frontend
    image: php:8.2-fpm
    ports:
    - containerPort: 80
YAML

另外一种场景是,当 frontend 和 redis 这两个容器应用为紧耦合的关系,并组合为一个整体对外提供服务时,应将这两个容器封装为一个 Pod 。

# frontend-localredis-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: redis-php
  labels:
    name: redis-php
spec:
  containers:
  - name: frontend
    image: php:8.2-fpm
    ports:
    - containerPort: 80
  - name: redis
    image: redis
    ports:
    - containerPort: 6379

# 属于同一个 Pod 的多个容器应用之间在相互访问时仅需通过 localhost 就可以通信
YAML

创建上述两个 pod:

kubectl apply -f frontend-pod.yaml
kubectl apply -f frontend-localredis-pod.yaml
ShellScript

查看已创建的 pod:

kubectl get pods
kubectl get pods -o wide

# 查看 pod 详细信息
kubectl describe pod redis-php
ShellScript

删除 pod:

kubectl delete pod <pod_name>
ShellScript

注意:同一个 pod 内的容器可以共享网络与存储资源。

3. Pod 的类型

pod 的类型分为普通 pod 和静态 pod 两大类,其中普通 pod 又分为裸部署 pod 和被控制器管理的 pod。

  • 普通 pod:创建 pod 的请求是提交给 Api server 的。
    • 裸部署 pod:资源清单里指定的 kind 就是 Pod ,与任何控制器资源都无关,没有自愈等由控制器实现的相关功能。
    • 被控制器管理的 pod:可通过控制器实现自愈或者自己定制的相关功能。
  • 静态 pod:直接通过配置文件或 HTTP 的方式交给 kubelet 创建的 pod ,不通过 API Server 创建。

创建静态 pod 有两种方式:

  • 基于本地配置文件
  • 基于网络上的配置文件

基于本地配置文件

需要在 kubelet 的主配置文件中设置 staticPodPath (在比较旧的 Kubernetes 版本中也可以通过命令行参数 -pod-manifest-pth 进行配置,该命令行参数将被逐渐奔用),指定 kubelet 需要监控的配置文件所在的目录,kubelet 会定期扫描该目录,并根据该目录下的 .yaml 或 json 文件创建静态 Pod。(注意:kubelet 在扫描文件时会忽略以“.”开头的隐藏文件。)
kubelet 的默认 staticPodPath 为 /etc/kubernetes/manifests ,如果想修改为其他路径可修改该字段为 staticPodPath: /xxxx。在配置文件中如果该字段不存在,可以手动添加该字段,后重启  kubelet。

基于网络上的配置文件

基本同上,只需将 staticPodPath 指向一个 URL 路径,例如:staticPodPath: http://example.com/static-pods。

4. Pod 的启动退出流程简述

  • 创建pause基础容器,提供共享名称空间。
  • 串行初始化容器,初始化容器运行成功后运行业务容器。
  • 启动业务容器,启动那一刻会同时运行主容器上定义的 Poststart 钩子事件。
  • startupProbe 健康状态监测,判断容器是否启动成功。
  • 持续健康检测 livenessProbe、readnessProbe。
  • 结束时,在容器结束之前会先执行 Prestop 钩子事件,然后才终止容器。

5. Pod 的生命周期管理

5.1. Pod 运行的各个阶段(Phase)

Phase描述
PendingPod 已被 API Server 接收,但尚未调度或容器未完全启动(如镜像下载中)。
RunningPod 已完成调度到特定 Node,其包含的所有容器均已创建,并且至少有一个容器处于正在运行状态、正在启动状态或正在重启状态。
SucceededPod 中的所有容器已成功完成任务并退出。这通常发生在执行一次性任务或作业后,所有容器成功完成并退出。
FailedPod 内的所有容器均已终止,但至少有一个容器在运行过程中发生了错误或异常。
Unknown由于某种原因无法获得 Pod 的状态,原因可能是从 Master 到 Pod 所在 Node 网络通信失败。

Pod 在创建之后,首先进入 Pending 阶段;然后等到至少一个容器正常启动就进入 Running 阶段;如果全部容器都运行完成并成功结束,则进人 Succeeded 阶段;如果有部分容器运行失败,则进人 Failed 阶段。在 Pod 生命周期内的各个阶段,Kubernetes 会持续监控其中每个容器的状态,并根据重启策略和健康检查策略进行相应操作。

5.2. Pod 的各种状态(Conditions)

Conditions 是一组更细粒度的状态,描述 Pod 是否满足某些关键条件。每个条件包含:

  • type(类型)
  • statusTrue/False/Unknown
  • lastProbeTime(上一次探测 Pod 状态的时间戳)
  • lastTransitionTime(Pod 从上一个状态转换到当前状态的时间戳)
  • reason(原因)
  • message(详细信息)

常见的条件类型:

Condition Type描述
PodScheduledPod 是否已被调度到节点(status=True 表示已调度)。
PodReadyToStartContainersPod 已创建并且完成网络配置,可以启动容器。该特性从 v1.25 开始引入。
Initialized所有 Init 容器 是否成功完成(status=True 表示初始化完成)。
ContainersReady所有容器是否通过就绪探测(status=True 表示容器就绪)。
ReadyPod 是否可提供服务(通常用于 Service 流量路由)。

查看 Pod 状态示例:

kubectl -n kube-flannel get pod kube-flannel-ds-956vj -o yaml

apiVersion: v1
kind: Pod
...
status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: "2025-08-06T00:20:49Z"
    status: "True"
    type: PodReadyToStartContainers
  - lastProbeTime: null
    lastTransitionTime: "2025-07-14T02:08:31Z"
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: "2025-08-06T00:21:02Z"
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: "2025-08-06T00:21:02Z"
    status: "True"
    type: ContainersReady
  - lastProbeTime: null
    lastTransitionTime: "2025-07-14T02:07:40Z"
    status: "True"
    type: PodScheduled
Bash

5.3. 容器的状态(ContainerStatuses)

ContainerStatuses 描述 Pod 中每个容器的详细状态,包括:

  • state:容器的当前状态(WaitingRunning 或 Terminated)。
    • Waiting(等待中),容器尚未启动,可能原因:
      • ImagePullBackOff:镜像拉取失败。
      • CrashLoopBackOff:容器崩溃后等待重启。
      • ContainerCreating:容器正在创建(如挂载卷未就绪)。
    • Running(运行中),容器正在运行。
    • Terminated(已终止),表示容器运行结束。
  • lastState:容器上一次的状态(用于排查崩溃或重启问题)。
  • restartCount:容器重启次数。

可通过 kubectl describe pod <pod_name> 命令查看容器详细信息。

5.4. Events(事件)

Events 记录 Pod 生命周期中的关键事件(如调度失败、镜像拉取错误等),可通过 kubectl describe pod <pod-name> 查看:

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  10s   default-scheduler  Successfully assigned default/mypod to node-1
  Normal  Pulling    8s    kubelet            Pulling image "nginx"
  Warning Failed     5s    kubelet            Failed to pull image "nginx:404"
Bash

常见事件:

  • Scheduled:Pod 已调度到节点。
  • Pulling/Pulled:拉取镜像中/成功。
  • Created/Started:容器创建/启动。
  • Failed/BackOff:容器启动失败或崩溃。
  • Evicted:表示 Pod 被驱逐(Evicted)或驱逐出节点。当 Pod 被驱逐时,它的状态会变为 “Evicted”,这通常发生在节点资源不足或节点发生故障时。
  • OOMkilled:在 Kubernetes 中,如果一个容器被 OOM Killer 终止,容器的状态会被标记为 “OOMkilled”。
    • 系统级别的 OOM:系统内存不足,杀进程的范围是系统中所有的进程。
    • k8s 级别的 OOM:针对某个 Pod,该 pod 的容器对内存的使用达到 limits 的限定。

5.5. Pod 的重启策略

Pod 的重启策略应用于 Pod 内所有容器,并且仅在 Pod 所处的 Node 上由 kubelet 进行判断和重启操作。Pod 的重启策略包括 Always、OnFailure 和 Never,默认为 Always。

  • Always:当容器失效时,由 kubelet 自动重启该容器。
  • OnFailure:当容器终止运行且退出码不为0时,由 kubelet 自动重启该容器。
  • Never:不论容器处于哪种运行状态,kubelet 都不会重启该容器。

Pod 的重启策略与控制方式息息相关,控制器对 Pod 的重启策略要求如下:

  • Deployment、ReplicationController (RC)、DaemonSet 和 StatefulSet:必须被设置为“Always”,需要保证该容器持续运行。
  • Job:OnFailure 或 Never,确保容器执行完成后不再重启。
  • 静态 pod:不允许设置 estartPolicy,在静态 pod 失效是会由 kubelet 自动重启。

5.6. Pod 终止和垃圾清理

在 Kubernetes 中,Pod 的终止和垃圾清理是一个系统化的过程,涉及优雅终止(Graceful Termination)、资源释放、垃圾回收机制等。

Pod 的终止流程

  • 触发终止
    • 用户删除:通过 kubectl delete pod 或 API 请求删除。
    • 系统驱逐:因资源不足、节点维护等被 kubelet 驱逐。
    • 优先级抢占:高优先级 Pod 抢占低优先级 Pod 的资源。
  • 优雅终止(Graceful Termination)
    • API Server 标记 Pod 为“Terminating”。
    • kubelet 探测到 Pod 状态为“Terminating”则向容器发送 SIGTERM 信号。
      • 默认等待时间:30 秒(可通过 spec.terminationGracePeriodSeconds 修改)。
    • 强制终止
      • 如果容器在优雅终止期内未退出,kubelet 发送 SIGKILL 强制终止。
    • 清理容器和网络资源
      • 删除容器运行时(Docker/Containerd)中的容器实例。
      • 释放 Pod 占用的网络接口(如 CNI 插件管理的 IP 地址)。

垃圾回收(Garbage Collection)

  • 垃圾回收类型
资源类型回收机制
终止的 Podkubelet 定期清理 Failed/Succeeded 状态的 Pod(需手动或配置自动清理)。
悬挂的镜像kubelet 根据磁盘压力自动清理未使用的容器镜像(通过 image-gc-high-threshold 配置)。
停止的容器kubelet 清理已退出的容器(通过 --container-gc-threshold 控制保留数量)。
Evicted Pod需手动清理或通过脚本定期删除(如 kubectl delete pods --field-selector=status.phase=Failed)。
  • 配置示例
# kubelet 参数(通常在 /var/lib/kubelet/config.yaml 中配置)
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
evictionHard:
  memory.available: "500Mi"
  nodefs.available: "10%"
imageGCHighThresholdPercent: 85  # 磁盘使用率超过 85% 时触发镜像清理
containerGCHighThreshold: 80     # 保留最多 80 个停止的容器
YAML

6. 容器的探针和健康检查机制

容器探针(Probe)是Kubernetes中用于检测容器健康状况的机制,它通过定期执行诊断来评估容器的运行状态。

6.1. 探针类型

  • Liveness Probe (存活探针)
    • 作用:检测容器是否正在运行。
    • 失败后果:kubelet 会杀死容器并根据重启策略决定是否重启。如果未配置该探针,则 kubelet 会认为探针返回的值永远为 Success。
  • Readiness Probe (就绪探针)
    • 作用:检测容器服务是否处于 Ready 状态,只有处于 Ready 状态的 Pod 才能接收请求。
    • 失败后果:从 Service 的端点列表中移除该 Pod,停止向其发送流量。就绪探针也是定期触发的,存在于整个 Pod 生命周期。如果未配置该探针,则 kubelet 会认为探针返回的值永远为 Success。
  • Startup Probe (启动探针)
    • 作用:检测容器应用是否已启动。
    • 失败后果:在启动探针成功前,其他探针不会执行,如果启动探针检测失败,kubelet 会杀死容器并根据重启策略决定是否重启。如果未配置该探针,则 kubelet 会认为探针返回的值永远为 Success。

6.2. 探针检查方式

上述三种探针都可以配置以下几种检查方式:

  • exec:在容器内执行指定命令,返回0表示成功。
  • tcpSocket:对指定端口进行 TCP 检查,如果能建立 TCP 连接表示成功。
  • httpGet:对指定路径和端口发送HTTP GET请求,状态码2xx或3xx表示成功。

每种探针都可以配置如下字段:

  • initialDelaySeconds:容器启动后等待多少秒开始探测,默认值为 0,最小值为 0。
  • periodSeconds:执行探测的频率(秒),默认值为 10,最小值为 1。
  • timeoutSeconds:探测超时时间(秒),当发生超时时则认为探针失败。默认值为 1,最小值为 1。
  • successThreshold:探测连续成功多少次才认为成功,默认值为 1,最小值为 1。LivenessProbeStartupProbe 该值必须被设置为 1。
  • failureThreshold:探测连续失败多少次才认为失败,默认值为 3,最小值为 1。

配置示例:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: my-app:v1
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: X-Custom-Header
          value: Awesome
      initialDelaySeconds: 15
      periodSeconds: 20
      timeoutSeconds: 1
      failureThreshold: 3
    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/ready
      initialDelaySeconds: 5
      periodSeconds: 5
    startupProbe:
      httpGet:
        path: /healthz
        port: 8080
      # 在下面的配置中,探测时间间隔 periodSeconds 被设置为 10s,失败次数 failureThreshold 被设置为 30 次,表示允许容器在 300s 内完成启动。这通常用来保护需要启动时间很长的容器。如果容器在 300s 后仍未启动,则探测启动失败,kubelet 会杀掉该容器,并根据重启策略决定是否重启。
      failureThreshold: 30
      periodSeconds: 10
YAML

7. Pause 容器

Pause容器(Pause Container)是 Kubernetes 集群中一个特殊的辅助容器,主要用于为 Pod 提供共享的基础设施(如网络命名空间)。

核心功能

  • 共享网络命名空间:Pod中的多个容器共享同一个网络栈(相同的IP和端口空间),这是通过Pause容器实现的。Pause容器启动后,会创建网络命名空间,其他容器通过Join方式共享该空间,使它们可以通过localhost直接通信。
  • 充当PID 1进程:在Linux中,PID 1进程负责管理孤儿进程并避免僵尸进程。Pause容器作为Pod的“根容器”(PID 1),确保其他容器进程被正确回收。

使用 Pause 容器的优点

  • 解耦Pod生命周期与业务容器:如果业务容器崩溃重启,Pod的网络命名空间不会因此销毁(因为Pause容器仍在运行),确保Pod网络稳定性。
  • 简化设计:通过一个轻量级、稳定的中间层管理共享资源,避免每个容器重复实现命名空间逻辑。

结构示例

一个包含Nginx和Sidecar容器的Pod,实际结构如下:

Pod (IP: 10.1.0.3)

├── Pause容器(维护网络命名空间)
├── Nginx容器(共享Pause容器的网络)
└── Sidecar容器(共享Pause容器的网络)
TeX

Nginx和Sidecar通过localhost直接通信,因为它们在同一个网络命名空间中。

查看 Pause 容器

  • 执行kubectl describe pod <pod-name>时,可以看到 Pause 容器的信息。通过容器运行时管理工具也能查看到它(名称包含pause)。

8. Init 容器

8.1. Init 容器概述

初始化容器(Init Container)是在Pod的主容器启动之前运行的专用容器,用于执行初始化任务。它们与常规容器类似,但具有以下特点:

  • 先于应用容器启动:必须成功完成才会启动主容器。
  • 顺序执行:按照定义的顺序依次运行,并且只有前一个初始化容器运行成功才会运行行一个初始化容器。
  • 一次性:运行完成后即终止,不会持续运行。不支持健康检查机制,应为必须在初始化容器运行成功后才能启动普通容器。

系统会在 Pod 的状态信息的 initContainerStatuses 字段中显示初始化容器的运行状态信息。

8.2. Init 容器使用场景

在很多应用场景中,应用容器在启动之前都可能需要进行一些初始化操作,例如:

  • 等待其他关联组件正确运行(例如数据库或某个后台服务)。
  • 预先基于环境变量或配置模板生成应用所需的配置文件。
  • 从远程数据库中获取本地所需配置,或者将自身注册到某个中央数据库中。
  • 下载相关依赖包,或者对系统进行一些预配置操作。
  • 以更高的权限调整内核参数。

8.3. Init 容器基本配置示例

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
YAML

在初始化容器中也可以设置资源限制、Volume 等等。但对资源限制的设置与应用容器略有不同,如下所述:

  • 如果有多个初始化容器定义了资源请求或资源限制,则取最大的值作为所有初如化容器的资源请求值或资源限制值。
  • Pod 的有效(effective)资源请求值或资源限制值取以下二者中的较大值:①所有应用容器的资源请求值或资源限制值之和;②初始化容器的有效资源请求值或资源限制值。
  • 初始化容器终止后,其请求(request)和限制(limit)的CPU、内存资源会立即释放,只有应用容器的资源需求会被计入Pod的总资源需求。所以调度器在分配节点时,会考虑所有初始化容器和应用容器的资源请求中的最大值(即有效值),但运行后只保留常规容器的资源占用。

8.4. 将初始化容器作为长时间运行的边车容器

9. 钩子函数

9.1. 基本概念

PostStart 和 PreStop 是 Kubernetes 为容器提供的两种生命周期钩子(Lifecycle Hooks),允许在容器生命周期的特定时刻执行自定义操作。

对比概览:

特性PostStartPreStop
触发时机容器启动后立即执行(异步运行)容器终止前执行
主要用途初始化配置、服务注册优雅关闭、服务注销
执行保证不保证在ENTRYPOINT前完成保证在容器终止前完成
失败影响容器会被杀死,并根据RestartPolicy决定是否重启。如果钩子运行失败,也会强制删除 Pod

注意:如果一些初始化工作一定要在业务容器运行前运行,那就用 initcontainers 来执行,如果这些初始化工作没有要求必须在业务容器运行前运行,则可以使用 PostStart 来执行。

9.2. PostStart 钩子

配置方式:

# 示例1:Exec方式(执行命令)
lifecycle:
  postStart:
    exec:
      command:
        - "/bin/sh"
        - "-c"
        - "echo 'Container started' > /tmp/start.log"
        
# 示例2:HTTP方式(发送请求)
lifecycle:
  postStart:
    httpGet:
      path: /initialize
      port: 8080
      httpHeaders:
      - name: X-Custom-Header
        value: Initialization
YAML

9.3. PreStop 钩子

配置方式

# 示例1:Exec方式
lifecycle:
  preStop:
    exec:
      command:
        - "/bin/sh"
        - "-c"
        - "sleep 10 && nginx -s quit"
        
# 示例2:HTTP方式
lifecycle:
  preStop:
    httpGet:
      path: /graceful-shutdown
      port: 8080
YAML

注意:当 Pod 开始终止时,Kubernetes 会执行 preStop 钩子。钩子有一个超时时间(默认为 30 秒,可通过 terminationGracePeriodSeconds 调整)。如果钩子在超时时间内没有成功完成,Kubernetes 会终止 Pod,而不再继续等待钩子完成。

9.3. 完整配置示例

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: main-container
    image: nginx:1.19
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo 'Start at $(date)' >> /var/log/lifecycle.log"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "nginx -s quit; echo 'Stop at $(date)' >> /var/log/lifecycle.log"]
    volumeMounts:
    - name: logs
      mountPath: /var/log
  volumes:
  - name: logs
    emptyDir: {}
YAML

10. 在容器内获取 Pod 信息

上一篇
下一篇