什么是 Pod
Pod 是 K8s 中最小的调度和管理单元。一个 Pod 是一组(通常是一个,也可以是多个)共享网络和存储的容器集合。同一个 Pod 内的容器:
- 共享同一个网络命名空间(相同 IP 地址,可通过 localhost 互相访问)
- 共享同一个 IPC 命名空间(可以通过共享内存通信)
- 可以挂载相同的存储 Volume
- 总是被调度到同一个 Node 上
Pod 这个抽象层允许将紧密耦合的容器(如应用 + 日志收集 agent)作为一个整体管理,同时保持容器的隔离性。Pod 中有一个隐藏的 Pause 容器(infra 容器),负责持有 Pod 的网络命名空间,其他容器加入这个命名空间。
Pod 完整 YAML 示例
apiVersion: v1
kind: Pod
metadata:
name: web-pod
namespace: default
labels:
app: web
version: v1
spec:
containers:
- name: web # 容器名称
image: nginx:1.25
imagePullPolicy: IfNotPresent # Always/Never/IfNotPresent
ports:
- containerPort: 80
protocol: TCP
resources: # 资源请求和限制
requests: # 调度依据:保证至少得到这么多
cpu: 100m # 100 millicores = 0.1 CPU
memory: 128Mi # 128 Mebibytes
limits: # 硬上限:超出则被限流/OOMKilled
cpu: 500m
memory: 256Mi
env: # 环境变量
- name: APP_ENV
value: production
livenessProbe: # 存活探针:失败则重启容器
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 15 # 容器启动后等待 15s 再开始探测
periodSeconds: 10 # 每 10s 探测一次
failureThreshold: 3 # 连续 3 次失败才重启
readinessProbe: # 就绪探针:失败则从 Service 摘流
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts: # 挂载 Volume
- name: config-vol
mountPath: /etc/nginx/conf.d
volumes: # 声明 Pod 级别的 Volume
- name: config-vol
configMapRef:
name: nginx-config
restartPolicy: Always # Always/OnFailure/Never
terminationGracePeriodSeconds: 30 # 优雅停止等待时间(秒)
Pod 生命周期
Pod 生命周期状态机 ┌──────────────────────────────────────────────────────┐ │ 创建 Pod │ └──────────────────┬───────────────────────────────────┘ ▼ Pending ←── 等待调度 / 拉取镜像 / 等待 PVC 绑定 ▼ Running ←── 至少一个容器在运行 ├──── 所有容器成功退出 ──► Succeeded └──── 容器失败且不再重启 ──► Failed Unknown ←── Node 失联,状态未知 Terminating ←── 收到删除信号,等待优雅退出
多容器 Pod 设计模式
虽然大多数 Pod 只包含一个主容器,但 K8s 定义了三种多容器协作模式:
Sidecar(边车)模式
在主容器旁运行辅助容器,增强或扩展主容器的功能,两者共享相同的存储和网络。
spec:
containers:
- name: app # 主容器:写日志到共享目录
image: my-app:v1
volumeMounts:
- name: log-vol
mountPath: /var/log/app
- name: log-shipper # Sidecar:读日志并发送到 Elasticsearch
image: fluent/fluent-bit:3.0
volumeMounts:
- name: log-vol
mountPath: /var/log/app
readOnly: true
volumes:
- name: log-vol
emptyDir: {} # Pod 生命周期内的临时共享存储
Init 容器
在主容器启动前运行的初始化容器,串行执行,必须全部成功才会启动主容器。
spec:
initContainers: # Init 容器列表,按顺序执行
- name: wait-for-db # 等待数据库就绪
image: busybox:1.36
command:
- sh
- -c
- "until nc -z mysql-svc 3306; do echo waiting...; sleep 2; done"
- name: db-migrate # 执行数据库迁移
image: my-app:v1
command: ["python", "manage.py", "migrate"]
containers:
- name: app # Init 容器全部成功后才启动
image: my-app:v1
资源请求与限制
健康探针(Health Probes)
K8s 提供三种探针,通过不同机制告知 K8s 容器的健康状态:
Liveness Probe(存活探针)
探测容器是否仍在运行。失败时 K8s 重启容器。用于检测死锁等无法自行恢复的状态。
Readiness Probe(就绪探针)
探测容器是否准备好接受流量。失败时将 Pod 从 Service 的 Endpoints 中摘除,不再转发流量,但不重启容器。
containers:
- name: app
image: my-app:v1
startupProbe: # 启动探针:启动慢的应用防止被 Liveness 误杀
httpGet:
path: /healthz
port: 8080
failureThreshold: 30 # 最多等 30 * 10s = 300s 启动
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0 # startupProbe 通过后立即开始
periodSeconds: 10
timeoutSeconds: 5 # 探测超时时间
failureThreshold: 3
readinessProbe:
tcpSocket: # TCP 端口探测(另一种探针类型)
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
Pod QoS 服务质量等级
K8s 根据容器的 requests/limits 设置,自动将 Pod 分为三个 QoS 等级,决定节点内存紧张时 Pod 被驱逐的优先级:
| QoS 等级 | 条件 | 驱逐优先级 |
|---|---|---|
| BestEffort | 没有设置任何 requests 和 limits | 最先被驱逐 |
| Burstable | 至少有一个容器设置了 requests,但 requests ≠ limits | 其次被驱逐 |
| Guaranteed | 所有容器都设置了 requests == limits(CPU 和内存) | 最后被驱逐 |
生产环境关键服务应设置 requests == limits,达到 Guaranteed QoS,避免在节点资源紧张时被意外驱逐。同时配合 LimitRange 为 Namespace 设置默认资源限制,防止忘记设置的 Pod 成为 BestEffort 等级。
如果你的容器频繁被 OOMKilled,不要盲目提高 memory limit。先用 kubectl top pods 观察实际内存用量,分析是内存泄漏还是正常需求。同时,Java 应用要注意设置 JVM 堆大小(-Xmx)与 K8s memory limit 的对应关系,不然 JVM 会按节点总内存分配堆,很快超出 limit 被 Kill。
K8s 1.29/1.32:官方 Sidecar Container 支持
K8s 1.32 稳定了官方 Sidecar 容器机制,彻底解决了 Sidecar 生命周期管理问题:
spec:
initContainers:
- name: log-shipper # 官方 Sidecar:在 initContainers 中设置 restartPolicy
image: fluent/fluent-bit:3.0
restartPolicy: Always # 关键!设置此字段使其成为 Sidecar 而非 Init
volumeMounts:
- name: log-vol
mountPath: /var/log/app
readOnly: true
containers:
- name: app # 主容器:退出后 log-shipper 才会被终止
image: my-app:v1
volumeMounts:
- name: log-vol
mountPath: /var/log/app
volumes:
- name: log-vol
emptyDir: {}
官方 Sidecar 的优势:
- 主容器退出后,Sidecar 仍运行直到 Job 完成,确保所有日志被发送
- Sidecar 在主容器之前启动(作为 initContainer),可以先做好准备
- Sidecar 的就绪状态不影响 Pod 的 Ready 状态判断
K8s 1.32:In-Place Pod Resources Update
Beta 特性:无需重建 Pod 即可修改其 CPU/内存资源配置,通过直接调整 cgroup 实现:
# 修改运行中 Pod 的资源限制(直接修改 spec,不触发 Pod 重建)
kubectl patch pod my-pod --type merge \
-p '{"spec":{"containers":[{"name":"app","resources":{"requests":{"cpu":"200m","memory":"256Mi"},"limits":{"cpu":"500m","memory":"512Mi"}}}]}}'
# 查看资源更新状态
kubectl describe pod my-pod
# 观察 Resources 字段中的 Allocated Resources vs Requested 的差异
# resizeStatus: Proposed/InProgress/Deferred/Infeasible
In-Place Pod Resources Update 的限制:
1. 只能修改 CPU 和内存的 requests/limits,不能修改其他字段
2. 内存 limit 缩减时需要容器配合,容器需要先减少内存使用
3. 若节点资源不足以满足新的请求,更新会被推迟(Deferred 状态)
4. 部分运行时(如 containerd 1.7+)才支持此特性
Pod 是 K8s 最小调度单元,同 Pod 内容器共享网络和存储。生命周期阶段:Pending → Running → Succeeded/Failed。三种健康探针各司其职:startupProbe(防止启动慢被误杀)、livenessProbe(死锁时重启)、readinessProbe(未就绪时摘流量)。requests/limits 决定调度和 QoS 等级(Guaranteed/Burstable/BestEffort)。K8s 1.32 带来官方 Sidecar 支持(initContainers + restartPolicy:Always)和 In-Place 资源更新(Beta)。