veth pair 设备

veth pair 设备

面试题

什么是 veth pair?它在 Docker 网络中扮演什么角色?如何查看和管理 veth 设备?

标准答案

veth pair(Virtual Ethernet Pair)是 Linux 内核中的虚拟网络设备,由一对虚拟网卡组成,是 Docker 容器网络通信的核心通道。

什么是 veth pair

# veth pair 是一对虚拟以太网卡
# 像一根"虚拟网线"
# 一端发送的数据,另一端立即收到

# visual:
# [容器A:eth0] ===[网线]=== [宿主机:vethXXX]
# [容器B:eth0] ===[网线]=== [宿主机:vethYYY]

veth pair 的特性

# 1. 成对出现
#    创建时生成两张虚拟网卡,删除时一起删除

# 2. 数据穿透
#    一端收到的数据立即出现在另一端
#    就像一根直连的以太网线

# 3. 可跨命名空间
#    一端可以在一个网络命名空间
#    另一端可以在另一个网络命名空间

# 4. 没有物理限制
#    是纯软件实现,没有带宽、距离限制

查看 veth 设备

# 1. 查看所有 veth 设备(宿主机端)
ip link show type veth

# 输出示例
# 12: vethabc123@if11:  mtu 1500
#     link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
#     ↑ veth 宿主机端  ↑ 容器端 if11

# 2. 查看详细统计
ip -s link show vethabc123
# 可以看到收发字节数、包数、错误数等

# 3. 查看 veth 连接到了哪个网桥
bridge link show | grep veth
# 12: vethabc123 state UP @docker0

容器内的对应设备

# 在容器内部,veth pair 的另一端显示为 eth0
docker exec my-container ip addr show eth0

# 11: eth0@if12:  mtu 1500
#     link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
#     inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0

# @if12 表示其对端是宿主机上的 ifindex 12(即 vethabc123)

veth pair 的数据传输流程

# 容器 A → 容器 B 的数据流

# 1. 容器 A 的应用发送数据
#    目标 IP: 172.17.0.3(容器 B)

# 2. 容器 A 的 eth0 发出数据包
#    vethA(容器端)收到并立即传递给 vethA(宿主机端)

# 3. vethA(宿主机端)连接到 docker0 网桥
#    数据包进入 docker0

# 4. docker0 根据 MAC 地址表查找
#    目标 MAC 对应 vethB 端口

# 5. 数据包从 vethB(宿主机端)发送
#    立即出现在 vethB(容器端)

# 6. 容器 B 的 eth0 收到数据包
#    交给容器 B 的网络栈处理

# 整个过程不需要物理网卡参与
# 纯内核空间内的内存拷贝

手动创建 veth pair

# 创建一个 veth pair
sudo ip link add veth0 type veth peer name veth1

# 查看
ip link show type veth
# 12: veth0@veth1: ...
# 13: veth1@veth0: ...

# 分配 IP
sudo ip addr add 192.168.1.1/24 dev veth0
sudo ip addr add 192.168.1.2/24 dev veth1

# 启用
sudo ip link set veth0 up
sudo ip link set veth1 up

# 测试连通性
ping -c 2 192.168.1.2 -I veth0

# 删除
sudo ip link delete veth0
# 注意:删除一个,两个一起消失

将 veth 放入不同命名空间

# 创建两个网络命名空间
sudo ip netns add ns1
sudo ip netns add ns2

# 创建 veth pair
sudo ip link add veth-ns1 type veth peer name veth-ns2

# 分别放入不同命名空间
sudo ip link set veth-ns1 netns ns1
sudo ip link set veth-ns2 netns ns2

# 配置 IP
sudo ip netns exec ns1 ip addr add 10.0.0.1/24 dev veth-ns1
sudo ip netns exec ns2 ip addr add 10.0.0.2/24 dev veth-ns2

# 启用
sudo ip netns exec ns1 ip link set veth-ns1 up
sudo ip netns exec ns2 ip link set veth-ns2 up

# 测试
sudo ip netns exec ns1 ping 10.0.0.2
# ✅ 命名空间 ns1 和 ns2 可以通过 veth pair 通信

# 这模拟了 Docker 容器网络的基本原理

性能特征

# veth pair 的性能特征

# 1. 接近于原生性能
#    纯内核实现,没有上下文切换开销
#    实测可达 ~10Gbps 以上

# 2. 主要性能损耗
#    - MTU 限制需分段
#    - 过多的 iptables 规则
#    - 数据包在多个命名空间间穿越

# 3. 优化建议
#    - 增大 MTU(9000 巨帧)
#    - 减少不必要的 iptables 规则
#    - 使用多队列 veth

常见问题排查

# 1. 查看 veth 连接到了哪个网桥
bridge link show

# 2. 查看容器对应的 veth
CONTAINER_IP=$(docker inspect -f '{{.NetworkSettings.IPAddress}}' my-container)
ip link show | grep -B1 "$CONTAINER_IP\|veth"

# 3. 查看 veth 的统计数据
ip -s link show vethabc123
# RX: bytes  packets  errors  dropped
# TX: bytes  packets  errors  dropped

# 4. 通过 veth 抓包
tcpdump -i vethabc123 -n

# 5. 找到容器 PID 对应的 veth
PID=$(docker inspect -f '{{.State.Pid}}' my-container)
cat /proc/$PID/net/if_inet6 | grep eth0
# 查看容器 eth0 的 MAC
MAC=$(docker exec my-container cat /sys/class/net/eth0/address)
# 在宿主机找这个 MAC
ip link show | grep -i "$MAC" -B1

面试官追问

问:veth pair 和 tap/tun 设备有什么区别?

答:
veth pair:工作在第 2 层(数据链路层),成对出现,用于连接两个网络命名空间
tap 设备:工作在第 2 层,供用户空间程序处理以太网帧(QEMU/KVM 虚拟机常用)
tun 设备:工作在第 3 层(网络层),供用户空间程序处理 IP 包(OpenVPN 常用)

veth 是最轻量的虚拟网络设备,无需用户空间程序参与,只在内核空间完成数据转发。

问:一个容器可以有多少个 veth pair?

答:理论上可以有很多,每个额外的网络接口就是一个 veth pair。在 Docker 中,每个网络对应一个 veth pair。所以如果一个容器连接了 3 个网络,它在容器内会有 3 个 eth 设备(eth0、eth1、eth2),宿主机上就有 3 个对应的 veth 设备。

问:为什么不直接用网桥而要先用 veth pair?

答:网桥工作在宿主机的网络命名空间中。容器在独立的网络命名空间中,不能直接连接宿主机上的网桥。veth pair 的作用就是穿透命名空间边界——一端在容器命名空间,另一端在宿主机命名空间,数据可以通过 veth pair 穿越命名空间边界到达网桥。

总结

veth pair 是 Docker 网络的基础设施,它像一根”虚拟网线”连接了容器的网络命名空间和宿主机的网络栈。每启动一个容器,Docker 就创建一对 veth,一端变成容器的 eth0,另一端连到 docker0 网桥。理解 veth pair 是理解 Docker 网络底层机制的关键。

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容