想要了解工作负载,必须知道工作负载工作的对象--Pod,我们先介绍Pod。

一、Pod是什么?

1.1先明确定位:Pod是K8s的最小“最小调度单元”,不是容器

很多人会把Pod和容器搞混,但关键区别在于:K8s不会直接调度容器,所有容器都必须“装在Pod里”,K8s只对Pod进行调度(比如分配到那个节点运行)

结合图可理解: 可以把Pod形象地比作一个“豌豆荚”,里面的每颗“豆子”就是容器。就像同一个豌豆荚里的豆子会共享土壤中的养分、水分和阳光,Pod里的所有容器也会共享这个Pod的核心资源——包括唯一的网络空间(Pod IP)和挂载的存储卷,彼此协同又依赖,形成一个不可拆分的资源使用与调度单元。

1.2 再看结构:Pod是“容器的封装体”,支持单容器或多容器

Pod的结构有两种常见形态,核心是“容器的组合逻辑”:

a.单容器Pod:最主流形态,一个Pod路只装一个业务容器。

b.多容器Pod:一个Pod里装多个“紧密协作”的容器,这些容器共享资源。比如“业务容器(运行Web服务)+Sidecar容器(收集该Web服务的日志)”--日志容器必须和业务容器在同一节点、共享日志目录,拆成两个Pod会导致日志收集失败,这时就需要放在一个Pod里。

1.3 Pod 对多容器的管理逻辑及核心特性解析

这是Pod最关键的设计逻辑,也是多容器Pod能协作的基础:

1.3.1 Pod 中的特殊容器类型:Init 容器 —— 应用容器启动前的 “初始化助手”

除了常规的应用容器,Pod 还支持 Init 容器,专门用于 “在应用容器启动前完成初始化操作”,进一步完善多容器管理的功能性:

  1. 运行时机:Init 容器会在所有应用容器启动前按定义顺序依次运行,且必须全部成功执行(若某 Init 容器失败,Pod 会重启直到 Init 容器成功),确保应用容器启动时已满足依赖条件。
  2. 典型用途:解决应用容器启动前的 “前置依赖问题”,比如:
    • 等待其他服务就绪(如 Init 容器循环检测 MySQL 服务的 IP 和端口,直到能连通再退出,避免应用容器启动后因无法连接数据库报错);
    • 初始化配置文件(如 Init 容器从配置中心拉取应用配置,写入 Volume,应用容器启动后直接从 Volume 读取配置);
    • 权限初始化(如 Init 容器为应用容器所需的存储目录设置权限,避免应用容器因权限不足无法写入数据)。
  3. 与应用容器的差异:Init 容器不支持 “重启策略”(失败后仅通过 Pod 重启重试),且资源配置独立于应用容器,不会占用应用容器的资源限额。

1.3.2 支撑多容器协作的核心特性:网络与存储的 “共享机制”

Pod 的网络与存储特性是多容器能够高效协作的关键支撑,确保容器间 “能通信、能传数据”:

  1. 网络共享:localhost互通 + 集群内可达
    • 内部通信:Pod 内所有容器共享同一个网络命名空间,拥有唯一的 Pod IP,容器间可通过 “localhost+ 端口” 直接通信(如 Web 容器监听localhost:8080,Sidecar 容器通过localhost:8080获取 Web 容器的监控数据),无需跨网络,延迟极低;
    • 外部通信:Pod IP 由 Calico、Flannel 等 CNI 插件分配,且在集群内唯一,Pod 内的容器可通过 Pod IP 与其他节点的 Pod 通信,实现跨节点的多容器协作(如 A 节点 Pod 的应用容器与 B 节点 Pod 的数据库容器通信)。
  2. 存储共享:Volume—— 多容器的数据 “中转站”
    • 数据共享:通过给 Pod 挂载 Volume(如 emptyDir、PVC),所有容器可读写 Volume 内的文件,实现数据互通(如日志收集场景:应用容器将日志写入 Volume,Sidecar 容器从同一个 Volume 读取日志并上传到日志平台);
    • 数据持久化:若挂载的是 PVC 等持久化 Volume,即使 Pod 重启或容器重建,Volume 内的数据也不会丢失,确保多容器协作过程中数据的连续性(如数据库 Pod 中,Init 容器初始化数据库配置到 PVC,应用容器从 PVC 读取配置并写入数据,Pod 重启后数据仍保留)。

1.3.3 Pod 管理多容器的核心逻辑:“同节点、同生命周期、按需共享”

Pod 管理多个容器的核心原则是 “仅用于紧密协作的场景”,避免无关联容器混装,具体管理方式体现在三个维度:

  1. 调度一致性:K8s 会将 Pod 内所有容器作为 “一个整体” 调度到同一节点,不会出现 “Pod 内容器分散在不同节点” 的情况 —— 确保容器间无需跨节点通信,减少网络延迟,为紧密协作奠定基础(如 Sidecar 容器需实时读取业务容器日志,必须同节点部署)。
  2. 生命周期绑定:Pod 的生命周期(创建、启动、停止、删除)会同步到所有内部容器 —— 当 Pod 启动时,所有容器按配置顺序启动;当 Pod 被删除或故障重启时,里面的所有容器会被同时停止、重新启动,不会出现 “Pod 存在但部分容器缺失” 的情况,保障协作的完整性。
  3. 资源按需共享:Pod 不会强制容器共享所有资源,而是允许用户按需配置 “共享范围”—— 可通过 Volume 让容器共享存储(如业务容器写数据到 Volume,分析容器从 Volume 读数据),也可通过默认的网络共享让容器互通,但 CPU、内存等计算资源需为每个容器单独配置限额,避免单个容器过度占用资源影响其他容器。

注:后面会说Pod的网络模型及如何通信,及Volume(K8S存储卷)。

1.4 通俗类比:把Pod看作“轻量级虚拟机”,容器是“虚拟机里的进程”

如果觉得抽象,用“虚拟机”类比会更容易理解:

  • 传统场景:我们在虚拟机里运行多个进程(比如 Web 进程、日志进程),进程间共享虚拟机的 IP 和磁盘。

  • K8s 场景:Pod 就像 “轻量级虚拟机”(比真实虚拟机资源开销小得多),Pod 内的容器就像 “虚拟机里的进程”—— 容器间共享 Pod 的 IP(对应虚拟机 IP)和 Volume(对应虚拟机磁盘),且同属一个 “资源单元”。

  • Pod与容器之间的关系看作,Pod是容器的二次封装!

二、Pod工作方式及创建流程详解

一、Pod的创建方式

在K8s中,创建Pod主要有两种方式:

1.命令行直接创建(不常用)

使用Kubectl run命令可快速创建Pod:

kubectl run nginx1 -- image="docekr.io/library/nginx:latest" --image-pull-policy="IfNotpresent"

2.通过YAML配置文件创建(推荐)

所有K8s资源都通过YAML文件定义,Pod也不例外,这种方式更便于版本控制和配置管理。

二、自主式Pod

自主式Pod是指直接定义的Pod资源,不通过控制器管理。

1.定义示例

apiVersion:v1 #api版本
kind:Pod      #创建的资源
metadata:
  name:tomcat-test
  namespace:default  #Pod所在的命名空间
  lables:
    app:tomcat       #Pod具有的标签
spec:
  container:
  - name:tomcat-java  #Pod里容器的名字
    ports:
    - containerPort:8080  #容器暴露的端口
    image: docker.io/library/tomcat:8.5-jre8-apline  #容器使用的镜像
    imagePullPolicy:IfNotPresent #镜像拉取策略

注:常见的API版本类型及示例如下

1.核心版本(core group):以v1表示,是Kubernetes最早最早的核心API版本,包含最基础的资源,如Pod、Service、Namespace、ConfigMap、Secret、Node等。

2.应用版本(apps group):包含与应用部署相关的资源,如Depolyment、ReplicaSet、StatefulSet、DaemonSet等,常见版本有apps/v1。

3.批处理版本(batch group):包含与任务调度相关的资源,如Job、CronJob等,常见版本有batch/v1beta1(部分旧版本)。

4.网络版本(networking.k8s.io goup):包含网络相关资源,如Ingress、NetworkPolicy等,常见版本networking.k8s.io/v1.

5.存储版本(storage.k8s.io group):包含存储相关资源,如StorageClass、CSIDriver等,常见版本有storage.k8s.io/v1。

2.操作流程

准备镜像:将所需镜像(如tomcat.tar.gz)上传到节点并加载

docker load -i tomcat.tar.gz

创建Pod:

kubectl apply -f pod-tomcat.yaml

查看Pod状态:

kubectl get pods -o wide -l app=tomcat

暴露Pod到集群外(临时访问):

kubectl port-forward --address 0.0.0.0 tomcat-test 8888:8080

3.缺点

自主式Pod存在明显缺陷:当Pod被删除后,不会自动创建,在生产环境中存在较大风险,因此实际应用中通常使用控制器管理Pod。

三、控制器管理的Pod

生产环境中,Pod通常由各种控制器管理,常见的控制器包括:

  • Replicaset
  • Deployment
  • Job
  • CronJob
  • Daemonset
  • Statefulset

控制器可以确保Pod始终维持在期望状态,如自动重建故障或被删除的Pod。

注:工作负载后续介绍,考虑到Pod是最小调度单元,必须弄清楚后,工作负载会更容易理解!

四、Pod 创建完整流程

1.提交请求:客户端通过Kubectl 命令或直接调用API Server的Rest API 接口提交创建Pod的请求(kubectl apply -f filename.yaml)

2.存储元数据:API Server接收到请求后,将Pod的元数据信息写入etcd数据库

3.调度过程:

  • API Server 通过 watch 机制通知调度器(scheduler)有新的 Pod 需要创建
  • 调度器使用调度算法筛选合适的节点(过滤掉资源不足等不符合要求的节点)
  • 调度器将选中的节点信息返回给API Server
  • API Server将Pod与节点的绑定信息写入etcd

4.创建容器:

  • API Server 通过 watch机制(长连接)通知目标节点的kubelet有Pod需要创建
  • kubelet调用容器运行时接口(CRI)初始化容器环境,创建并启动Pod内的容器

5.状态反馈:

  • 容器创建完成后,kubelet 将 Pod 的状态信息反馈给 API Server
  • API Server 将 Pod 的状态信息更新到 etcd 中

五、Pod常见的状态和重启策略

1.常见的Pod状态

 Pod的status定义在PodStatus对象中,其中有一个phase字段。它简单描述了Pod在器生命周期的阶段。熟悉Pod的各种状态对我们理解如何设置Pod调度策略、重启策略是很重要的。如下便是Pod常见的状态:

挂起(Pending)

含义:Pod已被API Server创建,但尚未被调度到任何节点,或正在下载镜像

常见原因:

    • 没有节点满足 Pod 的资源需求(如 CPU / 内存不足)

    • 节点亲和性规则不匹配

    • 镜像下载缓慢或镜像仓库不可访问

  • 持续时间:包括调度时间和镜像下载时间,视网络和资源情况而定

运行中(runing)

含义:Pod已绑定到某个节点,所有容器都已创建,至少有一个容器处于运行中、重启或启动状态

标志:READY字段显示“1/1”或类似状态,表示至少有一个容器就绪。

成功(Succeeded)

含义:Pod中所有容器都已成功终止,且不会再重启

典型场景:一次性任务完成(如Job创建的Pod)

失败(Failed)

含义:Pod中所有容器都已终止,且至少有一个容器是异常终止的

判断标准:容器以非0状态退出或被系统强制终止

未知(Unknown)

含义:API Server无法获取Pod的状态信息

常见原因:Pod所在节点的kubelet与API Server通信中断(如节点故障、网络问题)

CrashLoopBackOff

含义:容器曾经启动成功,但随后异常退出,且处于反复重启的循环中

常见原因:

  • 应用程序存在 bug 导致崩溃

  • 健康检查失败

  • 资源不足

  • 排查:查看容器日志(kubectl logs <pod-name>)分析退出原因

Error

  • 含义:Pod 启动过程中发生错误

  • 常见原因:
    • 镜像不存在

    • 容器启动命令错误

    • 权限问题

2. Pod重启策略决定了容器异常时kubectl的处理方式,与Pod状态密切相关:

  1. Always(默认)

    • 行为:当容器失败时,kubelet 自动重启该容器

    • 适用场景:长期运行的服务(如 Web 服务器、数据库)

    • 与状态关系:若容器持续失败,Pod 可能会在 Running 和 CrashLoopBackOff 状态间切换

  2. OnFailure

    • 行为:当容器终止且退出码不为 0 时,kubelet 自动重启该容器

    • 适用场景:需要完成但可能失败的任务

    • 与状态关系:正常完成(退出码 0)后进入 Succeeded 状态,失败则重启

  3. Never

    • 行为:无论容器运行状态如何,kubelet 都不会重启该容器

    • 适用场景:一次性任务,不需要重试

    • 与状态关系:容器终止后保持 Terminated 状态,可能是 Succeeded 或 Failed

3.状态与重启策略的关联实例

  1. Web 服务 Pod

    • 配置:restartPolicy: Always
    • 状态流转:Pending → Running(正常运行)
    • 异常情况:若服务崩溃,会自动重启,状态短暂变为 Running(重启中),若持续失败则进入 CrashLoopBackOff
  2. 数据处理 Job

    • 配置:restartPolicy: OnFailure
    • 状态流转:Pending → Running → Succeeded(处理成功)
    • 异常情况:若处理失败,容器会重启,状态保持 Running,最终可能 Failed(多次失败后)
  3. 初始化脚本 Pod

    • 配置:restartPolicy: Never
    • 状态流转:Pending → Running → Succeeded(脚本执行成功)
    • 异常情况:脚本执行失败后直接进入 Failed 状态,不会重启

六、Pod生命周期之 Init 容器:主容器启动前的 “初始化助手”

在Pod的完整生命周期中,Init容器扮演着“前置准备”的关键角色。它先于主容器启动并完成初始化工作是保障主容器顺利运行的重要机制;所有 Init 容器按序执行完毕后,主容器才启动。

6.1 Init 容器的核心定义与运行逻辑

Init容器是Pod中先于主容器启动的专用容器,专门用于执行初始化任务,其核心特性可概括为“三先特性”:

  • 启动时机优先:在所有主容器启动前运行,且必须全部成功执行完毕,主容器才会启动(类似程序中的 “前置初始化函数”)。

  • 执行逻辑特殊
    • 一旦初始化任务完成(如脚本执行结束、依赖检查通过),Init 容器会自动退出(生命周期短暂,不长期运行);

    • 若存在多个 Init 容器,将按定义顺序串行执行(先执行第一个,成功后再执行第二个,以此类推),而非并行。

  • 资源共享特性:与主容器共享 Pod 的存储卷(Volume)和网络命名空间,因此 Init 容器生成的数据(如配置文件、证书)可直接被主容器读取。

6.2 主容器

主容器启动与停止阶段,可通过postStart(启动后钩子) 和preStop(停止前钩子) 两类容器钩子,自定义执行初始化或清理操作,灵活适配业务对容器生命周期的精细控制需求:

一、postStart:容器启动后的 “即时触发钩子”

  • 触发时机:主容器创建完成后立刻执行,无需等待容器内进程就绪。

  • 核心作用:执行容器启动后的初始化操作,如配置文件补全、注册实例到服务发现平台等。

  • 失败影响:若钩子执行失败(如命令报错),主容器会被杀死,后续是否重启由 Pod 的restartPolicy决定(如Always策略下会重启容器重试)。

  • 特性:无需传递参数,钩子执行不阻塞容器内业务进程启动(即业务进程与钩子可并行执行)。

二、preStop:容器停止前的 “收尾钩子”

  • 触发时机:容器被删除前触发,钩子执行完成后,K8s 才会向 Docker daemon 发送删除容器的信号。

  • 核心作用:执行容器停止前的清理操作,如关闭数据库连接、释放占用资源、通知上下游服务 “实例下线” 等,避免业务数据丢失或服务中断。

  • 执行保障:无论钩子执行成功与否,最终都会执行容器删除操作,但钩子会阻塞删除流程,确保收尾逻辑完成。

  • 特性:无需传递参数,适用于需要 “优雅停机” 的场景(如 Java 服务通过钩子执行shutdown命令,释放 JVM 资源)。

6.3 Init 容器与主容器的关键差异

Init 容器作为 Pod 启动阶段的 “前置初始化单元”,在特性上与主容器存在显著差异。它不支持就绪探针(Readiness Probe),无需判断 “是否就绪”,只需完成初始化任务后成功退出即可;运行时长较短,一旦初始化逻辑(如等待依赖、生成配置)执行完毕便自动终止,且多个 Init 容器需按定义顺序串行执行,只有全部完成后,主容器才会启动。在异常处理上,若 Init 容器执行失败,Kubernetes 会重启 Pod 直至其成功(仅当 restartPolicy 设为 Never 时才停止重试),确保主容器启动前的初始化条件完全满足。

主容器则是 Pod 中承担核心业务服务的单元,特性更贴合长期运行需求。它支持配置就绪探针,用于判断容器是否具备接收请求的能力,保障服务可用性;运行时长通常较长,会持续提供业务服务,直至出现异常或被主动终止,且多个主容器可并行启动,无严格顺序限制。其重启逻辑完全受 Pod 的 restartPolicy 控制,例如在 Always 策略下,主容器一旦失败便会被重启,OnFailure 策略下仅在异常退出时重启,Never 策略下则永不重启,灵活适配不同业务的稳定性需求。

6.4 Kubernetes Pod 的两类核心探测:存活性(Liveness Probe)与就绪性(Readiness Probe)

在 K8s 中,Liveness Probe(存活性探测)和 Readiness Probe(就绪性探测)是保障 Pod 运行稳定性与服务可用性的关键机制,二者针对容器生命周期的不同阶段发挥作用,核心目标与执行逻辑存在明确差异:

一、Liveness Probe(存活性探测):判断容器 “是否存活”,决定是否重启

  • 核心作用:检测 Pod 内容器的应用进程是否正常运行,识别 “存活但不可用” 的容器(如进程死锁、服务卡死),确保容器始终处于可正常工作的状态。

  • 探测结果影响
    • 若探测成功:判定容器健康,不执行任何操作;

    • 若探测失败:判定容器不健康,Kubelet 会根据 Pod 的restartPolicy(如 Always、OnFailure)决定是否重启容器(无特殊配置时默认重启)。

  • 特殊规则:若容器未配置 Liveness Probe,K8s 会默认判定存活探测 “始终成功”,即使容器内应用异常,也不会主动重启。

二、Readiness Probe(就绪性探测):判断容器 “是否就绪”,决定是否对外提供服务

  • 核心作用:检测容器内的应用是否完成启动(如初始化配置加载、依赖服务连接成功),确保只有 “完全就绪” 的容器才接收外部流量,避免将请求转发到未准备好的应用。

  • 探测结果影响
    • 若探测成功:将容器的Ready状态设为true,Pod 会被加入 Service 的 Endpoint 列表,对外提供服务;

    • 若探测失败:将容器的Ready状态设为false,Pod 会从 Service 的 Endpoint 列表中移除,外部流量不再转发至该容器(容器仍存活,不会重启)。

  • 典型场景:适用于启动耗时较长的应用(如 Spring Boot 服务加载配置、初始化数据库连接),避免启动过程中接收请求导致报错。

三、探针的三种探测方法:Exec、TCP、HTTP

LivenessProbe(存活性探测)和 ReadinessProbe(就绪性探测)均支持三种探测方式,可根据应用特性选择合适的检测逻辑:

1. ExecAction:命令执行检测

  • 原理:在容器内执行指定命令,通过命令退出码判断状态(退出码为 0 则探测成功,非 0 则失败)。

  • 适用场景:需执行复杂逻辑判断的场景,如检查文件是否存在、配置是否正确等。

  • 示例:检测 /tmp/healthy 文件是否存在,存在则判定健康:

  • livenessProbe:
      exec:
        command: ["test", "-f", "/tmp/healthy"]

2. TCPSocketAction:TCP 连接检测

  • 原理:通过容器的 IP 和端口尝试建立 TCP 连接,若连接成功则探测成功,失败则判定异常。

  • 适用场景:任何基于 TCP 的服务(如数据库、Redis、SSH 服务),无需依赖应用层逻辑。

  • 示例:检测容器的 8080 端口是否能建立 TCP 连接:

  • readinessProbe:
      tcpSocket:
        port: 8080

3. HTTPGetAction:HTTP 请求检测

  • 原理:向容器的 IP、端口及指定路径发送 HTTP GET 请求,若响应状态码在 200~399 之间则探测成功。

  • 适用场景:Web 应用、API 服务等 HTTP 协议的服务,可直接检测业务接口状态。

  • 示例:检测 /health 路径的 HTTP 响应是否正常:

  • livenessProbe:
      httpGet:
        path: /health
        port: 8080

三种方法各有侧重:Exec 适合自定义逻辑,TCP 适合底层连通性检测,HTTP 适合 Web 服务的应用层健康检查,可根据探针类型(存活 / 就绪)和业务需求灵活组合使用。

4. 探针探测结果有以下值:

1Success:表示通过检测。

2Failure:表示未通过检测。

3Unknown:表示检测没有正常进行。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐