1. 从一个真实需求说起为什么要在OVS上折腾VXLAN数据中心里的虚拟机迁移、跨机架的二层互通、多租户网络隔离这几个需求凑在一起传统VLAN方案基本就顶不住了。VLAN只有12位标识符满打满算4094个可用网络而且跨三层设备透传二层广播域本身就是个麻烦事。我在实际项目里遇到过最头疼的场景是两个机柜各有一台宿主机上面跑着同一业务的虚拟机要求它们像插在同一台交换机上一样通信但中间隔着三层路由设备。这时候VXLAN就成了绕不开的选择。VXLAN的本质是把二层以太网帧封装进UDP里通过三层网络传输在两端解封装还原出二层帧。它用24位VNI标识符理论支持1600万个隔离网络彻底解决了VLAN数量瓶颈。而Open vSwitch作为一款开源虚拟交换机原生支持VXLAN隧道配置灵活还能和Linux内核的数据平面配合性能上也有保障。这篇内容适合谁看如果你已经对Linux网络基础、网桥概念、IP路由有一定了解并且手头有两台以上的Linux主机物理机或虚拟机都行想通过实际操作把VXLAN隧道跑通那接下来的内容就是为你准备的。我会从整体设计思路讲起把每一步配置背后的原因说清楚再给出完整的实操流程和排错经验。整个实验环境我用的是两台运行主流Linux发行版的虚拟机各自带一块业务网卡通过一个三层可达的网络互联。需要提前说明的是VXLAN本身只是一个封装协议它不负责控制平面。也就是说隧道对端地址、VNI与流量的映射关系需要你自己维护。在小规模场景下手工配置静态隧道完全够用大规模部署才需要引入EVPN之类的控制平面。我们这个实验走的是静态配置路线简单直接适合理解和入门。2. 实验环境搭建与核心概念对齐2.1 两台主机的网络规划先把实验拓扑说清楚。我准备了两台Linux主机分别叫hostA和hostB。每台主机有两块网卡一块用于管理/底层传输一块用于承载业务流量。管理网卡的地址段是192.168.100.0/24hostA是192.168.100.10hostB是192.168.100.20。这两台主机之间三层可达能互相ping通这是VXLAN隧道建立的前提。业务侧我规划了两个网段10.10.10.0/24和10.10.20.0/24分别对应VNI 100和VNI 200。hostA上创建两个内部端口IP分别是10.10.10.1和10.10.20.1hostB上对应10.10.10.2和10.10.20.2。目标是让hostA的10.10.10.1能ping通hostB的10.10.10.2同时10.10.20.1能ping通10.10.20.2而且两个VNI的流量互相隔离。这里有个关键点VXLAN的底层传输依赖UDP默认目的端口是4789。有些环境里会用到8472这是早期Linux内核实现的历史遗留现在标准端口是4789。我建议统一用4789避免兼容性问题。2.2 OVS的安装与基础检查安装OVS在不同发行版上命令略有差异。以常见的RPM系和DEB系为例RPM系用包管理器安装openvswitch和openvswitch-kmod如果需要内核模块DEB系则是openvswitch-switch和openvswitch-common。安装完成后用ovs-vsctl show检查数据库连接是否正常用ovs-vsctl --version确认版本。我用的版本是2.17.x这个版本对VXLAN的支持已经很成熟了。安装完第一件事是启动服务。systemd环境下执行systemctl enable --now openvswitch然后确认ovsdb-server和ovs-vswitchd两个进程都在跑。如果ovs-vsctl show报数据库连接失败八成是服务没起来或者socket路径不对。可以用systemctl status openvswitch看详细日志。提示有些发行版默认没加载openvswitch内核模块需要手动modprobe openvswitch。如果modprobe报错检查内核头文件包是否安装必要时重新编译内核模块。2.3 VXLAN、VNI、VTEP这几个概念的关系在动手之前把几个术语理清楚能少走很多弯路。VTEP是VXLAN隧道端点每台参与VXLAN通信的主机就是一个VTEP它负责封装和解封装。VNI是VXLAN网络标识符类似VLAN ID但位数更多用来区分不同的虚拟二层网络。隧道的目的地址就是对端VTEP的底层IP。打个比方VXLAN隧道就像两个小区之间修的地下通道VTEP是通道两端的入口VNI是通道里划分的不同车道底层IP是通道入口的地址。数据帧从hostA的某个VNI车道进入通道到达hostB后从对应VNI车道出来中间走的是三层网络但两端感觉像直连。OVS里创建VXLAN端口时需要指定remote_ip和key。remote_ip是对端VTEP地址key就是VNI。如果有多对端可以创建多个VXLAN端口或者用ovs-vsctl的set interface命令动态添加remote_ip。3. 核心配置实操从零把隧道跑通3.1 hostA上的完整配置流程先创建网桥。我习惯用br-vxlan作为网桥名清晰好记。执行ovs-vsctl add-br br-vxlan。这个网桥是OVS管理的虚拟交换机后面所有端口都挂到它上面。接着创建VXLAN隧道端口。命令是ovs-vsctl add-port br-vxlan vxlan100 -- set interface vxlan100 typevxlan options:remote_ip192.168.100.20 options:key100。这条命令做了三件事在br-vxlan上添加一个名为vxlan100的端口指定类型为vxlan设置对端IP为hostB的管理地址VNI为100。同理再创建vxlan200key改成200。然后创建内部端口也就是业务侧的虚拟网卡。ovs-vsctl add-port br-vxlan veth100 -- set interface veth100 typeinternal。这个internal类型的端口会在宿主机上生成一个同名网卡可以配IP。给它配上10.10.10.1/24ip addr add 10.10.10.1/24 dev veth100然后ip link set veth100 up。veth200同理配10.10.20.1/24。这里有个细节internal端口默认可能在DOWN状态必须手动up。另外如果宿主机有NetworkManager或systemd-networkd在管理网卡可能会干扰OVS创建的internal端口建议把这些端口加入排除列表或者干脆停掉网络管理服务用ip命令手工管理。3.2 hostB上的对称配置hostB的配置和hostA镜像对称。创建br-vxlan网桥添加vxlan100和vxlan200端口但remote_ip要指向hostA的192.168.100.10。internal端口veth100配10.10.10.2/24veth200配10.10.20.2/24。配置完成后用ovs-vsctl show检查两端的端口状态。正常情况下vxlan端口的type是vxlanoptions里能看到remote_ip和key。internal端口应该显示为internal类型并且有对应的Linux网卡。3.3 验证隧道连通性先在hostA上ping hostB的底层地址确认三层可达。然后ping业务地址ping 10.10.10.2。如果通了说明VNI 100的隧道工作正常。再ping 10.10.20.2验证VNI 200。如果ping不通按这个顺序排查先看ovs-vsctl show里vxlan端口是否真的创建成功再看ip link show确认internal端口是UP状态然后用tcpdump -i 底层网卡 udp port 4789抓包看封装后的UDP报文有没有发出去、有没有收到回包。我遇到过最常见的问题是防火墙没放行UDP 4789或者底层网卡的路由不对导致封装报文发不出去。注意VXLAN封装后的报文源地址是底层网卡的IP目的地址是对端VTEP的IP。如果底层网络有NAT设备VXLAN可能无法正常工作因为NAT会改写端口和地址导致解封装失败。这个实验要求底层网络是纯三层可达不做NAT。3.4 用流表验证VNI隔离两个VNI都通了之后可以进一步验证隔离性。在hostA的veth100上ping hostB的10.10.20.2应该不通因为VNI 100和VNI 200是隔离的。如果通了说明配置有问题可能是两个VXLAN端口挂到了同一个网桥上但没有正确区分VNI或者流表把流量泛洪了。OVS默认的NORMAL流表会根据VLAN和VNI做转发决策。在VXLAN场景下每个VXLAN端口对应一个VNIinternal端口如果不打VLAN标签默认走VNI 0。所以更严谨的做法是给internal端口打上VLAN标签再通过流表把VLAN和VNI做映射。不过对于这个基础实验两个VNI各自独立不配VLAN也能工作因为OVS会把不同VXLAN端口的流量按VNI隔离。4. 进阶话题多播、流表与性能调优4.1 从静态单播到多播的取舍前面配的是静态单播隧道每端都要手动指定对端IP。如果只有两台主机这没问题。但如果有三台、五台甚至更多VTEP需要互通手工配置的工作量就上来了而且新增节点要改所有现有节点的配置。这时候可以考虑多播模式VXLAN端口不指定remote_ip而是加入一个多播组底层网络负责把广播、未知单播、多播流量复制到组内所有VTEP。多播模式配置更简单但依赖底层网络支持多播路由。很多云环境或跨网段场景下多播是被禁用的所以实际生产里静态单播配合自动化脚本更常见。我的建议是小规模5台以内用静态单播脚本批量下发大规模上EVPN控制平面让BGP自动分发VTEP和VNI信息。4.2 流表精细化控制默认的NORMAL流表虽然能用但不够灵活。比如你想让VNI 100的流量走特定的底层路径或者做QoS限速就需要写自定义流表。OVS的流表语法和OpenFlow兼容可以用ovs-ofctl add-flow添加。举个例子把VNI 100的广播流量限速到1Mbps先创建QoS策略再在流表里匹配VNI字段并应用QoS。这个操作需要先ovs-vsctl set interface vxlan100 ingress_policing_rate1000再配合流表匹配。实际配置时要注意VXLAN的VNI在OVS里对应的是tunnel_id字段流表匹配用tun_id100。流表调试可以用ovs-ofctl dump-flows br-vxlan查看当前流表用ovs-appctl ofproto/trace模拟报文转发路径。这两个命令是排错利器能清楚看到报文在OVS内部走了哪条流表、做了哪些动作。4.3 性能相关的几个关键参数VXLAN封装解封装有CPU开销尤其是小包场景。几个优化方向一是开启网卡的TSO、GRO、GSO等卸载功能让硬件分担部分计算二是调整OVS的other_config参数比如max-idle和max-revalidator影响流表老化时间三是如果内核支持用ovs-vsctl set Open_vSwitch . other_config:dpdk-inittrue启用DPDK数据平面把转发放到用户态轮询大幅提升吞吐但会占用专用CPU核。我实测下来在普通千兆环境下不开启DPDK单隧道吞吐能到900Mbps左右接近线速。万兆环境下如果不开DPDK小包转发率会明显下降这时候DPDK或者智能网卡卸载就很有必要了。不过DPDK配置复杂对网卡型号有要求入门阶段先把基础隧道跑通性能优化可以后续再搞。5. 踩坑实录与常见问题速查5.1 隧道不通的排查思路隧道不通是最常见的问题我整理了一个排查顺序表按这个顺序走基本能定位到根因。排查步骤检查命令预期结果常见异常底层连通性ping 对端VTEP IP通路由缺失、防火墙拦截OVS服务状态ovs-vsctl show正常显示网桥和端口数据库连接失败、服务未启动VXLAN端口状态ovs-vsctl list interface vxlan100typevxlanoptions正确remote_ip写错、key不匹配internal端口状态ip link show veth100UP状态有IP端口DOWN、IP未配封装报文抓包tcpdump -i eth0 udp port 4789有UDP报文进出只有出没有进对端未响应流表检查ovs-ofctl dump-flows br-vxlan有NORMAL或自定义流表流表为空或匹配错误我遇到过一次诡异的情况两端配置完全对称底层也通但业务ping就是不通。抓包发现hostA发出了封装报文hostB也收到了但hostB没有解封装。最后查出来是hostB的OVS版本和hostA不一致hostB的VXLAN实现有个bug升级到相同版本后解决。所以实验环境尽量保持两端软件版本一致能省很多事。5.2 MTU问题最容易被忽略的坑VXLAN封装会增加开销外层IP头20字节UDP头8字节VXLAN头8字节总共36字节。如果底层网卡MTU是1500那么业务侧能用的最大MTU就是1500-361464。如果业务报文超过1464且设置了DF位就会被丢弃表现为ping大包不通、TCP连接卡顿。解决办法有两个一是把业务侧internal端口的MTU调小到1464ip link set veth100 mtu 1464二是把底层网卡MTU调大到1550或更高让封装后不超过底层MTU。生产环境通常用第二种因为调小业务MTU可能影响应用性能。但调大底层MTU需要全网设备支持包括中间的路由器和交换机所以要先确认底层网络的最大MTU。提示用ping -M do -s 1472 对端业务IP测试147281480是ICMP载荷加上IP头20字节正好1500。如果这个ping不通但小包通基本就是MTU问题。5.3 多网桥场景下的路由冲突如果宿主机上已经有其他网桥或网络命名空间可能会和OVS的internal端口产生路由冲突。比如默认路由指向了错误的网卡导致封装报文的源地址不对。这时候要用ip route get 对端VTEP IP确认路由走向必要时添加策略路由指定VXLAN流量走特定网卡。另一个常见问题是ARP表混乱。internal端口和物理网卡如果在同一网段ARP响应可能从错误的接口发出。解决办法是给internal端口配一个独立的子网或者用VRF做隔离。OVS本身支持多网桥可以把管理流量和业务流量分到不同网桥减少干扰。5.4 重启后配置丢失的应对OVS的配置默认保存在数据库里重启后应该自动恢复。但internal端口的IP地址是用ip命令配的不在OVS数据库里重启后会丢。解决办法是把IP配置写进启动脚本或者用ovs-vsctl的set interface命令把IP配置也纳入OVS管理部分版本支持。更稳妥的做法是用配置管理工具统一管理确保每次重启后状态一致。我在实际项目里还遇到过OVS数据库损坏导致配置全丢的情况虽然概率很低但一旦发生很麻烦。建议定期备份/etc/openvswitch/conf.db出问题时可以快速恢复。6. 从实验到生产的距离把两台主机的VXLAN隧道跑通只是第一步。真实生产环境里VTEP数量可能几十上百VNI数量上千手工配置完全不现实。这时候需要引入自动化工具比如用Ansible批量下发OVS配置或者用Python脚本调用OVSDB接口动态创建隧道。再往上就是EVPN方案用BGP作为控制平面VTEP和VNI信息自动分发支持多活和快速收敛。另一个生产环境必须考虑的是高可用。单台VTEP故障会导致该节点上所有业务网络中断。常见的做法是双网卡绑定做底层冗余OVS层面用bond端口聚合再配合BFD快速检测链路故障。如果业务对中断极度敏感还需要考虑多活VTEP方案这涉及更复杂的控制平面设计。监控方面OVS提供了ovs-appctl系列命令查看端口统计、流表命中率、丢包计数。可以对接Prometheus做长期监控设置告警阈值。我习惯重点关注rx_dropped和tx_dropped两个指标它们能反映MTU问题、缓冲区溢出等常见故障。最后分享一个我在实际调试中总结的小技巧每次修改OVS配置前先用ovs-vsctl show和ovs-ofctl dump-flows把当前状态保存下来改完后对比差异。这样一旦出问题能快速回滚到已知正常的状态。OVS的配置命令大多支持--may-exist参数重复执行不会报错适合写在脚本里做幂等操作。
阅读完成 · 觉得有帮助?