3、OVS 基本操作:ovs-vsctl 命令详解、Bridge/Port/Interface 管理、流表基础概念

好,咱们进入正题。上一章我们把 OVS 装上了,现在该动动手了。说实话,OVS 最常用的工具就是 ovs-vsctl,我几乎每天都要敲它几十遍。你把它想象成 OVS 的「遥控器」就行——所有对交换机、端口、隧道的配置,都靠它来下发。

3.1 ovs-vsctl 命令详解

ovs-vsctl 是 OVS 的管理工具,专门用来操作 ovsdb(OVS 的数据库)。说白了,你敲的每一条命令,最终都会写到数据库里,然后 OVS 的守护进程 ovs-vswitchd 会读取这些配置并生效。

我个人习惯把常用命令分成三类:查询类增删改类调试类。咱们一个个看。

3.1.1 查询类命令

刚接手一个环境,第一件事就是看当前有什么。我最常用的就是:

# 查看所有 Bridge(网桥)
ovs-vsctl list-br

# 查看某个 Bridge 上的所有 Port(端口)
ovs-vsctl list-ports br0

# 查看某个 Port 对应的 Interface(接口)详细信息
ovs-vsctl list interface veth0

# 查看整个 OVS 的配置概览
ovs-vsctl show

这里有个小细节:ovs-vsctl show 输出的是树形结构,一眼就能看清 Bridge、Port、Interface 的层级关系。我在项目里排查问题时,第一件事就是跑 show,看看拓扑对不对。

3.1.2 增删改类命令

创建和删除是日常操作。举个例子:

# 创建一个名为 br0 的 Bridge
ovs-vsctl add-br br0

# 给 br0 添加一个物理端口 eth0
ovs-vsctl add-port br0 eth0

# 删除一个端口
ovs-vsctl del-port br0 eth0

# 删除整个 Bridge(会连带删除所有端口)
ovs-vsctl del-br br0

嗯,这里要注意:add-port 的时候,如果这个端口已经被别的 Bridge 占用了,OVS 会报错。我曾经在测试环境里犯过这个错,折腾了半天才发现 eth0 已经被另一个 Bridge 绑定了。

3.1.3 调试类命令

有时候配置完了,发现流量不通。这时候我会用:

# 查看某个 Interface 的统计信息(收发包、丢包等)
ovs-vsctl list interface eth0

# 查看 Bridge 的流表统计
ovs-ofctl dump-flows br0

# 查看 OVS 的日志(定位问题利器)
tail -f /var/log/openvswitch/ovs-vswitchd.log

你想想看,如果流量不通,先看 Interface 的统计里有没有收到包,再看流表有没有命中。这两步走完,80% 的问题都能定位到。

3.2 Bridge / Port / Interface 管理

这三个概念是 OVS 的基石。我简单解释一下:

  • Bridge:就是虚拟交换机。你可以创建多个 Bridge,每个 Bridge 独立工作。
  • Port:Bridge 上的端口。一个 Port 可以对应一个物理网卡、一个虚拟网卡、或者一个隧道。
  • Interface:Port 底层的实际接口。一个 Port 通常对应一个 Interface,但像 Bond 口(链路聚合)就是一个 Port 对应多个 Interface。

看个实际例子:

# 创建一个 Bridge
ovs-vsctl add-br br-int

# 添加一个内部端口(类似 Linux 的虚拟网卡)
ovs-vsctl add-port br-int vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=192.168.1.100

# 查看结构
ovs-vsctl show

输出大概长这样:

Bridge br-int
    Port br-int
        Interface br-int
            type: internal
    Port vxlan0
        Interface vxlan0
            type: vxlan
            options: {remote_ip="192.168.1.100"}

看到了吗?br-int 这个 Bridge 有两个 Port:一个是它自己(内部端口),另一个是 VXLAN 隧道端口。每个 Port 下面挂着一个 Interface。

小技巧: 如果你想让 Bridge 本身有一个 IP 地址(比如用于管理),那就用内部端口。我通常会给每个 Bridge 创建一个内部端口,然后配个 IP,方便远程管理。

3.3 流表基础概念

流表是 OVS 的灵魂。没有流表,OVS 就是一个普通的 Linux Bridge。有了流表,它才能做 OpenFlow 交换机该做的事。

流表说白了就是一张规则表。每条规则包含两部分:匹配条件动作。当数据包进入 OVS 时,它会从上到下匹配流表,找到第一条匹配的规则,然后执行对应的动作。

3.3.1 流表的结构

一条流表规则长这样:

# 匹配源 MAC 为 aa:bb:cc:dd:ee:ff 的数据包,转发到端口 1
ovs-ofctl add-flow br0 "dl_src=aa:bb:cc:dd:ee:ff, actions=output:1"

这里 dl_src 是匹配条件,output:1 是动作。你可以匹配的东西很多:MAC 地址、IP 地址、端口号、VLAN ID、隧道 ID 等等。

3.3.2 常用匹配条件

匹配字段 含义 示例
in_port 入端口 in_port=1
dl_src 源 MAC dl_src=00:11:22:33:44:55
dl_dst 目的 MAC dl_dst=ff:ff:ff:ff:ff:ff
nw_src 源 IP nw_src=10.0.0.1
nw_dst 目的 IP nw_dst=10.0.0.0/24
tcp_src TCP 源端口 tcp_src=80
tun_id 隧道 ID(VNI) tun_id=100

3.3.3 常用动作

动作 含义 示例
output:port 转发到指定端口 output:1
normal 走传统二层交换(类似普通交换机) actions=normal
drop 丢弃数据包 actions=drop
mod_dl_src 修改源 MAC mod_dl_src=00:11:22:33:44:55
mod_nw_src 修改源 IP mod_nw_src=10.0.0.2
set_tunnel 设置隧道 ID set_tunnel:100

3.3.4 流表优先级

流表是有优先级的。数值越大,优先级越高。默认是 0。我建议你给关键规则设置高优先级,避免被低优先级规则误匹配。

# 高优先级规则(匹配特定流量)
ovs-ofctl add-flow br0 "priority=100, dl_src=00:11:22:33:44:55, actions=output:2"

# 低优先级规则(默认转发)
ovs-ofctl add-flow br0 "priority=0, actions=normal"
注意: 如果你没有添加任何流表,OVS 默认行为是丢弃所有数据包。所以要么加一条 actions=normal 让它走传统交换,要么自己写完整的流表规则。我第一次用 OVS 时就踩了这个坑——配完 Bridge 发现 ping 不通,查了半天才发现没加默认规则。

3.4 实战小练习

光说不练假把式。咱们来个小实验:

# 1. 创建 Bridge
ovs-vsctl add-br br-demo

# 2. 添加两个内部端口(模拟两台虚拟机)
ovs-vsctl add-port br-demo vm1 -- set interface vm1 type=internal
ovs-vsctl add-port br-demo vm2 -- set interface vm2 type=internal

# 3. 给内部端口配 IP
ip addr add 10.0.0.1/24 dev vm1
ip addr add 10.0.0.2/24 dev vm2
ip link set vm1 up
ip link set vm2 up

# 4. 添加流表:让 vm1 和 vm2 可以互通
ovs-ofctl add-flow br-demo "in_port=1, actions=output:2"
ovs-ofctl add-flow br-demo "in_port=2, actions=output:1"

# 5. 测试
ping -c 3 10.0.0.2 -I vm1

如果 ping 通了,恭喜你,你已经掌握了 OVS 的基本操作。如果没通,检查一下流表有没有生效:

ovs-ofctl dump-flows br-demo

嗯,到这里,OVS 的基本操作就讲完了。下一章咱们会深入 GRE 和 Geneve 隧道,到时候这些基础操作都会用上。你先把这些命令敲熟,后面就轻松了。