04 | 为什么我们需要 Pod

发布时间:2026/7/15 8:46:44
04 | 为什么我们需要 Pod 系列专栏《深入剖析 Kubernetes》· 基于张磊极客时间专栏思想整理 · 适合 CSDN 发布04 | 为什么我们需要 Pod如果你已经用过 Docker一定会有一个直觉容器Container就是最小的部署单位。但在 Kubernetes 里真正被调度schedule的单元不是容器而是Pod。这背后是 K8s 设计哲学里最关键的一次抽象升级。本文回答三个问题Pod 到底是什么为什么不直接调度容器以及 Pod 内部是怎么协作的一、Pod 是逻辑主机不是单个容器先看一个事实Kubernetes 永远不会直接调度一个容器它调度的永远是 Pod。Pod 在 K8s 的 API 里是一个一级资源对象就像虚拟机在云平台上是一个一级对象一样。一个 Pod 可以包含一个或多个容器这些容器被捆绑在一起共享运行环境被调度到同一台 Node 上生死与共。为什么要多此一举因为现实中很多协作场景需要一组容器必须待在一起。传统思路直接调度容器 --------------------------- | Scheduler | | - Container A (log) | A 和 B 可能漂到不同 Node | - Container B (app) | 网络、存储耦合怎么办 --------------------------- K8s 思路调度 Pod逻辑主机 ---------------------------------- | Pod (scheduled as one unit) | | ---------- ---------- | | | Container| | Container| | | | app | | log | | | ---------- ---------- | | 共享 net / ipc / uts namespace | ----------------------------------二、为什么不直接调度容器——亲密关系Co-location云原生里有一类典型需求张磊称之为**“超亲密关系”super intimate relationship**。这类容器必须共享网络命名空间Network Namespace两个容器要用localhost直接通信像同一台机器上的两个进程。共享存储Volume一个容器写、另一个容器读比如日志、配置文件。共享 IPC / UTS 命名空间能互相发信号、共享主机名。如果让调度器分别调度两个容器它们可能被分到不同 Node网络隔离、存储也连不起来。Pod 的出现就是为了解决这一组容器必须被当作一个整体来调度的问题。三、Infra 容器pausePod 的地基关键设计Pod 里的第一个容器是一个特殊的 Infra 容器镜像叫pause它几乎什么都不做只负责占用并创建一组 Linux Namespace。----------------------------------------------------- | Pod | | | | [ pause 容器 ] -- 先创建持有 net/uts/ipc ns | | | | | | join共享 | | v | | ---------------- ---------------- | | | 业务容器 app | | sidecar 日志 | | | | (进程监听 8080) | | (读 /var/log) | | | ---------------- ---------------- | | \ / | | \ localhost:8080 通信 | | \ / | | 共享同一个 Network Namespace | | IP Pod IP由 pause 持有 | -----------------------------------------------------为什么需要pause因为容器是会被销毁重建的。如果让业务容器持有 Network Namespace业务容器一重启IP 就没了同 Pod 的其他容器网络也断。把 Namespace 交给一个永不退出、最轻量的pause容器持有业务容器和 sidecar 都以--netcontainer:pause的方式加入它Pod 的 IP 和网卡就稳如磐石。验证一下docker ps | grep pause或在 Node 上cat /proc/业务容器pid/ns/net会发现同 Pod 内容器的 net namespace inode 完全一致。四、Pod 内多容器通过 localhost 通信因为共享 Network NamespacePod 内所有容器看到的都是同一个 IPPod IP和同一组端口。容器之间直接localhost:端口即可互通无需 Service无需跨网络。举例app 容器监听127.0.0.1:8080sidecar 容器访问localhost:8080就能拿到数据。这正是 sidecar 模式的基础。五、Sidecar 模式示例日志收集最经典的 sidecar 用法——业务容器只管写日志到本地文件sidecar 容器负责把日志转发出去如发到 Kafka / ES。二者通过共享 Volume 交换数据。apiVersion:v1kind:Podmetadata:name:web-with-log-sidecarspec:# 共享存储卷用于业务容器与 sidecar 交换日志volumes:-name:logsemptyDir:{}# 空目录卷Pod 生命周期内有效Pod 删除即消失containers:-name:app# 业务容器image:nginx:1.25volumeMounts:-name:logsmountPath:/var/log/nginx# nginx 把访问日志写到这里-name:log-agent# sidecar 容器image:fluent/fluent-bit:3.0volumeMounts:-name:logsmountPath:/var/log/nginx# 与 app 挂载同一卷读取日志env:-name:FLUENT_BIT_OUTPUT# 转发目标示例标准输出value:stdout参数解释emptyDir节点本地临时卷Pod 调度到某 Node 时创建Pod 删除即清空。适合容器间临时中转数据。volumeMounts.mountPath两边挂同一logs卷到相同路径天然实现业务写、sidecar 读。两个容器没有 ports 映射也能互相访问因为它们共享 Pod 网络。六、Pod 生命周期与 restartPolicyPod 有自己明确的状态机kubectl get pod看到的STATUS就是生命周期快照状态含义Pending已创建但容器尚未全部运行含调度、拉镜像Running至少一个容器运行中Succeeded所有容器正常退出且不再重启批处理作业Failed至少一个容器以非 0 退出且不再重启CrashLoopBackOff容器反复崩溃kubelet 退避重试注意Pod 本身没有健康自愈能力——它没有副本概念。Pod 里容器崩了由restartPolicy决定要不要重启容器不是重建 Podspec:restartPolicy:Always# 默认。容器退出就重启适合长驻服务# OnFailure # 仅非 0 退出才重启适合 Job# Never # 永不重启适合一次性任务关键点Pod 是一次性的抽象。真正负责多副本 自愈 扩容的是上层控制器ReplicaSet / Deployment这正是下一篇的主题。小结 / 核心要点Pod 是 K8s 最小调度单元不是容器。调度器永远面向 Pod。Pod 解决超亲密关系共享网络、存储、IPC必须调度到同一 Node。pauseInfra 容器是地基先行创建并持有 Namespace保证 Pod IP 稳定业务容器加入它。Pod 内容器用localhost互通天然适合 sidecar日志收集、代理、适配器模式。Pod 无副本/自愈能力靠restartPolicy决定容器重启策略高可用交给 Deployment。