Linux 网络命名空间与 Overlay 实战:把容器网络刨到底


很多 Docker/K8s 用户对"容器为什么有自己的网络?容器间、容器与宿主机怎么互通?"只停留在"会用 Ubuntu 那几条命令"的层面,一遇到网络隔离、多宿主机跨机通信就发怵。其实这些背后的地基就是 Linux 的"网络命名空间(netns)+ 虚拟网卡(veth)+ 网桥(bridge)"组合。这篇把容器网络刨到 Linux 层讲透:网络命名空间怎么隔离、veth/网桥/overlay 怎么组成"一套可迁移的分布式虚拟网络",以及排障时该看哪些 `ip netns`、`ip link` 命令和常见坑。

一、网络命名空间解决什么:让"多个进程组"各有一张独立的虚拟网卡环境

Linux 网络命名空间(network namespace)把一个进程能"看到"的网络栈(网卡、路由表、iptables 规则、socket)整套隔离:跑在命名空间里的进程看到的是一个"全新虚拟网络栈",有它自己的 lo、自己的接口与路由,互不串扰。这正是"容器有独立 IP、独立端口空间"的底层原理——每个容器一个 netns,宿主机一个默认 netns。要做到这一点,Linux 提供了一套"虚拟设备"让命名空间之间能打通:veth(一对首尾相连的虚拟网线,一端进容器 netns、一端进宿主)、网桥/OVS(把多台虚拟网卡桥接成一个二层局域网)。理解它先从"命名空间 + 虚拟设备"这套概念出发,容器网络就不再是"黑魔法"。

二、单机怎么通:veth + 网桥把容器连成一个虚拟局域网

一个容器"联网"的典型路径:Linux 造一个 netns 给容器 → 在宿主 netns 里造一个 Linux bridge(桥,如 docker0)→ 用一对 veth 把容器 netns 和 bridge 各挂一端 → 容器就获得了 bridge 上的一个二层接口与 IP,容器间、容器与宿主就能互通(容器出外网再走 bridge + NAT/路由)。自托管手搓也能还原这套(`ip netns add`、`ip link add veth0 type veth peer name veth1`、`ip link set ... master bridge`),方便排障时自己加点/dev 容器对比理解。下面是一段"手搓一个网络命名空间并接上 bridge"的最小实验。

# 造一个虚拟局域网的最小手工实验(root 下)
# 1) 命名空间 + 网桥 + veth 对
ip netns add ns1
ip link add br0 type bridge
ip link set br0 up
ip link add veth0 type veth peer name veth1
# 2) veth 一端进命名空间、一端挂桥
ip link set veth1 netns ns1
ip link set veth0 master br0
ip link set veth0 up
# 3) 给命名空间里的端配 IP 并启用
ip netns exec ns1 ip addr add 172.17.0.2/24 dev veth1
ip netns exec ns1 ip link set veth1 up
ip netns exec ns1 ip link set lo up
# 4) 验证:从命名空间 ping 网桥上的宿主接口
ip netns exec ns1 ping -c1 172.17.0.1

手搓的坑:忘给 veth/桥 `up`,接口处于 DOWN;没在 netns 里启 lo;配完不 `ip netns exec` 验证;忘了 bridge 需要有网关/NAT 才能出公网。对绝大多数人,用 Docker/CNI 现成桥即可,但会手搓一下就"看得懂它们是这么拼的"。

三、跨主机怎么办:overlay 网络把"多个单机局域网"织成一张大网

单机上桥只能解决一台里的容器互通;多台宿主机要互通就得用"overlay(覆盖)网络":在每台宿主上虚拟出一个"同名逻辑网段",容器照常用自己网段的 IP,实际跨主机包被封装(如 VXLAN 封装在 UDP 里)走宿主物理网络转发——对上层容器而言"像在同一张内网"。Docker Swarm/K8s 的 overlay 网络、CNI 的 VXLAN/Calico 等网络插件,本质上都是这套"虚拟网段 + 跨机封装"的实现。选型上:纯二层 VXLAN 编配简单、跨主机丢包略高、好用在局域网/同网段;Calico 之类基于路由/BGP 的更可扩展、适合更大规模(也更复杂)。理解 overlay 先抓"逻辑网段统一 + 跨机封装"两点。

# VXLAN 的最小手动示例(两宿主 h1/h2,物理 eth0 上建 overlay)
# h1:
ip link add vx0 type vxlan id 100 dev eth0 remote 10.0.0.22 dstport 4789
ip addr add 172.19.0.1/24 dev vx0 && ip link set vx0 up
# h2:同样的 id,remote 指到 h1
ip link add vx0 type vxlan id 100 dev eth0 remote 10.0.0.21 dstport 4789
ip addr add 172.19.0.2/24 dev vx0 && ip link set vx0 up
# 现在 h1/h2 之间能 ping 通 172.19.0.x,即"跨主机一张内网"的雏形

overlay 的坑:MTU——封装多了帧头,物理链路 MTU 不调(降到 ~1450 或设好 DF)会导致大包不传;UDP 端口(VXLAN 4789)被防火墙挡导致跨机不通;路由/网关不配使跨网段出不去。

四、边界与排障:命名空间替你"隔离",overlay 替你"互联"

三者各司其职:netns 负责"隔离"(给容器独立网络)、veth/桥负责"打通单机"、overlay 负责"跨机互联"。边界要认清:命名空间是"网络栈隔离",不替代"进程级安全"(root 权限、能力、挂载隔离还要靠其它机制);overlay 是"逻辑网段",不改变底层物理网络的延迟与带宽。排障优先级也清晰:单机不通先 `ip netns exec` + `ip link/addr`,跨机先查 MTU、UDP 端口与路由。把这几层想明白,容器网络的"玄学"就变成了"可复现的诊断"。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

systemd 服务加固实战:让服务不 root、不裸跑、破坏面最小

Elasticsearch 集群实战:分片扩容、安全下线与 reindex 数据迁移

评 论
更换验证码