Skip to content
rouroumaibing

Pod

CNCF 20 分钟阅读

一、一句大白话描述概念

Pod 是 Kubernetes 中最小的部署单元,就像一个豌豆荚🫛,里面住着关系密切的几个”豌豆”(容器),它们共享网络和存储资源。

二、图示

1
2
3
4
5
6
7
8
9
┌─────────────────────────────────────┐
│ Pod │
│ ┌──────────┐ ┌──────────┐ │
│ │ 容器 A │ │ 容器 B │ │
│ │ (主应用) │ │ (Sidecar) │ │
│ └──────────┘ └──────────┘ │
│ │
│ 共享: IP地址 | 端口空间 | 存储卷 │
└─────────────────────────────────────┘

三、知识点

1. 为什么需要 Pod

Kubernetes 不直接部署容器,而是把一个或多个关系紧密的容器包装成 Pod。原因:

  • 协同调度:同 Pod 内的容器保证调度到同一节点,可以本地通信
  • 资源共享:共享网络命名空间(IP、端口)和存储卷
  • 原子管理:Pod 作为整体创建、销毁,容器间生命周期绑定

2. Pod 中容器的共享资源

资源 共享方式
网络 同一 IP 地址和端口空间,容器间通过 localhost 通信
存储 共享 Volume 挂载,可直接读写同一目录
IPC 共享进程间通信
UTC 共享主机名

注意:容器间不共享 PID 命名空间(默认隔离),文件系统也是各自独立的。

3. Pod 生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
           ┌──────────┐
│ Pending │
└────┬─────┘
│ 调度成功 + 镜像拉取完成

┌──────────┐
┌────→│ Running │
│ └────┬─────┘
│ │
重启 │ ┌─────┴──────┐
│ ▼ ▼
│ ┌────────┐ ┌─────────┐
└─┤ Failed │ │Succeeded│
└────────┘ └─────────┘

│ 反复崩溃

┌──────────────────┐
│ CrashLoopBackOff │
└──────────────────┘
状态 说明
Pending 已创建,等待调度或拉取镜像
Running 至少一个容器运行中
Succeeded 所有容器正常退出,不会再重启
Failed 至少一个容器异常退出
CrashLoopBackOff 容器反复崩溃,kubelet 退避重启

4. Sidecar 模式

多容器 Pod 最常见的设计模式:主容器 + 辅助容器(Sidecar)。Sidecar 与主容器共享网络和存储,负责日志收集、监控代理等辅助工作,主容器专注业务逻辑。

5. Pod vs Deployment

实际生产中很少直接创建 Pod,而是用 Deployment 管理:

  • Pod:一次性,挂了不会自动重建
  • Deployment:管理 Pod 副本,自动恢复、滚动更新

6. Init 容器

Init 容器在主容器启动前按顺序运行,全部成功后才会启动主容器。常用于:

  • 等待依赖服务就绪(如等数据库可用)
  • 初始化配置文件或数据
  • 注册服务到发现系统

与普通容器的区别:Init 容器必须成功退出才会继续下一个,失败会根据 Pod 的 restartPolicy 决定是否重启。

资源计算:调度 Pod 时,kubelet 取以下两者的较大值作为资源需求:

  • 所有 Init 容器的最大资源请求
  • 所有普通容器的资源请求之和
1
2
3
4
5
6
7
8
spec:
initContainers:
- name: init-db
image: busybox
command: ['sh', '-c', 'until nslookup db-service; do sleep 3; done;']
containers:
- name: main-app
image: my-app:1.0

上例中 init-db 会一直等待直到 db-service 可解析,成功退出后才启动 main-app

7. 容器探针

探针是 kubelet 对容器定期执行的健康检查:

探针类型 作用 失败后果
livenessProbe 容器是否存活 重启容器
readinessProbe 容器是否就绪 从 Service 端点移除,不接流量
startupProbe 容器是否已启动 禁用 liveness/readiness 检查直到成功

四种检测方式:exec(执行命令)、httpGet(HTTP 请求)、tcpSocket(TCP 连接)、grpc(gRPC 健康检查,1.24+ 稳定)。

探针配置字段

字段 默认值 说明
initialDelaySeconds 0 容器启动后首次探测的等待秒数
periodSeconds 10 探测间隔
timeoutSeconds 1 单次探测超时时间
successThreshold 1 连续成功几次视为通过
failureThreshold 3 连续失败几次视为失败

8. 资源请求与限制

1
2
3
4
5
6
7
resources:
requests: # 调度依据:节点可用资源需满足 requests
cpu: 100m # 100m = 0.1 核
memory: 128Mi
limits: # 运行上限:超过触发限制
cpu: 200m
memory: 256Mi
字段 作用 超额后果
requests 调度器据此选择节点 调度失败(Pending)
limits.cpu CPU 上限 CPU 节流(throttle),性能下降
limits.memory 内存上限 OOMKilled,容器被杀

生产建议:requests 和 limits 都设置,requests 用于调度,limits 防止嘈杂邻居。但 CPU limits 可能导致延迟敏感型应用性能下降,需权衡。

QoS 等级:Kubernetes 根据 requests/limits 配置自动为 Pod 分配 QoS 等级,决定节点资源不足时的驱逐顺序。

QoS 等级 条件 驱逐优先级
Guaranteed 每个容器 requests = limits(CPU 和内存都设置) 最低(最后被驱逐)
Burstable 至少一个容器设置了 requests 或 limits,但不满足 Guaranteed
BestEffort 所有容器都未设置 requests 和 limits 最高(最先被驱逐)

节点资源紧张时,kubelet 按 BestEffort → Burstable → Guaranteed 顺序驱逐 Pod。生产环境建议设置为 Guaranteed。

9. Pod Condition

Pod 的状态通过 pod.status.conditions 字段以条件列表形式描述,每个条件记录 Pod 在某方面的状态:

条件类型 说明
PodScheduled Pod 已被调度到某节点
PodReadyToStartContainers Pod 沙箱已创建,可以启动容器(1.31+)
Initialized 所有 Init 容器已成功完成
ContainersReady 所有普通容器已就绪
Ready Pod 可接收流量(PodScheduled + Initialized + ContainersReady 均为 True)
DisruptionTarget Pod 即将被驱逐或中断
PodResizePending 资源调整请求已提交但尚未处理
PodResizeInProgress 资源调整正在处理中
1
2
# 查看 Pod 条件
kubectl get pod my-app-pod -o jsonpath='{.status.conditions[*].type}'

10. 原生 Sidecar 容器

Kubernetes 1.28+ 支持在 initContainers 中声明 restartPolicy: Always 的容器作为原生 Sidecar:

1
2
3
4
5
6
7
8
spec:
initContainers:
- name: log-sidecar
image: fluent-bit
restartPolicy: Always # 原生 Sidecar 标志
containers:
- name: main-app
image: my-app:1.0

与普通 Sidecar 的区别

特性 普通 Sidecar(containers 中) 原生 Sidecar(initContainers + Always)
启动顺序 与主容器同时启动,无顺序保证 先于主容器启动
停止顺序 无保证 主容器退出后才停止
依赖管理 需额外探针协调 启动顺序由 kubelet 保证

原生 Sidecar 解决了”Sidecar 必须先于主容器启动”的痛点,如日志代理需在主容器前就绪才能收集全部日志。

11. 临时容器(Ephemeral Containers)

临时容器是注入到运行中 Pod 的特殊容器,专用于运行时调试:

  • 无资源限制:不设 ports、probes、resources
  • 不可重启:没有 restartPolicy
  • 不参与调度:直接复用 Pod 所在节点
1
2
# 向运行中的 Pod 注入临时调试容器
kubectl debug -it my-app-pod --image=busybox --target=main-app

典型场景:Pod 因缺少调试工具(如 distroless 镜像)而无法 exec 进去时,用 kubectl debug 注入一个带工具的临时容器排查问题。

12. Downward API

Downward API 将 Pod 和容器的元数据暴露给容器内部使用,有两种方式:

环境变量方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
spec:
containers:
- name: main-app
image: my-app:1.0
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: CPU_LIMIT
valueFrom:
resourceFieldRef:
resource: limits.cpu

Volume 方式(适合暴露标签和注解):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
spec:
containers:
- name: main-app
image: my-app:1.0
volumeMounts:
- name: pod-info
mountPath: /etc/pod-info
volumes:
- name: pod-info
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations

可暴露的字段:metadata.namemetadata.namespacemetadata.labelsmetadata.annotationslimits.cpulimits.memoryrequests.cpurequests.memory 等。

13. 高级 Pod 配置

配置项 字段 作用
优先级 priorityClassName 引用 PriorityClass,决定调度和驱逐优先级
运行时 runtimeClassName 引用 RuntimeClass,选择容器运行时(如 gVisor、Kata Containers)
安全上下文 securityContext 设置 runAsUserrunAsNonRootreadOnlyRootFilesystemcapabilities
节点选择 nodeSelector / affinity 约束 Pod 调度到特定节点
容忍 tolerations 允许 Pod 调度到带污点的节点
运行开销 overhead 容器运行时额外开销(由 RuntimeClass 自动设置)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spec:
priorityClassName: high-priority
runtimeClassName: gvisor
nodeSelector:
disktype: ssd
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
containers:
- name: main-app
image: my-app:1.0
securityContext:
runAsNonRoot: true
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]

生产建议:设置 securityContext 最小权限原则,敏感工作负载用 runtimeClassName 选择沙箱运行时。

四、代码逻辑分析

Pod YAML 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: v1
kind: Pod
metadata:
name: my-app-pod
labels:
app: my-app
spec:
containers:
- name: main-app # 主容器
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
- name: log-collector # Sidecar 容器
image: busybox:1.36
command: ["sh", "-c", "tail -f /var/log/app.log"]
volumeMounts:
- name: shared-log
mountPath: /var/log
volumes:
- name: shared-log # 共享存储卷
emptyDir: {}

关键字段解析

字段 作用
spec.containers 定义 Pod 内的容器列表
resources.requests 调度时的最小资源需求,决定调度到哪个节点
resources.limits 资源上限,超过会被限制或 OOMKill
volumes.emptyDir Pod 级别的临时共享目录,Pod 删除时清空
volumeMounts 容器内挂载路径,多个容器可挂载同一 Volume

查看 Pod

1
2
3
4
5
6
7
8
9
10
11
# 查看所有 Pod
kubectl get pods -o wide

# 查看 Pod 详情(事件、状态、容器信息)
kubectl describe pod my-app-pod

# 查看 Pod 日志
kubectl logs my-app-pod -c main-app

# 进入容器
kubectl exec -it my-app-pod -c main-app -- sh

五、参考链接