Kubernetes Pod 是什么?生命周期和重启策略怎么理解?
Pod 是 Kubernetes 里最小的可调度单元,不是容器本身。一个 Pod 可以包含一个或多个容器,这些容器共享网络命名空间、存储卷和生命周期,被调度到同一个节点上运行。大多数业务场景是一个 Pod 一个主容器;只有当多个容器必须紧密协作、共享 localhost 或共享文件时,才适合放进同一个 Pod。理解 Pod 的重点是:它是一次运行实例,天然会被替换,不应该把它当成固定机器来使用。
Pod 和容器是什么关系
容器负责运行进程,Pod 负责把一组容器包装成 Kubernetes 能调度和管理的对象。同一个 Pod 内的容器共享同一个 IP,可以通过 localhost 通信,也可以挂载同一个 volume 交换文件。取舍是协作方便,但扩缩容粒度也被绑在一起:一个 Sidecar 占用资源过高,会影响主容器;主容器需要扩容时,Sidecar 也会跟着复制。不要把数据库、后端、前端这类生命周期不同的组件塞进一个 Pod。
yamlapiVersion: v1 kind: Pod metadata: name: web labels: app: web spec: containers: - name: nginx image: nginx:1.25 ports: - containerPort: 80 resources: requests: cpu: 100m memory: 128Mi limits: memory: 256Mi
Pod 生命周期有哪些阶段
Pod 常见 phase 有 Pending、Running、Succeeded、Failed 和 Unknown。Pending 表示对象已经创建,但还没成功运行,原因可能是调度失败、镜像拉取慢、PVC 没绑定或 init container 还没完成。Running 只表示 Pod 已经绑定节点并且至少一个容器在运行,不等于业务已可接流量。Succeeded 和 Failed 常见于 Job,Unknown 多和节点失联或 kubelet 状态无法上报有关。
bashkubectl get pod web -o wide kubectl describe pod web kubectl get events --sort-by=.metadata.creationTimestamp
重启策略怎么选
Pod 的 restartPolicy 有 Always、OnFailure、Never。Deployment、DaemonSet、StatefulSet 这类长期服务通常只能用 Always,因为控制器期望服务持续运行。Job 常用 OnFailure,失败时让容器重跑,成功退出就不再重启。Never 适合一次性调试或希望失败状态被保留下来的任务。边界是 restartPolicy 只管 Pod 内容器重启,不等于控制器是否会重新创建 Pod;Deployment 即使容器一直崩,ReplicaSet 仍会努力维持副本数。
yamlapiVersion: batch/v1 kind: Job metadata: name: data-migrate spec: template: spec: restartPolicy: OnFailure containers: - name: migrate image: busybox command: ["sh", "-c", "./migrate.sh"] backoffLimit: 3
探针和生命周期钩子别混淆
livenessProbe 用来判断容器是否需要重启,readinessProbe 用来判断 Pod 是否可以加入 Service 后端,startupProbe 用来保护启动慢的应用。常见踩坑是把 readiness 写得太宽,应用还没连上数据库就接流量;或者把 liveness 写得太激进,启动高峰时被反复杀掉。生命周期钩子如 preStop 更适合优雅下线,让应用先停止接新请求,再等待连接处理完。
yamlreadinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 periodSeconds: 10
为什么不建议直接管理裸 Pod
裸 Pod 删除后不会自动恢复,节点故障时也缺少更高层控制器帮你维持副本。生产服务通常应该用 Deployment、StatefulSet、DaemonSet 或 Job 创建 Pod。Deployment 适合无状态服务,StatefulSet 适合有稳定身份和存储的服务,DaemonSet 适合每个节点一个代理,Job 适合一次性任务。直接写 Pod YAML 可以用于学习和临时排查,但不适合作为长期交付方式。
追问
Pod 为什么不是直接等于容器?
Kubernetes 需要一个比容器更高的抽象来表达共享网络、共享卷、调度和生命周期。Pod 内多个容器可以通过 localhost 通信,这对 Sidecar、日志代理、服务网格代理很有用。取舍是这些容器会被一起调度、一起扩缩容,不能独立水平扩展。只有强协作关系才放同一个 Pod,否则应该拆成不同工作负载。
Pending 一定是镜像拉不下来吗?
不一定。Pending 可能是调度阶段就失败了,比如资源 request 太高、节点污点没有容忍、亲和性规则过硬、PVC 未绑定,也可能是镜像拉取或 init container 阶段卡住。最可靠的方式是看 kubectl describe pod 里的 Events。踩坑点是只看 Pod phase 会误导判断,真正原因通常写在 Warning 事件里。
Running 是否代表服务已经可用?
不代表。Running 只说明容器层面已启动,业务可能还在加载配置、连接数据库或预热缓存。Service 是否转发流量主要看 readinessProbe 和 EndpointSlice,而不是只看 Pod phase。边界是没配置 readinessProbe 时,Kubernetes 可能过早把 Pod 加入后端。滚动发布中这会导致短暂 502 或请求超时。
Always、OnFailure、Never 应该怎么选?
长期服务用 Always,失败了就重启,配合 Deployment 等控制器维持副本。批处理任务通常用 OnFailure,让非零退出码触发重试,成功退出后保持完成状态。Never 适合调试或希望失败现场保留下来的任务。不要在 Deployment 里幻想用 OnFailure 管服务生命周期,这不符合控制器约束,也会让行为变得难以预测。
Pod 被删除后数据会不会还在?
要看数据放在哪里。容器文件系统和 emptyDir 通常会随 Pod 消失,PVC 挂载的持久卷则可以跨 Pod 保留。取舍是持久化能保护数据,但也引入存储绑定、访问模式、扩容和回收策略问题。生产里不要把重要数据写在容器本地路径,除非明确接受 Pod 重建后数据丢失。