2.3 Pod 的本地实现:容器组与 infra 容器


2.3 Pod 的本地实现:容器组与 infra 容器

本节摘要:Pod 是 Kubernetes 的最小调度单元——一组共享网络与 IPC 命名空间的容器。Podman 把这个概念完整搬到单机:pod create 建立 Pod 与 infra 容器(一个暂停态的占位进程),随后加入的容器共享它的网络栈。本节实操验证共享效果,解释 infra 容器的存在理由,并对比 Docker Compose 的"服务组"模型与 Pod 模型的语义差别。

为什么单机也需要 Pod

先回答一个合理的疑问:我又不跑 Kubernetes,为什么要关心 Pod?答案藏在"共享"二字里。开发中经常遇到这样的需求:一个应用容器和一个日志收集容器必须看到同一块网络——日志容器要访问应用容器的回环地址;或者一个应用与一个代理要共享同一 IPC 通道做零拷贝通信。Docker 的解法是创建一个共享的 bridge 网络让容器通过容器名互访,可行,但回环地址不通、IPC 各自独立。

Pod 的解法更彻底:组内容器直接共享同一个网络命名空间——同一个 IP、同一组端口空间、回环互通。这正是 Kubernetes 里"为什么一个 Pod 内的多个容器能像同一台机器上的进程一样协作"的原因。Podman 原生支持这套语义,代价是你要多理解一个角色:infra 容器。

动手建一个 Pod

实操最直观。创建一个带 infra 容器的 Pod,加入两个业务容器,验证共享:

# 创建 Pod,发布端口,infra 容器自动创建 podman pod create --name devpod -p 8080:80 # 4c1d... # 查看当前 Pod 里的容器——多了一个没让你创建的 podman ps -a --pod # CONTAINER ID IMAGE COMMAND STATUS POD NAMES # 2b8e... registry.access.../... Created devpod 2b8e-infra # 解读:第一个"容器"就是 infra 容器,镜像是发行版提供的 pause 镜像 # 加入两个业务容器:一个简易 http 服务,一个客户端 podman run -d --pod devpod --name web docker.io/library/nginx:alpine podman run --pod devpod --name probe alpine:3.19 \ sh -c 'wget -qO- http://127.0.0.1:80 | head -1' # <!DOCTYPE html> # 关键点:probe 容器通过 127.0.0.1 直接访问到了 web 容器的服务。 # 没有网络别名解析、没有跨容器路由——它们本来就在同一个网络栈里 # 验证共享:两个容器看到的网络设备完全一致 podman exec web ip addr show eth0 | grep 'inet ' podman exec probe ip addr show eth0 | grep 'inet ' # 两边输出同一个 IP。因为 eth0 属于共享的网络命名空间

infra 容器:不能删的占位进程

infra 容器的镜像通常叫 pause,它只做一件事:sleep,占据着 Pod 的共享命名空间。存在理由牵涉生命周期问题:网络命名空间必须有进程持有才不会销毁。如果共享的网络栈属于第一个业务容器,那这个容器一退出,整组容器的网络就塌了——同 Pod 的其他容器瞬间失联。

pause 把"命名空间的持有者"与"业务容器"解耦:它不做事,所以几乎不会崩;它活着,命名空间就活着;业务容器可以随意重启进出,互不牵连。Kubernetes 在集群里用的正是同一个机制(每个 Pod 第一个启动的就是 pause 容器)。验证一下它确实在偷懒:

# infra 容器的进程开销 podman pod stats devpod --no-stream # POD CPU% MEM # devpod 0.01% 300KiB 级别 # 几乎为零——这就是"占位"的成本 # 试着删掉 infra 容器会怎样? # podman 会拒绝或导致 Pod 网络失效,取决于版本; # 正确的解体顺序永远是:先删业务容器,再 pod rm

一个容易踩的坑顺带记录:podman run --pod 时再指定 -p 端口映射会被拒绝——端口属于 Pod 整体,必须在 pod create 时声明。这个设计同样来自 Kubernetes:端口是 Pod 的属性,不是容器的。

与 Docker Compose 的模型对照

用一张结构图把两种组织方式的形态差别画出来,比文字更直观:

图:Docker 服务组 与 Podman Pod 的结构对照

图:Docker 服务组 与 Podman Pod 的结构对照

既然讲对比驱动,就把三种"把容器组织起来"的方式并排放:

维度 Docker bridge 网络 Docker Compose Podman Pod
网络共享 容器名互访,回环不通 同左(service 名解析) 同一网络栈,回环互通
IPC 共享 默认各自独立 默认各自独立 组内共享 IPC 命名空间
生命周期 各容器独立 随 project 启停 infra 持有,业务容器可单独进出
端口声明 每容器各自 -p 每服务各自映射 pod create 时统一声明
与 K8s 的语义距离 中(service 集合近似) 近(同一 Pod 概念)

Compose 的"一组服务"与 Pod 的"一组容器"看起来都是"把相关的东西放一起",但语义重心不同:Compose 描述的是服务拓扑(谁依赖谁、什么顺序启动),每个容器仍是独立的网络公民;Pod 描述的是进程协作(谁和谁共享一台"机器"),组内容器像同一主机上的进程。前者适合"应用 + 数据库 + 缓存"这种服务组合,后者适合"应用 + 日志收集"这种进程级共生。选错模型不会立刻报错,但会让通信方式变得别扭——第 8 章 play kube 会看到这个差别的终局形态。

本节要点回顾

  • Pod = 共享网络与 IPC 命名空间的容器组:组内回环互通、IP 相同
  • infra 容器是命名空间的持有者:pause 镜像,开销近乎为零,业务容器可自由进出
  • 端口属于 Pod:必须在 pod create 时声明,run 时补挂会被拒绝
  • Pod 与 Compose 语义不同:进程级共生 与 服务拓扑,适用场景不同
  • 解体顺序:先删业务容器再 pod rm,别碰 infra

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U