尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Open vSwitch (OVS) 虚拟交换机:从核心架构到跨主机网络部署实战

Open vSwitch (OVS) 虚拟交换机:从核心架构到跨主机网络部署实战 1. 从“虚拟交换机”说起为什么是OVS如果你在数据中心、云计算或者虚拟化环境里待过一阵子肯定对“虚拟交换机”这个概念不陌生。简单来说它就是在软件层面模拟出来的一个交换机负责连接虚拟机、容器或者物理网卡让它们之间能像插在同一个物理交换机上一样互相通信。早期的虚拟化方案比如VMware ESXi里的vSwitch或者KVM里用到的Linux Bridge都属于这类。它们好用吗对于简单的桥接和隔离确实够用。但当你开始玩更复杂的网络功能比如动态路由、流量监控、安全策略或者想把网络配置自动化起来的时候这些“传统”虚拟交换机的短板就暴露出来了功能有限、配置管理麻烦、对SDN软件定义网络的支持不够原生。这时候Open vSwitchOVS就登场了。我第一次接触OVS是在一个需要为OpenStack云平台搭建底层网络的时候。当时的诉求很明确我们需要一个能集中管理、支持丰富网络协议、并且能通过编程接口API灵活控制流量的虚拟交换机。OVS几乎是为这个场景量身定做的。它不仅仅是一个桥接工具更像是一个运行在用户空间的、功能完整的网络操作系统内核。你可以把它理解为一个开源的、软件定义的虚拟交换机它提供了我们期望从高端物理交换机上获得的大部分功能比如VLAN、QoS、流量监控sFlow/NetFlow甚至是隧道封装VXLAN, GRE, Geneve等。更重要的是它从一开始就为SDN设计其核心的OpenFlow协议让你可以通过控制器比如OpenDaylight, ONOS以编程的方式定义网络流量如何转发这彻底改变了网络运维的模式。所以当我们在说“构建OVS网络”时我们谈论的远不止是拉起一个虚拟网桥。我们是在用软件定义的方式构建一个灵活、可编程、易于自动化管理的虚拟网络基础设施。这个网络可以跨越多台物理服务器形成一个统一的、逻辑上的大二层或三层网络完美适配云原生、微服务、容器化这些现代架构对网络的动态需求。2. OVS的核心架构拆解“用户空间”与“内核空间”的协作要玩转OVS首先得理解它的“双空间”架构。这是OVS高性能和丰富功能的基础也是很多初学者配置时感到困惑的源头。OVS主要由两大组件构成运行在用户空间的ovs-vswitchd守护进程和运行在内核空间的datapath内核模块。### 2.1 用户空间的“大脑”ovs-vswitchdovs-vswitchd是OVS的控制平面你可以把它看作是网络的管理员和策略制定者。它负责处理所有复杂的逻辑维护流表Flow Table这是OVS的核心。流表里存放着一条条的流表项Flow Entry每条表项都像是一个交通规则规定了“什么样的数据包匹配条件应该执行什么动作比如转发到某个端口、修改包头、丢弃等”。ovs-vswitchd负责流表的计算、下发和更新。支持多种管理协议它通过OpenFlow协议与SDN控制器通信接收控制器下发的流表。同时它也支持OVSDBOVS Database管理协议用于配置端口、网桥等。实现高级网络功能像隧道封装/解封装VXLAN, GRE、连接跟踪Connection Tracking用于有状态防火墙、NAT等复杂功能都是在用户空间实现的。### 2.2 内核空间的“快车道”datapath内核模块datapath模块是OVS的数据平面它是性能的关键。它的工作模式非常巧妙首包上送当一个数据包第一次到达OVS管理的网桥时内核datapath里没有对应的快速转发规则。于是它把这个数据包或者其元数据上送到用户空间的ovs-vswitchd。流表计算ovs-vswitchd根据配置的流表和逻辑计算出这个数据包应该如何处理并生成一条对应的“快速路径”流表项。规则下发这条新的流表项被下发给内核datapath模块缓存起来。后续包直通之后所有匹配这条规则的数据包将直接在内核空间被快速处理转发、修改等无需再经过用户空间。这极大地提升了转发性能。这种架构带来的一个直接好处是灵活性和性能的平衡。复杂的控制逻辑在用户空间方便开发和扩展而高频的数据转发在内核空间保证了接近线速的性能。理解这一点对于后续的排错和性能调优至关重要。比如当你发现网络延迟异常高时可能需要检查是不是有大量“首包”产生例如海量的短连接导致数据包频繁在用户态和内核态之间切换。### 2.3 关键进程与工具除了上面两个核心还有几个重要的守护进程和命令行工具ovsdb-server负责管理OVS的配置数据库OVSDB。所有网桥、端口、控制器等配置信息都存储在这里。ovs-vswitchd会从它这里读取配置。ovs-vsctl最常用的命令行管理工具用于查询和修改OVSDB中的配置比如创建/删除网桥、添加端口、设置控制器等。ovs-ofctl用于直接管理OpenFlow流表的工具可以查看、添加、删除流表项是进行流表调试和高级控制的利器。3. 从零开始部署一个基础的OVS网络环境理论说得再多不如动手搭一个。我们假设在一个干净的Linux服务器以Ubuntu 22.04为例上从零开始构建一个最简单的OVS网络连接两个网络命名空间可以近似理解为两个轻量级虚拟机进行通信。### 3.1 系统准备与OVS安装首先更新系统并安装OVS的核心包。OVS的安装非常直接主流Linux发行版的仓库都提供了稳定的版本。# 更新软件包列表 sudo apt-get update # 安装Open vSwitch的核心组件 sudo apt-get install -y openvswitch-switch openvswitch-common # 安装后OVS的相关服务会自动启动。检查关键进程是否运行 sudo systemctl status openvswitch-switch.service安装完成后你会看到ovsdb-server和ovs-vswitchd进程已经在运行了。ovs-vsctl等命令行工具也可以直接使用。### 3.2 创建第一个OVS网桥与端口网桥Bridge是OVS中的核心抽象相当于一个虚拟交换机。我们来创建一个名为br0的网桥。# 创建一个新的OVS网桥 sudo ovs-vsctl add-br br0 # 查看网桥列表确认创建成功 sudo ovs-vsctl show执行ovs-vsctl show你会看到一个简单的输出显示了刚刚创建的网桥br0它目前还没有任何端口。接下来我们创建两个网络命名空间netns模拟两台需要联网的主机。# 创建两个网络命名空间命名为ns1和ns2 sudo ip netns add ns1 sudo ip netns add ns2现在我们需要创建虚拟网卡对veth pair。veth pair总是成对出现像一根虚拟的网线一端插在“主机”这里是root命名空间上另一端插在“客户机”网络命名空间上。我们将这对网卡的一端加入到OVS网桥另一端放入网络命名空间。# 创建第一对vethveth1-br 和 veth1-ns sudo ip link add veth1-br type veth peer name veth1-ns # 将veth1-br端口添加到OVS网桥br0 sudo ovs-vsctl add-port br0 veth1-br # 将veth1-ns这一端移入网络命名空间ns1 sudo ip link set veth1-ns netns ns1 # 对第二对veth重复上述操作 sudo ip link add veth2-br type veth peer name veth2-ns sudo ovs-vsctl add-port br0 veth2-br sudo ip link set veth2-ns netns ns2### 3.3 配置IP地址并测试连通性端口连接好了但还没配置IP和启动。我们来给命名空间内的网卡配置IP并启动它们同时启动主机侧的veth端口和OVS网桥。# 在命名空间ns1中配置IP并启动网卡 sudo ip netns exec ns1 ip addr add 192.168.100.10/24 dev veth1-ns sudo ip netns exec ns1 ip link set veth1-ns up sudo ip netns exec ns1 ip link set lo up # 顺便启动回环接口 # 在命名空间ns2中配置IP并启动网卡 sudo ip netns exec ns2 ip addr add 192.168.100.20/24 dev veth2-ns sudo ip netns exec ns2 ip link set veth2-ns up sudo ip netns exec ns2 ip link set lo up # 在主机侧启动连接到网桥的veth端口 sudo ip link set veth1-br up sudo ip link set veth2-br up # 启动OVS网桥本身它会自动管理其端口 sudo ip link set br0 up现在激动人心的时刻到了测试ns1和ns2之间的网络连通性。# 从ns1 ping ns2 sudo ip netns exec ns1 ping 192.168.100.20 -c 4如果一切顺利你应该能看到成功的ping回复。恭喜你你已经用OVS构建了一个最简单的二层网络两个命名空间就像接在了同一个交换机下的两台电脑可以互相通信。 注意这里我们手动配置了IP地址。在生产环境中IP地址通常由DHCP服务器分配。你可以在OVS网络中添加一个开启了DHCP服务的端口例如连接到一个提供DHCP的物理网络或一个DHCP容器或者使用更高级的SDN控制器来管理IP地址分配。4. 深入流表理解OVS的转发逻辑与排错利器基础连通性测试通过后我们来看看OVS到底是怎么转发数据包的。秘密就在流表里。上面我们用的是最简单的“学习交换机”模式OVS会自动学习MAC地址并生成流表。让我们来窥探一下。### 4.1 查看与解读OpenFlow流表使用ovs-ofctl工具可以查看网桥的流表。sudo ovs-ofctl dump-flows br0你可能会看到类似这样的输出cookie0x0, duration100.123s, table0, n_packets10, n_bytes980, idle_age30, priority0 actionsNORMAL这条流表项是OVS的默认行为。table0表示这是主流转发表Table 0。priority0是优先级数字越大优先级越高。actionsNORMAL是动作表示让OVS按照传统的“学习交换机”模式来处理数据包学习源MAC地址根据目的MAC地址在已知端口转发如果未知则泛洪。当我们从ns1pingns2后OVS会学习到veth1-ns的MAC地址并可能生成更具体的流表项。为了看到更清晰的流表我们可以先清空流表然后重新触发通信。# 清空br0的所有流表项 sudo ovs-ofctl del-flows br0 # 再次从ns1 ping ns2 sudo ip netns exec ns1 ping 192.168.100.20 -c 2 # 再次查看流表 sudo ovs-ofctl dump-flows br0现在你可能会看到新增的流表项它们明确匹配了源/目的MAC地址和端口并指定了转发动作。这就是OVS内核datapath加速的基础首包触发流表计算和下发后续包匹配这条精确规则快速转发。### 4.2 手动操纵流表实现简单策略流表的强大之处在于你可以手动编程。假设我们想实现一个简单的策略禁止ns1192.168.100.10访问ns2192.168.100.20。注意流表默认工作在二层匹配MAC地址。但我们可以利用OVS的“NORMAL”动作或更高级的流表来模拟三层过滤。一个更直接的方法是使用OVS的连接跟踪conntrack和OpenFlow来丢弃特定流量。这里我们先演示一个基于IP地址的简单丢弃需要OVS处理IP层。# 添加一条高优先级的流表项匹配从ns1端口进来且目的IP是ns2的IPv4流量动作为丢弃drop # 首先我们需要知道连接ns1的OVS端口号 PORT_NS1$(sudo ovs-vsctl get Interface veth1-br ofport) # 添加流表项。这是一个简化的示例实际匹配可能需要更多字段。 # 这条规则的意思是在table 0优先级为100高于默认的0匹配从端口$PORT_NS1进入、IPv4协议、目的IP为192.168.100.20的数据包执行丢弃动作。 sudo ovs-ofctl add-flow br0 table0, priority100, in_port$PORT_NS1, ip, nw_dst192.168.100.20, actionsdrop添加后立即再次从ns1pingns2会发现ping不通了。而ns2pingns1可能依然通取决于你是否添加了反向规则。这就是通过编程流表实现网络策略的基本原理。### 4.3 流表排错实战当ping不通时假设在搭建过程中ns1无法ping通ns2我们可以按照以下链路排查检查物理链路虚拟层面确认veth pair创建正确且端口状态是UP。ip link show | grep veth sudo ovs-vsctl list-ports br0检查命名空间内配置确认命名空间内的网卡IP配置正确且已启动。sudo ip netns exec ns1 ip addr show sudo ip netns exec ns2 ip addr show检查OVS端口状态使用ovs-vsctl show查看端口是否被正确添加到网桥以及端口的link-state。追踪流表匹配这是最强大的排错工具。使用ovs-appctl来跟踪一个数据包在OVS中的处理路径。# 在另一个终端开启OFPTrace需要先清空或注意流量 sudo ovs-appctl ofproto/trace br0 in_port$PORT_NS1,dl_srcaa:bb:cc:dd:ee:ff,dl_dstaa:bb:cc:dd:ee:ee,ip,nw_src192.168.100.10,nw_dst192.168.100.20 -generate这个命令会模拟一个从ns1端口进入发往ns2IP的数据包并详细输出它在每个流表中的匹配情况和最终执行的动作。通过这个输出你可以清晰地看到数据包是被哪条规则匹配了是被转发了、丢弃了还是泛洪了。检查内核datapath流表如果怀疑性能问题或快速路径未建立可以查看内核缓存的流表。sudo ovs-dpctl dump-flows掌握流表的查看和追踪是驾驭OVS网络不可或缺的技能。它让你从“黑盒”操作变为“白盒”调试。5. 超越单机构建跨主机的Overlay网络单机内的虚拟网络很有用但真正的威力在于连接多台物理主机构建一个大的、逻辑上统一的二层网络这就是Overlay网络。VXLAN是其中最流行的隧道技术之一。下面我们模拟在两台主机Host A和Host B上通过VXLAN隧道连接各自的OVS网络。假设环境Host A: IP 10.0.0.1 有一个OVS网桥br-vxlan连接着本地虚拟机/容器比如ns-a IP 172.16.1.10/24。Host B: IP 10.0.0.2 有一个OVS网桥br-vxlan连接着本地虚拟机/容器比如ns-b IP 172.16.1.20/24。目标让ns-a和ns-b能够直接通信就像它们在同一个局域网172.16.1.0/24一样。### 5.1 在Host A上配置# 创建网桥 sudo ovs-vsctl add-br br-vxlan # 添加一个VXLAN类型的端口指定远程对端IPHost B和VXLAN网络标识符VNI sudo ovs-vsctl add-port br-vxlan vxlan0 -- set interface vxlan0 typevxlan options:remote_ip10.0.0.2 options:key100 # key100 就是VNI两端必须一致。 # remote_ip10.0.0.2 指定了隧道对端。 # 创建本地命名空间并连接到网桥同第3节步骤 sudo ip netns add ns-a sudo ip link add veth-a-br type veth peer name veth-a-ns sudo ovs-vsctl add-port br-vxlan veth-a-br sudo ip link set veth-a-ns netns ns-a sudo ip netns exec ns-a ip addr add 172.16.1.10/24 dev veth-a-ns sudo ip netns exec ns-a ip link set veth-a-ns up sudo ip link set veth-a-br up sudo ip link set br-vxlan up### 5.2 在Host B上配置# 创建网桥 sudo ovs-vsctl add-br br-vxlan # 添加VXLAN端口远程IP指向Host A sudo ovs-vsctl add-port br-vxlan vxlan0 -- set interface vxlan0 typevxlan options:remote_ip10.0.0.1 options:key100 # 创建本地命名空间并连接 sudo ip netns add ns-b sudo ip link add veth-b-br type veth peer name veth-b-ns sudo ovs-vsctl add-port br-vxlan veth-b-br sudo ip link set veth-b-ns netns ns-b sudo ip netns exec ns-b ip addr add 172.16.1.20/24 dev veth-b-ns sudo ip netns exec ns-b ip link set veth-b-ns up sudo ip link set veth-b-br up sudo ip link set br-vxlan up### 5.3 测试与原理分析配置完成后在Host A上执行sudo ip netns exec ns-a ping 172.16.1.20如果底层网络10.0.0.1到10.0.0.2是通的并且防火墙没有阻止UDP 4789端口VXLAN默认端口那么ping应该成功。这里发生了什么ns-a172.16.1.10发出一个目的IP为172.16.1.20的ICMP请求包。包到达Host A的br-vxlan网桥。网桥发现目的MAC地址不在本地学习表中初始状态于是进行泛洪。泛洪的包到达vxlan0端口。OVS识别这是一个VXLAN隧道端口。OVS将这个原始的二层以太网帧从ns-a发出的整个封装到一个新的UDP数据包中。外层IP头源地址是Host A的IP10.0.0.1目的地址是Host B的IP10.0.0.2。外层UDP头目的端口是4789。并在UDP载荷前添加VXLAN头部其中包含VNI100。这个封装后的UDP包通过主机的物理网络接口发送出去穿越底层IP网络到达Host B。Host B的物理网卡收到UDP包内核或OVS识别出这是发往4789端口的VXLAN包将其交给br-vxlan网桥的vxlan0端口处理。vxlan0端口解封装剥离外层UDP和IP头取出原始的以太网帧来自ns-a并将其注入br-vxlan网桥。br-vxlan网桥学习到ns-a的MAC地址来自vxlan0端口并根据目的MAC地址ns-b将帧转发到veth-b-br端口最终送达ns-b。回复的包过程类似方向相反。通过VXLAN我们就在物理的三层IP网络之上构建了一个虚拟的二层大网络。OVS优雅地处理了所有的封装和解封装细节。6. 生产环境考量性能、高可用与安全在实验环境玩转后要将OVS用于生产有几个关键点必须考虑。### 6.1 性能调优要点DPDK集成对于需要极高数据平面性能的场景如NFV可以绕过内核datapath使用DPDKData Plane Development Kit轮询模式驱动让OVS直接在用户空间与网卡交互大幅提升吞吐量和降低延迟。但这需要专门的DPDK兼容网卡和更复杂的配置。多队列与CPU绑核为OVS的端口尤其是物理网卡启用多队列并利用pmdPoll Mode Driver线程将不同的队列绑定到不同的CPU核心上可以减少中断和锁竞争提升并行处理能力。流表优化避免使用大量低优先级的泛洪规则。尽量使用精确匹配或掩码匹配让流量命中内核快速路径。定期监控流表大小防止流表溢出。巨型帧Jumbo Frames在数据中心内部如果物理网络支持启用巨型帧如MTU9000可以减少封装/解封装的开销提升VXLAN等隧道网络的性能。需要确保整个路径物理交换机、主机、OVS、虚拟机的MTU设置一致。### 6.2 高可用方案单点的OVS网桥是故障的潜在来源。生产环境通常需要高可用。绑定Bonding将多个物理网卡绑定为一个逻辑端口接入OVS网桥提供链路聚合和故障切换。OVS支持多种绑定模式如主动-备份active-backup、负载均衡balance-slb, balance-tcp。sudo ovs-vsctl add-bond br0 bond0 eth0 eth1 lacpactive控制器集群如果使用SDN控制器如OpenDaylight, ONOS确保控制器自身是集群部署的避免单点控制器故障导致整个网络失控。OVSDB复制对于网桥配置的高可用可以考虑使用OVSDB的数据库复制功能将配置同步到备份服务器。### 6.3 安全实践流表防篡改确保OpenFlow通道通常是TLS加密的和OVSDB管理接口的安全防止未授权的控制器或管理客户端接入。使用连接跟踪Conntrack实现有状态防火墙OVS的conntrack功能可以跟踪连接状态从而实现类似有状态防火墙的规则。例如只允许内网发起对外请求并允许相关的回复包进入而主动从外部的入站连接则被拒绝。# 这是一个简化的示例允许已建立的连接和相关的回包通过 sudo ovs-ofctl add-flow br0 table0, priority100, ct_stateesttrk, actionsNORMAL sudo ovs-ofctl add-flow br0 table0, priority100, ct_statereltrk, actionsNORMAL sudo ovs-ofctl add-flow br0 table0, priority50, ip, actionsct(commit), NORMAL sudo ovs-ofctl add-flow br0 table0, priority1, actionsdrop网络策略隔离充分利用VLAN、VXLAN VNI或者OpenFlow流表在逻辑上严格隔离不同租户或不同安全等级的网络流量。7. 与云平台集成以OpenStack为例OVS是OpenStack Neutron网络组件最常用的后端之一。了解其集成方式有助于理解云中虚拟网络的运作。在OpenStack部署中Neutron通过其插件如openvswitch插件和代理ovs-agent来管理OVS。通常会有以下几种网桥br-int集成网桥。所有虚拟机的虚拟网卡tap设备最终都连接到这里。它负责内部端口的安全组策略通过流表实现、VLAN标记等。br-ex外部网桥。连接物理外部网络如数据中心网络为虚拟机提供浮动IP和外部网络访问能力。br-tun隧道网桥。当使用VXLAN/GRE等Overlay网络时用于处理隧道流量的封装和解封装。ovs-agent会监听Neutron服务器的消息自动创建这些网桥、端口、VXLAN隧道并下发复杂的OpenFlow流表来实现安全组、路由、DHCP等服务。例如一条“允许ICMP”的安全组规则在底层会被转换成br-int网桥上的一系列允许特定流量的OpenFlow规则。当你通过Horizon或CLI创建一个OpenStack网络、子网并启动实例时背后是Neutron和OVS在协同工作自动完成了我们上面手动完成的大部分操作创建网桥、添加端口、配置隧道、下发流表。理解这个底层机制对于排查OpenStack网络问题比如虚拟机网络不通、安全组不生效有巨大帮助。你可以直接登录到计算节点或网络节点使用ovs-vsctl和ovs-ofctl来检查网桥拓扑和流表状态这往往是定位复杂问题的终极手段。构建OVS网络从理解一个简单的虚拟交换机开始逐步深入到流表编程、跨主机隧道和高可用设计是一个典型的“从工具使用到架构理解”的过程。它要求我们不仅掌握命令和配置更要理解其背后的数据包流向和控制逻辑。在实际操作中最常遇到的坑往往是基础网络配置问题IP、路由、MTU、防火墙和流表逻辑错误。养成使用ovs-appctl ofproto/trace进行包追踪的习惯能帮你快速定位绝大多数转发层面的问题。最后记住OVS是一个强大的平台但在生产环境引入它时一定要结合具体的性能需求、高可用方案和安全规划进行设计和测试。
返回列表