带有 OVS 的 LXC 容器网络无法正确转发 ARP

带有 OVS 的 LXC 容器网络无法正确转发 ARP

使用 lxc 容器,我想单独模拟网络组件。为此,我尝试将 OVS 嵌入到 lxc 容器中。

最初,我采用以下设置,该设置运行正常并且两个主机可以互相 ping 通:

+---------------+ +---------------+
|     host1     | |     host2     |
| testnode-eth0 | | testnode-eth1 |
+-------|-------+ +-------|-------+
        |                 |
      vbr0--------------vbr1

host1 和 host2 是 lxc 容器,通过 testnode-ethX 绑定到 vbrX,它们是一对连接的 veth。testnode-ethX 具有 IP 地址和正确的路由。

现在我在中间启动一个 OVS 实例,将其命名为 switch1:

+---------------+ +-------------------------------+ +---------------+
|     host1     | |            switch1            | |     host2     |
| testnode-eth0 | | testnode-eth1   testnode-eth3 | | testnode-eth2 |
+-------|-------+ +-------|---------------|-------+ +-------|-------+
        |                 |               |                 |
      vbr0--------------vbr1            vbr3--------------vbr2

该设置与上述设置类似。这次,testnode-eth0、switch1 和 testnode-eth2 都有 IP 地址。交换机以独立模式运行,配置如下:

3bc3442a-1e83-4e51-ac80-10a618be0a62
    Bridge switch1
        fail_mode: standalone
        Port switch1
            Interface switch1
                type: internal
        Port testnode-eth1
            Interface testnode-eth1
        Port testnode-eth3
            Interface testnode-eth3
    ovs_version: "2.13.8"
----
OFPT_FEATURES_REPLY (xid=0x2): dpid:0000000000000001
n_tables:254, n_buffers:0
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
 1(testnode-eth1): addr:00:16:3e:77:1a:af
     config:     0
     state:      0
     current:    10GB-FD COPPER
     speed: 10000 Mbps now, 0 Mbps max
 2(testnode-eth3): addr:00:16:3e:a8:d6:0f
     config:     0
     state:      0
     current:    10GB-FD COPPER
     speed: 10000 Mbps now, 0 Mbps max
 LOCAL(switch1): addr:00:11:22:33:44:55
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0

当我从 host1 向 host2 发送 ping 时,host1 首先尝试对 host2 进行 arp 解析。Host1 发送 arp 请求,该请求可以顺利到达 host2。然后 Host2 发送 arp 回复,我可以使用 vrb2 和 vbr3 上的 tcpdump 观察到该回复。但回复从未到达 testnode-eth3。通过转储流量,我可以看到数据包计数器随着 arp 请求而增加,但接口上没有收到任何回复。示例:

OFPST_PORT reply (xid=0x2): 3 ports
  port LOCAL: rx pkts=147, bytes=5652, drop=0, errs=0, frame=0, over=0, crc=0
           tx pkts=16, bytes=1216, drop=0, errs=0, coll=0
  port  "testnode-eth1": rx pkts=123, bytes=5934, drop=0, errs=0, frame=0, over=0, crc=0
           tx pkts=56, bytes=4208, drop=0, errs=0, coll=0
  port  "testnode-eth3": rx pkts=24, bytes=1776, drop=0, errs=0, frame=0, over=0, crc=0
           tx pkts=155, bytes=8366, drop=0, errs=0, coll=0
==> send arp requests from host1 to host2, host 2 replies with equal amount of replies
OFPST_PORT reply (xid=0x2): 3 ports
  port LOCAL: rx pkts=153, bytes=5820, drop=0, errs=0, frame=0, over=0, crc=0
           tx pkts=16, bytes=1216, drop=0, errs=0, coll=0
  port  "testnode-eth1": rx pkts=129, bytes=6186, drop=0, errs=0, frame=0, over=0, crc=0
           tx pkts=56, bytes=4208, drop=0, errs=0, coll=0
  port  "testnode-eth3": rx pkts=24, bytes=1776, drop=0, errs=0, frame=0, over=0, crc=0
           tx pkts=161, bytes=8618, drop=0, errs=0, coll=0

我可以看到 eth1 上的 rx 计数器和 eth3 上的 tx 计数器增加(arp 请求),但 eth3 rx 上从未收到 arp 响应。这使我相信目标流量(arp 响应)未转发到 lxc 容器。我如何让 vbr3 将所有流量转发到 testnode-eth3,以及如何让 testnode-eth3 接受所有数据包,甚至不是针对它的数据包?

我到目前为止尝试过的:

  • 启用 ip_forward(主机 + 容器)
  • 禁用 arp_filter(主机 + 容器 + 所有接口)
  • 将 ips 添加到 testnode-eth1 和 testnode-eth3(无论哪种方式都不起作用)
  • 使用特权或非特权运行 lxc 容器
  • 指定 switch1 上针对特定端口或 switch1 接口本身的路由。没有区别。
  • 已验证 iptables 不会干扰。所有链 (INPUT/OUTPUT/FORWARD) 始终接受,在容器中 iptables 不存在。
  • 所有接口均处于 up 状态
  • 所有接口都尝试过使用和不使用混杂模式
  • net.ipv4.conf.*.forwarding尝试在所有地方启用

更多信息:

  • 主机容器位于 Ubuntu 18.04 上
  • Switch 容器运行在 Ubuntu 20.04 上,OVS 2.13.8 处于独立模式
  • 机器运行在 Manjaro 5.19.1-3 上

用于启动容器网络的代码:

# Bootstrap bridge interfaces to connect containers
ip link add vbr0 type veth peer vbr1
ip link set dev vbr0 up
ip link set dev vbr1 up
ip link add vbr2 type veth peer vbr3
ip link set dev vbr2 up
ip link set dev vbr3 up

# Create switch container and attach to bridge ends
lxc init ovs switch1
lxc config set switch1 security.privileged true
lxc start switch1
lxc network attach vbr1 switch1 testnode-eth1 testnode-eth1
lxc exec switch1 --  ip link set dev testnode-eth1 up
lxc network attach vbr3 switch1 testnode-eth3 testnode-eth3
lxc exec switch1 --  ip link set dev testnode-eth3 up

# Restart ovs with custom parameters to be in full controll easily
lxc exec switch1 -- service openvswitch-switch stop
lxc exec switch1 -- service ovs-vswitchd stop
lxc exec switch1 -- service ovsdb-server stop
lxc exec switch1 -- rm -rf /var/run/openvswitch
lxc exec switch1 -- mkdir /var/run/openvswitch
lxc exec switch1 -- ovsdb-server --remote=punix:/var/run/openvswitch/db.sock --remote=db:Open_vSwitch,Open_vSwitch,manager_options --private-key=db:Open_vSwitch,SSL,private_key --certificate=db:Open_vSwitch,SSL,certificate --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert --log-file=/var/log/openvswitch/ovsdb-server.log --pidfile --verbose --detach
lxc exec switch1 -- ovs-vsctl init
lxc exec switch1 -- ovs-vswitchd --pidfile --detach
lxc exec switch1 -- ovs-vsctl  -- --if-exists del-br switch1 -- add-br switch1 -- set bridge switch1 controller=[] stp_enable=false other_config:datapath-id=0000000000000001 fail_mode=standalone other-config:disable-in-band=true other-config:dp-desc=switch1 other-config:hwaddr=00:11:22:33:44:55 -- add-port switch1 testnode-eth1 -- add-port switch1 testnode-eth3
lxc exec switch1 -- ip link set dev switch1 up

lxc exec switch1 --  ip addr add dev switch1 10.0.0.8/16
lxc exec switch1 --  ip route add 10.0.0.2 via 10.0.0.8
lxc exec switch1 --  ip route add 10.0.0.4 via 10.0.0.8

# Boostrap two simple hosts
lxc init simple-host host1
lxc start host1
lxc network attach vbr0 host1 testnode-eth0 testnode-eth0
lxc exec host1 --  ip link set dev testnode-eth0 up
lxc exec host1 --  ip addr add dev testnode-eth0 10.0.0.2/16
lxc exec host1 --  ip route add 10.0.0.4 via 10.0.0.2
lxc init simple-host host2
lxc start host2
lxc network attach vbr2 host2 testnode-eth2 testnode-eth2
lxc exec host2 --  ip link set dev testnode-eth2 up
lxc exec host2 --  ip addr add dev testnode-eth2 10.0.0.4/16
lxc exec host2 --  ip route add 10.0.0.2 via 10.0.0.4

如果您想亲自尝试这个精确的网络,这里有一些代码来导入我的图像(这个交换机图像基于 Ubuntu 18.04,但其他方面相同,有同样的问题):

wget https://friwi.me/testbed_img/ovs-ubuntu-18.04-minimal.tar.gz
wget https://friwi.me/testbed_img/simple-host-ubuntu-18.04-minimal.tar.gz
lxc image import ovs-ubuntu-18.04-minimal.tar.gz --alias ovs --public
lxc image import simple-host-ubuntu-18.04-minimal.tar.gz --alias simple-host --public

如果您需要更多信息,我很乐意提供。我已经在这个地方呆了好几天了,似乎找不到答案。非常感谢大家的帮助。

答案1

经过 6 天的调试,我终于搞定了。我在 vbr1<->testnode-eth1 和 vbr3<->testnode-eth3 之间随机添加了两个 Linux 桥接器 br1 和 br3,一切开始按预期运行。

相关内容