前言

在 Kubernetes(K8s)的世界里,Pod 是最基础也是最核心的存在 —— 它是 K8s 集群中最小的部署单元,就像一个 “容器公寓”,能容纳一个或多个紧密协作的容器,让它们共享资源、协同工作。无论是新手入门还是老手进阶,吃透 Pod 的原理与用法,都是掌握 K8s 运维和开发的关键。本文将从基础概念到进阶实战,全面拆解 Pod 的核心知识点,附带详细命令解释和实用补充,让你轻松玩转 Pod。

一、Pod 基础:是什么?为什么存在?

1. 核心定义:最小部署单元的本质

Pod 不是容器,而是容器的 “逻辑宿主”—— 它是 K8s 中唯一能被直接部署、调度的最小单元,代表集群中的一个运行进程。一个 Pod 可以包含:

  • 1 个或多个紧密耦合的用户容器(应用容器);
  • 1 个特殊的基础容器(Pause 容器),由 K8s 自动创建,对用户透明。

关键特性

  • 共享网络:Pod 会被分配一个唯一 IP,内部所有容器共享这个 IP 和端口,可通过 localhost 直接通信;
  • 共享存储:Pod 可挂载多个 Volume(存储卷),所有容器都能访问,实现数据持久化(容器重启后数据不丢失);
  • 短暂性:Pod 是临时实体,生命周期有限,故障后默认不会自愈(需依赖控制器管理)。

2. 为什么需要 Pod?而非直接部署容器?

K8s 不直接管理容器,而是通过 Pod 封装容器,核心原因有 3 点:

  • 解决 “紧密协作” 问题:有些应用需要多个容器配合(如应用容器 + 日志收集容器),Pod 让它们共享资源、协同调度,避免分散部署导致的通信和依赖问题;
  • 统一资源管理:Pod 作为资源分配的最小单位,K8s 基于 Pod 分配 CPU、内存,简化调度和资源管控逻辑;
  • 提供一致的运行环境:通过 Pause 容器提供统一的 Linux 命名空间,确保容器间网络、存储隔离与共享的一致性。

3. Pod 的两种使用方式(附配置示例)

(1)单容器 Pod(最常用)

一个 Pod 只包含一个应用容器,Pod 相当于容器的 “封装壳”,K8s 管理 Pod 间接管理容器。

配置文件(single-container-pod.yaml)

yaml

apiVersion: v1  # API 版本(核心版本,稳定可用)
kind: Pod       # 资源类型为 Pod
metadata:
  name: single-container-pod  # Pod 名称(自定义,唯一)
spec:
  containers:  # 容器列表
  - name: nginx  # 容器名称(自定义)
    image: nginx:1.14  # 容器镜像(镜像名:版本号)

操作命令及解释

bash

运行

# 创建 Pod(基于配置文件)
kubectl create -f single-container-pod.yaml
# 解释:kubectl 是 K8s 命令行工具,create -f 表示通过文件创建资源

# 查看 Pod 状态(-o wide 显示详细信息,包括运行节点、IP)
kubectl get pods -o wide
# 输出示例:
# NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE
# single-container-pod     1/1     Running   0          5m    10.244.2.24  node02
# 解释:READY 1/1 表示 Pod 中 1 个容器正常运行;STATUS Running 表示 Pod 运行正常

# 查看 Pod 详细信息(如事件、容器配置)
kubectl describe pod single-container-pod
# 用途:排查 Pod 启动失败、状态异常等问题
(2)多容器 Pod(紧密协作场景)

一个 Pod 包含多个容器,共享网络和存储,适用于 “主应用 + 辅助组件” 的场景(如应用容器 + 日志收集容器 Filebeat)。

配置文件(multi-container-pod.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  containers:
  - name: app  # 主应用容器
    image: my-app:latest  # 自定义应用镜像
  - name: sidecar  # 辅助容器(Sidecar 模式)
    image: log-collector:latest  # 日志收集镜像(如 Filebeat)

核心说明

  • 两个容器可通过 localhost 通信(如 app 容器向 localhost:9000 发送日志,sidecar 容器监听该端口收集);
  • 可添加 volumeMounts 配置共享存储(如 app 写入日志到 Volume,sidecar 读取该 Volume 中的日志)。

4. 特殊容器:Pause 容器(基础容器)

每个 Pod 都会自动创建一个 Pause 容器,它是 Pod 的 “基础骨架”,核心作用:

  • 提供统一的 Linux 命名空间(网络、PID 等),让其他容器共享;
  • 维持 Pod 的生命周期(即使应用容器退出,Pause 容器仍运行,Pod 状态不会立即终止)。

查看 Pause 容器命令

bash

运行

# 在 Pod 运行的节点上执行(需登录节点)
docker ps -a | grep pause
# 输出示例:
# registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0 "/pause"
# 解释:Pause 容器镜像由 K8s 内置,默认从阿里云镜像仓库拉取

二、Pod 核心组件:容器分类与作用

Pod 中的容器分为 3 类,各司其职,共同保障应用正常运行:

1. 基础容器(Infrastructure Container)

即 Pause 容器,K8s 自动创建,用户无需配置,核心职责:

  • 维护 Pod 的网络命名空间(分配 Pod IP、管理端口);
  • 维护 Pod 的存储命名空间(挂载共享 Volume)。

配置说明:K8s 通过 kubelet 配置指定 Pause 镜像,默认路径:

bash

运行

cat /opt/kubernetes/cfg/kubelet
# 关键配置:--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0

2. 初始化容器(Init Containers)

在应用容器启动前执行的容器,用于完成 “前置准备工作”(如等待依赖服务启动、初始化配置文件、授权认证)。

核心特性:
  • 按配置顺序执行,前一个 Init 容器成功退出后,下一个才启动;
  • 必须全部成功执行,应用容器才会启动;
  • 若 Init 容器失败,Pod 会根据 restartPolicy 重启(默认 Always 策略下会反复重试)。
实战示例:等待依赖服务启动

配置文件(myapp-pod.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:  # 应用容器(主服务)
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:  # 初始化容器(2 个,按顺序执行)
  - name: init-myservice  # 等待 myservice 服务启动
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb  # 等待 mydb 服务启动
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

操作步骤及命令解释

bash

运行

# 1. 创建 Pod(此时 Init 容器会等待 myservice 和 mydb 服务)
kubectl create -f myapp-pod.yaml

# 2. 查看 Pod 状态(此时处于 Pending/Initializing 状态)
kubectl get pods
# 输出示例:myapp-pod   0/1     Pending   0          3m(Init 容器未完成)

# 3. 查看 Init 容器日志(排查等待原因)
kubectl logs myapp-pod -c init-myservice
# 输出:waiting for myservice(提示等待 myservice 服务)

# 4. 创建依赖服务(myservice 和 mydb,以 Service 为例)
# 创建 myservice 服务(myservice.yaml)
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
kubectl create -f myservice.yaml

# 创建 mydb 服务(mydb.yaml)
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377
kubectl create -f mydb.yaml

# 5. 再次查看 Pod 状态(Init 容器完成,应用容器启动)
kubectl get pods
# 输出示例:myapp-pod   1/1     Running   0          5m
Init 容器的核心作用补充:
  • 隔离初始化逻辑:无需在应用镜像中包含初始化工具(如 sed、awk、dig),减少应用镜像体积和安全风险;
  • 权限隔离:Init 容器可访问 Secrets(敏感信息,如密码),应用容器无法访问,提升安全性;
  • 延迟启动:确保应用容器仅在依赖条件满足时启动(如数据库就绪、配置文件下载完成)。

3. 应用容器(Main Containers)

即用户部署的核心业务容器,用于运行应用服务(如 Nginx、MySQL、自定义应用),核心特性:

  • 多个应用容器并行启动(无顺序依赖);
  • 共享 Pod 的网络和存储资源;
  • 生命周期由 Pod 的重启策略和健康检查控制。

三、Pod 关键配置:镜像拉取与重启策略

1. 镜像拉取策略(imagePullPolicy)

定义 K8s 如何拉取容器镜像,默认策略为 IfNotPresent,支持 3 种配置:

策略作用说明适用场景
IfNotPresent本地有镜像则直接使用,无则从镜像仓库拉取(默认)生产环境(稳定镜像,减少网络开销)
Always每次启动 Pod 都从镜像仓库拉取最新镜像开发环境(需实时获取最新代码)
Never仅使用本地镜像,不从仓库拉取(本地无镜像则启动失败)离线环境(无网络访问镜像仓库)

配置示例(pod-test1.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-test1
spec:
  containers:
  - name: nginx
    image: nginx:1.14  # 镜像名:版本号
    imagePullPolicy: Always  # 每次启动都拉取镜像

命令实战与问题排查

bash

运行

# 创建 Pod
kubectl create -f pod-test1.yaml

# 查看 Pod 状态(若出现 CrashLoopBackoff 异常)
kubectl get pods
# 输出示例:pod-test1   0/1     CrashLoopBackoff   4          3m33s

# 排查原因(查看 Pod 事件)
kubectl describe pod pod-test1
# 关键事件:容器执行完命令后进程终止(因配置了 command: ["echo", "SUCCESS"],执行完退出)
# 解决:删除 command 配置,让 Nginx 容器后台运行(修改后重新应用)
kubectl delete -f pod-test1.yaml  # 删除原有 Pod
kubectl apply -f pod-test1.yaml   # 应用修改后的配置

# 验证 Pod 状态(正常运行)
kubectl get pods -o wide

补充说明

  • 若镜像标签为 latest(默认标签),imagePullPolicy 会默认设为 Always
  • 私有镜像仓库需配置镜像拉取密钥(Secret),否则拉取失败(命令:kubectl create secret docker-registry)。

2. 重启策略(restartPolicy)

定义容器退出后 K8s 如何处理重启,仅作用于 Pod 内的容器(Pod 本身无法重启,只能删除重建),支持 3 种策略:

策略作用说明适用场景
Always无论容器退出状态码如何,都重启容器(默认策略)核心业务容器(需持续运行)
OnFailure仅当容器非正常退出(退出码非 0)时,才重启容器一次性任务(正常完成后不重启)
Never容器退出后不重启(无论退出状态如何)测试容器(手动控制生命周期)

配置示例(pod3.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
  - name: busybox
    image: busybox
    args: ['/bin/sh', '-c', 'sleep 30; exit 3']  # 30 秒后非正常退出(退出码 3)
  restartPolicy: OnFailure  # 非正常退出时重启

命令实战

bash

运行

# 创建 Pod
kubectl apply -f pod3.yaml

# 实时查看 Pod 状态(-w 监听变化)
kubectl get pods -w
# 输出示例:
# foo   1/1     Running   0          10s(初始运行)
# foo   0/1     Error     0          30s(30 秒后退出,状态 Error)
# foo   1/1     Running   1          35s(OnFailure 策略触发重启)

补充说明

  • 重启策略作用于 Pod 内所有容器,而非单个容器;
  • 若 Pod 因节点故障被删除,重启策略无效(需依赖控制器重建 Pod)。

四、Pod 进阶配置:资源限制与健康检查

1. 资源限制(Requests & Limits)

K8s 支持为容器设置 CPU 和内存的 “请求值”(Requests)和 “限制值”(Limits),避免资源争用和过度消耗,确保集群稳定。

核心概念:
  • Requests(请求值):容器启动时最少需要的资源,K8s 调度器根据该值选择 “资源充足” 的节点;
  • Limits(限制值):容器运行时最多可使用的资源,超出该值会被 K8s 限制(CPU 节流、内存 OOM 杀死容器)。
资源单位:
  • CPU:1 CPU = 1 vCPU(物理核心 / 超线程),支持毫核(m),如 500m = 0.5 CPU、100m = 0.1 CPU;
  • 内存:支持二进制单位(Gi、Mi、Ki,基于 1024)和十进制单位(GB、MB、KB,基于 1000),推荐使用二进制单位(如 1Gi = 1024Mi)。
配置示例(frontend.yaml):

yaml

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app  # 应用容器
    image: images.my-company.example/app:v4
    resources:
      requests:  # 最小资源请求
        memory: "64Mi"  # 最少 64Mi 内存
        cpu: "250m"     # 最少 0.25 CPU
      limits:  # 最大资源限制
        memory: "128Mi" # 最多 128Mi 内存
        cpu: "500m"     # 最多 0.5 CPU
  - name: log-aggregator  # 日志收集容器
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

资源计算说明

  • Pod 总请求资源 = 所有容器请求资源之和(0.5 CPU + 128Mi 内存);
  • Pod 总限制资源 = 所有容器限制资源之和(1 CPU + 256Mi 内存);
  • 调度器仅关注 Requests,确保节点剩余资源 ≥ Pod 总请求资源。

命令实战:查看资源分配

bash

运行

# 查看 Pod 资源配置
kubectl describe pod frontend | grep -A 10 "Resources"

# 查看节点资源使用情况(了解节点剩余资源)
kubectl describe nodes node02
# 输出示例(资源摘要):
# Allocated Resources:
#   (Total limits may be over 100 percent, i.e., overcommitted.)
#   Resource           Requests    Limits
#   --------           --------    ------
#   cpu                750m (37%)  1500m (75%)
#   memory             576Mi (14%) 1128Mi (28%)

补充说明

  • 若未设置 Requests,K8s 会自动将其设为与 Limits 相同;
  • 内存超出 Limits 会导致容器被 OOM 杀死(重启策略生效);
  • CPU 超出 Limits 会被节流(限制 CPU 使用率,不会杀死容器)。

2. 健康检查(探针 Probe)

K8s 通过 kubelet 定期对容器执行诊断(探针),确保容器 “存活” 且 “就绪”,支持 3 种探针类型,每种探针可通过 3 种方式检测。

(1)探针类型(核心规则)
探针类型作用说明失败处理逻辑
livenessProbe存活探针:判断容器是否运行(如应用卡死则重启)探测失败 → kubelet 杀死容器,按重启策略重启
readinessProbe就绪探针:判断容器是否准备好接收请求(如依赖未就绪则暂时剔除服务)探测失败 → 从 Service Endpoints 中移除 Pod IP
startupProbe启动探针:判断应用是否启动完成(适用于启动慢的应用,如 Java 服务)探测失败 → 杀死容器,按重启策略重启;成功后其他探针生效
(2)检测方式
检测方式作用说明适用场景
exec在容器内执行命令,返回码 0 则成功(如 cat /tmp/healthy自定义诊断逻辑(如检查配置文件存在)
tcpSocket测试容器 IP: 端口是否能建立 TCP 连接(三次握手成功则生效)检测网络服务可用性(如 Nginx 80 端口)
httpGet发送 HTTP GET 请求,响应状态码 200-399 则成功(如访问 /healthz 接口)Web 应用健康检查(如 Spring Boot actuator)
(3)探针配置参数(常用)
  • initialDelaySeconds:容器启动后延迟多久执行第一次探测(默认 0 秒,如 Java 应用设为 30 秒);
  • periodSeconds:探测频率(默认 10 秒,如设为 5 秒表示每 5 秒探测一次);
  • timeoutSeconds:探测超时时间(默认 1 秒,超时视为失败);
  • failureThreshold:探测失败多少次后判定为最终失败(默认 3 次)。
实战示例 1:exec 方式(存活探针)

配置文件(exec.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
spec:
  containers:
  - name: liveness-exec-container
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "touch /tmp/live ; sleep 30; rm -rf /tmp/live; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test", "-e", "/tmp/live"]  # 检查 /tmp/live 文件是否存在
      initialDelaySeconds: 1  # 启动 1 秒后开始探测
      periodSeconds: 3        # 每 3 秒探测一次

命令实战与现象

bash

运行

# 创建 Pod
kubectl create -f exec.yaml

# 实时查看 Pod 状态
kubectl get pods -w
# 现象:
# 前 30 秒:/tmp/live 存在,探测成功 → 状态 Running
# 30 秒后:/tmp/live 被删除,探测失败 → 触发重启(RESTARTS 计数增加)
实战示例 2:httpGet 方式(就绪探针 + 存活探针)

配置文件(readiness-httpget.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget
spec:
  containers:
  - name: readiness-httpget-container
    image: soscscs/myapp:v1  # 内置 Nginx 的镜像
    ports:
    - name: http
      containerPort: 80  # 容器暴露 80 端口
    readinessProbe:  # 就绪探针(判断是否能接收请求)
      httpGet:
        port: 80
        path: /index1.html  # 检查 /index1.html 是否存在
      initialDelaySeconds: 1
      periodSeconds: 3
    livenessProbe:  # 存活探针(判断应用是否存活)
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3

命令实战与现象

bash

运行

# 创建 Pod
kubectl create -f readiness-httpget.yaml

# 查看 Pod 状态(初始就绪探针失败,READY 0/1)
kubectl get pods
# 输出:readiness-httpget   0/1     Running   0          20s

# 进入容器创建 /index1.html 文件(模拟就绪条件满足)
kubectl exec -it readiness-httpget sh
cd /usr/share/nginx/html/
echo "ready" > index1.html
exit

# 再次查看 Pod 状态(就绪探针成功,READY 1/1)
kubectl get pods
# 输出:readiness-httpget   1/1     Running   0          1m

补充说明

  • 就绪探针失败时,Pod 状态仍为 Running,但 READY 为 0/1,Service 不会将流量转发给该 Pod;
  • 启动探针(startupProbe)适用于启动时间不确定的应用(如大数据组件),避免因启动慢被存活探针误杀;
  • 可同时配置多种探针(如存活 + 就绪),各司其职。

3. 容器生命周期钩子(PostStart & PreStop)

K8s 提供容器启动后和终止前的钩子函数,用于执行自定义逻辑(如初始化配置、优雅关闭应用)。

钩子类型触发时机作用场景
postStart容器启动后立即触发(不保证在容器内进程启动前执行,有短暂延迟)初始化配置(如写入配置文件、创建目录)
preStop容器终止前触发(优雅关闭,确保钩子执行完成后再终止容器)关闭应用进程(如 kill -TERM)、清理资源

配置示例(post.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: soscscs/myapp:v1
    lifecycle:  # 生命周期钩子配置
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from postStart >> /var/log/nginx/message"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from preStop >> /var/log/nginx/message"]
    volumeMounts:  # 挂载存储卷(持久化日志)
    - name: message-log
      mountPath: /var/log/nginx/
  volumes:
  - name: message-log
    hostPath:  # 挂载节点本地目录
      path: /data/volumes/nginx/log/
      type: DirectoryOrCreate  # 目录不存在则自动创建

命令实战

bash

运行

# 创建 Pod
kubectl create -f post.yaml

# 查看 postStart 执行结果(进入容器查看日志)
kubectl exec -it lifecycle-demo -- cat /var/log/nginx/message
# 输出:Hello from postStart

# 删除 Pod(触发 preStop 钩子)
kubectl delete pod lifecycle-demo

# 登录 Pod 运行的节点,查看 preStop 执行结果
ssh node02
cat /data/volumes/nginx/log/message
# 输出:
# Hello from postStart
# Hello from preStop

补充说明

  • postStart 钩子执行失败会导致容器重启(按重启策略);
  • preStop 钩子执行时间过长(超过 terminationGracePeriodSeconds,默认 30 秒),K8s 会强制终止容器。

五、Pod 类型与状态

1. Pod 类型

(1)自主式 Pod
  • 直接创建的 Pod(无控制器管理),无自愈能力;
  • 节点故障、Pod 异常退出后,不会自动重建;
  • 适用场景:临时测试、一次性任务(如数据备份)。
(2)控制器管理的 Pod
  • 通过 K8s 控制器(如 Deployment、StatefulSet、DaemonSet)创建的 Pod;
  • 控制器提供自愈、副本管理、滚动升级等功能(如 Deployment 确保指定数量的 Pod 运行);
  • 生产环境首选(99% 的场景使用控制器管理 Pod)。

补充:常用控制器对比

控制器类型核心作用适用场景
Deployment无状态应用部署(如 Nginx、Web 应用),支持滚动升级、回滚绝大多数无状态服务
StatefulSet有状态应用部署(如 MySQL 集群、ZooKeeper),提供稳定网络标识和存储数据库、分布式组件
DaemonSet每个节点运行一个 Pod(如日志收集、监控代理)集群级监控、网络插件

2. Pod 核心状态

Pod 生命周期包含多个状态,核心状态及含义如下:

状态含义说明常见原因
PendingPod 已被 K8s 接受,但容器未启动(调度中、镜像拉取中)镜像拉取慢、节点资源不足、调度失败
RunningPod 已调度到节点,所有容器启动完成,至少一个容器运行中正常运行状态
Succeeded所有容器正常终止(退出码 0),不会重启一次性任务执行完成(如数据导出)
Failed所有容器终止,至少一个容器非正常退出(退出码非 0)应用崩溃、配置错误、资源不足
UnknownK8s 无法获取 Pod 状态(如节点通信故障)节点宕机、kubelet 服务异常

补充:容器状态(Pod 状态的细分)

  • Waiting:容器启动中(如镜像拉取、初始化);
  • Running:容器正常运行;
  • Terminated:容器终止(正常或异常退出)。

六、总结与实战建议

Pod 是 K8s 世界的 “基石”,掌握它的核心要点:

  1. 本质是 “容器组 + 共享资源”,最小部署单元,不可直接扩容;
  2. 容器分类:基础容器(Pause)、初始化容器(Init)、应用容器(Main),各司其职;
  3. 关键配置:镜像拉取策略(按需选择)、重启策略(按业务场景配置)、资源限制(避免资源争用)、健康检查(确保服务可用);
  4. 生产环境:优先使用控制器(如 Deployment)管理 Pod,避免直接创建自主式 Pod。

实战避坑指南

  • 镜像拉取失败:检查镜像名称 / 版本是否正确、私有仓库是否配置密钥、网络是否能访问镜像仓库;
  • Pod 调度失败:查看节点资源是否充足(kubectl describe nodes)、是否存在节点亲和性限制;
  • 容器启动失败:查看容器日志(kubectl logs <pod-name> -c <container-name>)、Pod 事件(kubectl describe pod <pod-name>);
  • 健康检查失败:确认探测方式、路径 / 端口是否正确,调整 initialDelaySeconds(避免启动慢导致误判)。

通过本文的学习,你已掌握 Pod 的核心概念、配置方法和实战技巧。建议结合实际场景多动手实践(如部署 Nginx 多容器 Pod、配置健康检查),加深对 Pod 生命周期和 K8s 资源管理逻辑的理解。

更多推荐