Podman --network 网络模式完全指南:从 bridge 到 pasta 的配置详解与源码解析
【免费下载链接】podmanPodman: A tool for managing OCI containers and pods.项目地址: https://gitcode.com/gh_mirrors/po/podman
--network(简写--net)是 Podman 中最核心也最灵活的运行时选项之一,它决定了容器或 Pod 使用何种网络命名空间、如何接入网络、如何获得 IP 地址与端口转发能力。本指南以 Podman 官方 man page 文档 network.md 为骨架,完整覆盖bridge、用户自定义网络、host、none、container:、ns:、private、pasta全部模式,并结合仓库源码(pkg/specgen/namespaces.go、pkg/specgen/generate/namespaces.go)与 Quadlet 单元文档,帮助你理解每个模式的行为差异、适用场景与底层实现,从而在实际部署中正确选择网络方案。
选项适用范围
--network选项在 Podman 中同时作用于容器与 Pod 两类对象,官方文档声明该选项文件同时用于以下命令与单元类型:
podman createpodman runpodman pod createpodman kube play- Quadlet 单元:
podman-container.unit、podman-pod.unit、podman-kube.unit(对应键名为Network=mode)
也就是说,无论你是用 CLI 启动容器、创建 Pod、通过 Kubernetes YAML 播放工作负载,还是用 Quadlet 生成 systemd 服务,--network/Network=的语义完全一致。其基本作用为:设置容器(或 Pod)的网络模式。
bridge 模式:rootful 容器的默认网络栈
基本用法与默认行为
--network=bridge在bridge模式下,Podman 会在默认网桥上为容器创建一个网络栈,这是rootful(特权)容器的默认模式。当未指定任何--network选项时,Podman 实际上会采用private模式(详见下文),而private在 rootful 下同样落地为 bridge。
bridge 附加选项
bridge模式支持以冒号分隔的OPTIONS列表,可同时指定多个选项(逗号分隔):
| 选项 | 含义 | 取值示例 |
|---|---|---|
alias=name | 为该容器添加网络作用域内的别名 | alias=web |
ip=IPv4 | 为容器指定静态 IPv4 地址 | ip=10.88.0.10 |
ip6=IPv6 | 为容器指定静态 IPv6 地址 | ip6=fd00::2 |
mac=MAC | 为容器指定静态 MAC 地址 | mac=44:33:22:11:00:99 |
interface_name=name | 指定容器内部创建的网卡名称 | interface_name=eth0 |
host_interface_name=name | 指定容器外部(宿主侧)网卡名称 | host_interface_name=veth0 |
官方给出的组合示例——同时设置静态 IPv4 与静态 MAC 地址:
podman run --network bridge:ip=10.88.0.10,mac=44:33:22:11:00:99 nginx重要说明:上述列表之外的任何其他选项都会被原样透传给 netavark(Podman 的网络后端)而不做校验,这一特性可用于向 netavark 插件传递参数,为自定义网络插件预留了扩展通道。
rootless 下的端口转发行为
对于 rootless bridge 网络,端口转发默认由rootlessport组件完成。如果你希望改用 pasta 的内核级转发(通过pesto实现,能够在容器内保留原始客户端源 IP 地址),可以在containers.conf的[network]段中设置:
[network] rootless_port_forwarder = "pasta"官方文档明确提示:该选项目前处于实验阶段,其行为未来可能发生变化。
用户自定义网络:按名称或 ID 接入
除了默认网桥,--network还支持直接指定由podman network create创建的用户自定义网络:
--network=my-net --network=my-net:ip=10.89.0.5- 网络标识为自定义网络的名称或 ID;
- 同样支持在冒号后附加与 bridge 模式相同的选项(
alias=、ip=、ip6=、mac=等); - 可通过多次指定
--network来同时接入多个网络:
podman run --network=net1 --network=net2 --network=net3:ip=10.90.0.7 nginx向后兼容:出于兼容性考虑,也允许在第一个--network参数内以逗号分隔多个网络名(如--network=net1,net2),但这种写法无法使用上述 bridge 选项,且不建议在新配置中使用。
从源码看(pkg/specgen/namespaces.go 的ParseNetworkFlag),当指定多个--network时,Podman 要求网络模式必须是 bridge 类(IsBridge()),并且额外网络中不允许再出现bridge、pasta、host、none、private等模式关键字,否则会报错can only set extra network names。此外,bridge模式与自定义网络会共同记录在networkOrder中,最终按顺序传入 libpod 的WithNetNS(..., "bridge", finalNetworks)(见 pkg/specgen/generate/namespaces.go),由 netavark 完成实际的网桥与 veth 配置。
none:隔离但无网络
--network=none该模式会为容器创建独立的网络命名空间,但不在其中配置任何网络接口,因此容器内部没有任何网络连接能力(lo回环之外无其他网卡)。适用于完全不需要网络、追求最小攻击面的场景,例如纯计算型或离线任务容器。
container:id:复用其他容器的网络栈
--network=container:my-container容器会直接复用指定容器的网络命名空间,与目标容器共享 IP 地址、端口与网络接口。典型用途是 sidecar 模式:辅助容器挂载主容器的网络栈,通过localhost直接访问主容器内监听的服务,无需端口映射。
host:直接使用宿主网络命名空间
--network=host容器不创建隔离的网络命名空间,而是直接加入宿主的网络命名空间,与宿主共享全部网络接口与地址。官方文档对此给出了明确的安全警告:
该模式赋予容器对抽象 Unix domain socket 以及绑定在 localhost 上的 TCP/UDP socket 的完全访问权限。由于这些机制常被用来防止外部实体访问敏感的系统服务,使用本选项可能被视为一种安全漏洞。
因此host模式仅在可信环境或对网络性能、端口绑定有特殊要求的场景下使用。
ns:path:加入指定的网络命名空间
--network=ns:/var/run/netns/ns1ns:后跟一个网络命名空间文件的路径,容器将直接加入该命名空间(相当于执行setns进入目标 netns)。源码中对应处理为strings.HasPrefix(ns, "ns:")时设置NSMode = Path并保存路径值(pkg/specgen/namespaces.go),适合对接ip netns等外部工具创建的既有命名空间。
private:按运行身份自动选择
--network=privateprivate为容器创建全新的网络命名空间,其具体落地方式取决于运行身份:
- rootful 容器:使用
bridge模式(接入默认网桥); - rootless 容器:使用
pasta模式(用户态网络栈)。
事实上,当未显式指定网络模式(或指定default)时,Podman 默认采取private——源码中case ns == "" || ns == string(Default) || ns == string(Private): toReturn.NSMode = Private(pkg/specgen/namespaces.go),随后在 pkg/specgen/generate/namespaces.go 中Bridge/Private/Default统一走 bridge 分支,若未显式给出网络名则自动挂接配置中的DefaultNetwork。
pasta:rootless 容器的默认用户态网络栈
定位与默认行为
--network=pastapasta(由 pasta(1) 提供)是一个用户态网络栈,无需 root 权限即可为容器提供完整网络能力。它是rootless 容器的默认网络模式,且仅在 rootless 模式下受支持(源码 pkg/specgen/namespaces.go 中明确报错pasta networking is only supported for rootless mode or when inside a nested userns)。
默认情况下,pasta 会把宿主的 IPv4/IPv6 地址与路由、以及 Pod 接口名称复制到容器内,端口转发能够保留原始客户端源 IP 地址。pasta(1) 的全部选项都可以通过逗号分隔的参数传给pasta:之后。
默认注入的关键参数
Podman 为 pasta 自动注入以下参数,以优化容器网络体验:
| 默认参数 | 作用 | 覆盖方式 |
|---|---|---|
--config-net | 容器启动时自动配置网络 | 始终默认开启 |
--no-map-gw | 禁止容器通过网关地址直连宿主 | 传--map-gw覆盖 |
--dns-forward 169.254.1.1 | 内置 DNS 转发,该地址作为首个 resolver 写入 resolv.conf | 显式传--dns-forward指定其他 IP |
--map-guest-addr 169.254.1.2 | 使/etc/hosts中host.containers.internal生效,允许容器连接宿主 | 显式传--map-guest-addr指定其他 IP |
-t none/-u none | 当未配置任何 TCP/UDP 从宿主到容器的端口转发时,禁用基于监听端口的自动转发 | 通过--publish或直接传-t/-u覆盖 |
-T none/-U none | 禁用从容器到宿主的自动端口转发 | 同上 |
这些默认行为全部可以在containers.conf的[network]段中通过pasta_options键统一配置,而无需每次在命令行重复书写。
实战示例
官方文档给出了多个可直接套用的 pasta 配置示例:
1. 允许容器用网关地址直连宿主:
--network=pasta:--map-gw2. 指定容器内 tap 接口 MTU 为 1500 字节:
--network=pasta:--mtu,15003. 完整定制:禁用 IPv6、指定静态地址/网关/DNS/MTU:
--network=pasta:--ipv4-only,-a,10.0.2.0,-n,24,-g,10.0.2.2,--dns-forward,10.0.2.3,-m,1500,--no-ndp,--no-dhcpv6,--no-dhcp即容器内tap0接口分配10.0.2.0/24,网关10.0.2.2,DNS 转发器10.0.2.3,MTU 1500,并关闭 NDP、DHCPv6 与 DHCP。
4. 与上面相同但保持默认 MTU(65520 字节):
--network=pasta:-I,tap0,--ipv4-only,-a,10.0.2.0,-n,24,-g,10.0.2.2,--dns-forward,10.0.2.3,--no-ndp,--no-dhcpv6,--no-dhcp5. 启用双向基于监听端口的自动端口转发:
--network=pasta:-t,auto,-u,auto,-T,auto,-U,auto6. 将容器内 TCP 5201 端口转发到宿主,走回环接口以获得更好性能:
--network=pasta:-T,5201源码侧的 pasta 实现
在 pkg/specgen/namespaces.go 中,pasta:前缀后的选项会被按逗号切分并存入networkOptions;随后 pkg/specgen/generate/namespaces.go 通过libpod.WithNetNS(portMappings, postConfigureNetNS, "pasta", nil)把 pasta 模式传入 libpod 运行时。注意 pasta 模式下PortMappings仅允许配合 bridge 或 pasta 网络使用(pkg/specgen/pod_validate.go)。另外,旧版 rootless 使用的slirp4netns模式已从本版本移除,源码会直接报错提示改用 pasta(pkg/specgen/namespaces.go)。
Quadlet 中的 Network= 特殊规则
在 Quadlet(systemd 单元生成器)场景下,键名为Network=mode,且存在两条特殊命名规则:
1. 名称以.network结尾 —— 关联 Podman 网络单元:
如果网络名以.network结尾,Podman 将使用名为systemd-$name的 Podman 网络,且生成的 systemd 服务会依赖$name-network.service。该网络可通过对应的$name.networkQuadlet 文件自动创建(相关机制详见 podman-network.unit.5.md.in)。注意:对应的.network文件必须存在,例如:
# foo.network [Network] Subnet=10.200.0.0/24# bar.container [Container] Image=nginx Network=foo.network此时容器接入的是systemd-foo.network对应的网络,服务单元自动依赖foo-network.service。
2. 名称以.container结尾 —— 复用其他容器的网络栈:
如果网络名以.container结尾,容器将复用由$name.container创建的另一个容器的网络栈,生成的 systemd 服务会依赖$name.service。同样,对应的.container文件必须存在:
# db.container [Container] Image=postgres Network=app.container该容器会复用app.container定义的容器的网络栈(对应--network=container:app语义)。
模式速查与选择建议
| 模式 | rootful | rootless | 是否隔离 | 网络连接 | 典型场景 |
|---|---|---|---|---|---|
bridge | ✔ 默认 | 可用 | 是 | 默认网桥 | 常规服务、多容器互访 |
<网络名/ID> | ✔ | ✔ | 是 | 自定义网络 | 需要固定 IP、跨主机、多网络 |
none | ✔ | ✔ | 是 | 无 | 离线计算、最小攻击面 |
container:id | ✔ | ✔ | 共享 | 随目标容器 | sidecar、代理注入 |
host | ✔ | ✔ | 否 | 宿主网络 | 性能敏感、端口全开 |
ns:path | ✔ | ✔ | 加入指定 ns | 随目标命名空间 | 对接 ip netns 等外部工具 |
private | ✔(bridge) | ✔(pasta) | 是 | 按身份自动选择 | 未显式指定时的默认 |
pasta | 不支持 | ✔ 默认 | 是 | 用户态网络栈 | rootless 默认、保留源 IP |
选择建议:rootful 环境优先用默认的 bridge / private,需要跨容器固定寻址时创建自定义网络;rootless 环境保持默认 pasta,需要精细控制端口转发或 MTU 时在pasta:后追加参数;追求隔离且不需要网络时用none,而host与container:仅在明确需要共享网络栈的场景使用。
延伸阅读
- 选项文档本身:network.md(该文档同时驱动 create、run、pod create、kube play 与 Quadlet 的 man page 生成)
- 网络解析实现:pkg/specgen/namespaces.go(
ParseNetworkFlag) - 命名空间落地逻辑:pkg/specgen/generate/namespaces.go(
namespaceOptions中的 Network 分支) - Quadlet 网络单元:podman-network.unit.5.md.in、容器单元 podman-container.unit.5.md.in
- 校验工具:cmd/podman/parse/net.go(IP/MAC 等参数合法性校验)
【免费下载链接】podmanPodman: A tool for managing OCI containers and pods.项目地址: https://gitcode.com/gh_mirrors/po/podman
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考