网络命名空间
面试题
什么是 Linux 网络命名空间?Docker 是如何利用它实现容器网络隔离的?
标准答案
网络命名空间(Network Namespace)是 Linux 内核提供的网络隔离机制。每个网络命名空间拥有完全独立的网络栈——包括网络接口、路由表、iptables 规则、端口号空间等。这是 Docker 容器网络隔离的基石。
什么是网络命名空间
# 查看系统中的网络命名空间
ip netns list
# 或者
lsns -t net
每个网络命名空间是一个独立的网络环境:
– 自己的网络设备(lo、eth0 等)
– 自己的 IP 地址池和路由表
– 自己的 iptables/iptables6 规则
– 自己的 socket 端口号空间(容器 A 和容器 B 都可以用 80 端口)
Docker 与网络命名空间
# 每个 Docker 容器有自己的网络命名空间
docker run -d --name container-a nginx
docker run -d --name container-b nginx
# 查看容器的网络命名空间路径
docker inspect --format='{{.NetworkSettings.SandboxKey}}' container-a
# /var/run/docker/netns/xxxxxxxx
# 查看容器和命名空间的关联
lsns -t net | grep docker
容器网络命名空间的结构
宿主机网络命名空间(默认)
┌──────────────────────────────────┐
│ eth0 (物理网卡): 192.168.1.100 │
│ docker0: 172.17.0.1 │
│ vethXXX → 容器 A │
│ vethYYY → 容器 B │
│ iptables NAT/Masquerade │
│ 路由表 │
└────────┬─────────────────────────┘
│
│ veth pair(虚拟网线)
│
┌────────┴──────────┐ ┌─────────┴──────────┐
│ 容器 A 命名空间 │ │ 容器 B 命名空间 │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ lo: 127.0.0.1│ │ │ │ lo: 127.0.0.1│ │
│ │ eth0: 172.17 │ │ │ │ eth0: 172.17 │ │
│ │ │ │ │ │ │ │
│ │ 路由表 │ │ │ │ 路由表 │ │
│ │ 端口 80 │ │ │ │ 端口 80 │ │
│ └──────────────┘ │ │ └──────────────┘ │
└────────────────────┘ └────────────────────┘
核心机制:veth pair
网络命名空间之间不能直接通信,需要通过 veth pair(虚拟以太网对)连接:
# veth pair 像一根虚拟网线
# 一端在容器命名空间(eth0)
# 另一端在宿主机命名空间(vethXXX)
# 在宿主机上查看
ip link show | grep veth
# 12: veth12ab@if3: ...
# 13: veth34cd@if4: ...
# 在容器内查看
docker exec container-a ip link show
# 1: lo: ...
# 3: eth0@if12: ...
# 注意 eth0@if12 的 12 对应宿主机上的 veth12ab
手动模拟容器网络隔离
# 创建网络命名空间
ip netns add ns1
ip netns add ns2
# 在命名空间中启动回环接口
ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
# 创建 veth pair
ip link add veth1 type veth peer name veth1-peer
ip link add veth2 type veth peer name veth2-peer
# 将一端放到命名空间
ip link set veth1-peer netns ns1
ip link set veth2-peer netns ns2
# 分配 IP
ip netns exec ns1 ip addr add 10.0.0.1/24 dev veth1-peer
ip netns exec ns2 ip addr add 10.0.0.2/24 dev veth2-peer
# 启用接口
ip netns exec ns1 ip link set veth1-peer up
ip netns exec ns2 ip link set veth2-peer up
# 创建网桥连接两个命名空间
ip link add name bridge0 type bridge
ip link set bridge0 up
ip link set veth1 master bridge0
ip link set veth2 master bridge0
ip link set veth1 up
ip link set veth2 up
# 测试连通性
ip netns exec ns1 ping 10.0.0.2 # ✅ 互通
命名空间中的独立性
# 1. 独立的路由表
docker exec container-a ip route
# default via 172.17.0.1 dev eth0
# 172.17.0.0/16 dev eth0 scope link src 172.17.0.2
docker exec container-b ip route
# default via 172.17.0.1 dev eth0
# 172.17.0.0/16 dev eth0 scope link src 172.17.0.3
# 2. 独立的端口号空间
docker exec container-a sh -c "nc -l -p 5000 &" # 在 5000 端口监听
docker exec container-b sh -c "nc -l -p 5000 &" # 同样可以在 5000 端口监听
# 3. 独立的 iptables
docker exec container-a iptables -L # 容器 A 的规则
docker exec container-b iptables -L # 容器 B 的规则
# 4. 独立的 /proc/net
docker exec container-a cat /proc/net/tcp # 只看到本容器的连接
调试命名空间
# 进入容器的网络命名空间(宿主侧)
nsenter -t $(docker inspect -f '{{.State.Pid}}' container-a) -n ip addr
# 查看某个 PID 所属的网络命名空间
ls -l /proc/$(docker inspect -f '{{.State.Pid}}' container-a)/ns/net
# 网络命名空间的继承
# 如果使用 --network host,容器使用宿主命名空间
# 如果使用 --network container:xxx,容器共享另一个容器的命名空间
面试问答
问:网络命名空间和安全隔离有什么关系?
网络命名空间提供隔离但共享内核。容器 A 无法直接访问容器 B 的网络接口、IP 或端口,但如果双方都在同一个网桥上,它们可以在网络层通信(通过 veth + 网桥转发)。
问:容器删除后网络命名空间会自动销毁吗?
会。容器被删除后,它的网络命名空间也会被销毁,所有相关的 veth 对也会被清理。但要注意,某些异常情况可能导致残留的命名空间。
问:–network host 模式下网络命名空间是怎样的?
不使用独立的网络命名空间,容器直接使用宿主机的网络栈。意味着容器看到的路由表、iptables、网络设备都和宿主机一样,没有隔离。
问:一个容器能否加入多个网络命名空间?
一个容器只能有”一个”网络命名空间。但一个容器可以有多个网络接口,分别连接到不同的 Docker 网络(每个网络分配一个接口),所有接口在同一个网络命名空间内。
总结
网络命名空间是容器网络隔离的基础设施,本质上是 Linux 内核提供的一种轻量级虚拟化技术。Docker 利用它实现:每个容器拥有独立 IP、独立端口空间、独立路由。veth pair 是连接不同命名空间的”网线”,网桥则是连接多根网线的”交换机”。


暂无评论内容