ToolkitX
知识库工具箱

Pod 详解

Pod 生命周期、容器设计模式、Init

25min·进阶

01. Pod 是什么

Pod 是 K8s 的最小调度单位,一个 Pod 里可以有多个容器,但大多数情况是 1 个 Pod 1 个容器。Pod 里的所有容器共享同一个网络命名空间(同一个 IP)和存储卷,可以通过 localhost 互相通信。 Pod 是临时的——它会被创建、销毁、重建。每次重建 IP 都不一样。Pod 不应该被直接管理(除非临时调试),应该通过 Deployment、StatefulSet 等控制器来管理。 Pod 的生命周期:Pending(等待调度)→ Running(至少一个容器在跑)→ Succeeded/Failed(所有容器终止)。Pod 一旦终止了就不会复活,控制器会创建新的 Pod。
bash
# 快速创建一个临时 Pod 做调试
kubectl run debug-pod --image=nginx --rm -it -- sh

# 查看 Pod 详情
describe pod my-pod

# 查看 Pod 的 YAML(从 K8s 拿到的实际运行配置)
kubectl get pod my-pod -o yaml

# 删除 Pod(如果是 Deployment 管理的,会立刻重建)
kubectl delete pod my-pod

02. 多容器 Pod 与 Sidecar 模式

一个 Pod 里多个容器的经典模式叫 Sidecar——主容器干正事,Sidecar 容器干辅助工作:日志收集、代理、配置热更新。 比如你的应用容器把日志写到文件,Sidecar 容器负责把日志发送到日志系统。因为共享存储,Sidecar 能读到主容器的文件。 多容器 Pod 的注意事项:容器启动顺序没有保证(除非用 Init 容器)。如果一个 Pod 里的某个容器一直 CrashLoop,整个 Pod 的状态就是 CrashLoopBackOff。 Init 容器——Pod 里的特殊容器,在普通容器之前启动,完成后就退出。适合做初始化工作:等数据库就绪、下载配置、修改文件权限。
yaml
# Pod 定义(1 主容器 + 1 Sidecar)
apiVersion: v1
kind: Pod
metadata:
  name: app-with-sidecar
spec:
  containers:
  - name: app
    image: myapp:latest
    volumeMounts:
    - name: logs
      mountPath: /var/log/app
  - name: log-shipper
    image: fluentd:latest
    volumeMounts:
    - name: logs
      mountPath: /var/log/app
      readOnly: true
  volumes:
  - name: logs
    emptyDir: {}
Sidecar 模式最常见的就是日志收集——应用只管写日志,Sidecar 负责发送。两个容器各司其职,解耦。

03. 探针——Liveness、Readiness、Startup

K8s 用探针来检查容器的健康状况: Liveness Probe——容器还活着吗?如果探针失败,K8s 杀掉容器并重启。适合检测死锁、无限循环等导致进程还活着但已经不能服务的状态。 Readiness Probe——容器准备好接收流量了吗?失败时 K8s 不把流量路由到这个 Pod。适合检测依赖还没就绪的情况(如数据库还没连上)。 Startup Probe——容器启动完了吗?只用在启动慢的容器。启动期间 Startup Probe 如果失败,Liveness 不会执行(否则容器还没启动完就被杀了)。 探针有三种实现方式:HTTP GET(最常用)、TCP Socket、Exec(容器内执行命令)。
yaml
# 探针配置
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 15
  periodSeconds: 20

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10

startupProbe:
  httpGet:
    path: /startup
    port: 8080
  failureThreshold: 30
  periodSeconds: 10
Readiness 和 Liveness 要不同。Readiness 探针失败只是不导流量,Liveness 探针失败是直接杀容器重建。

04. 资源请求与限制

Pod 的每个容器都需要声明资源请求和限制: requests——调度时保证的最少资源。Scheduler 只会把 Pod 分配到有足够空闲资源的 Node 上。 limits——容器最多能用的资源。超出 CPU limit 会被 throttling(变慢),超出内存 limit 会被 OOMKilled(杀掉)。 requests 用于调度决策,limits 用于运行时限制。如果你设了 limits 没设 requests,K8s 会把 requests 默认设成跟 limits 一样。 资源单位:CPU 用核数(0.5 = 半核,或者写 500m = 500 millicpu)。内存用字节(Mi = 兆字节,Gi = 吉字节)。
yaml
# 资源声明
containers:
- name: app
  image: myapp:latest
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 500m
      memory: 256Mi

# 不设 limits 的后果:容器可以用光整个 Node 的资源
# 不设 requests 的后果:调度器不知道给多少资源,可能把 Node 塞爆
生产环境每个容器必须设 requests 和 limits。不设的话一个内存泄漏就能把整个 Node 上的 Pod 全拖垮。

05. Pod 排错

Pod 出问题了怎么排查?按这个顺序来: 1. kubectl get pods——先看状态是不是 Running。常见错误状态:Pending(调度不了,查 Node 资源或镜像拉取)、CrashLoopBackOff(起来了又挂,看日志)、ImagePullBackOff(拉不到镜像)、ErrImagePull(镜像名错了)。 2. kubectl describe pod——看 Events 部分,K8s 把 Pod 经历的一切都记在这里。拉镜像、调度、启动探针失败都有对应事件。 3. kubectl logs——看容器输出。如果 Pod 有多个容器,用 -c 指定。如果容器反复重启,加 --previous 看上次容器的日志。 4. kubectl exec——进容器里手动排查。记住容器里可能没装 curl/nc 之类的调试工具,用 alpine 镜像跑临时 Pod。
bash
# 排查流程
kubectl get pods                     # 状态
kubectl describe pod my-pod          # 事件
kubectl logs my-pod                  # 当前容器日志
kubectl logs my-pod --previous       # 上次崩溃的日志
kubectl exec -it my-pod -- sh        # 进入容器

# 临时调试 Pod
kubectl run debug --image=alpine --rm -it -- sh
# 进去后可以 ping、nslookup、curl 测试
describe pod 的 Events 是最重要的排查入口。每次 Pod 状态变化 K8s 都在 Event 里记原因。

知识测验

1/5正确 0

Pod 里多个容器怎么互相通信?

下一节

Service 与网络

下一节