问题

VPC内虚机通过NAT网关配置SNAT访问外网。如下所示:

使用中出现问题,虚机不能访问外网。

基础知识

DVR模式

按照 Neutron 原先的设计,所有网络服务都在网络节点上进行,这意味着大量 的流量和处理,给网络节点带来了很大的压力。这些处理的核心是路由器服务。 任何需要跨子网的访问都需要路由器进行路由。很自然,能否让计算节点上也运 行路由器服务?这个设计思路无疑是更为合理的,但具体实施起来需要诸多细节 上的技术考量。

为了降低网络节点的负载,同时提高可扩展性,OpenStack 自 Juno 版本开始正 式引入了分布式路由(Distributed Virtual Router,DVR)特性,来让计算节 点自己来处理原先的大量东西向流量和非 SNAT 南北流量。这样网络节点只需要 处理少部分的 SNAT流量,大大降低了负载和整个系统对网络节点的依赖。

DHCP 服务、VPN 服务目前仍然需要集中在网络节点上进行。

虚机的各种口

虚机流量发出,经过以下路径:

  • TAP 设备是一种工作在二层协议的点对点网络设备,每一个 TAP 设备都有一 个对应的 Linux 字符设备,用户程序可以通过对字符设备的读写操作,完成 与 Linux 内核网络协议栈的数据交换工作,在虚拟化环境中经常被模拟器使 用。总而言之,TAP设备其实就是一个Linux内核虚拟化出来的一个网络接口。
  • qbr,是一个Linux Bridge。因为OpenStack是把iptables规则丢在TAP设备实 现了安全组功能。但OVS跟Iptables的规则不兼容,有iptable的tap设备不能直接连接到ovs上。 所以用了一个折衷的方式,在中间加一层,使用qbr linux桥。
  • qvb 和qvo,虚拟ethernet接口,通常以pair的方式出现,一端发出的网包,会被另一端接收,可以形成两个网桥之间的通道。
  • br-int:bridge-integration,综合网桥,常用于表示实现主要内部网络功能 的网桥。
  • iptables:Linux 上常见的实现安全策略的防火墙软件。
  • TUN设备:模拟一个三层的网络设备,可以接受和发送三层网包。

dvr模式下,虚机报文路径

虚机通过snat网关访问外网,报文发出去流向是:

tap->qbr->qvb->qvo->br-int->qrouter->br-int->br-tun1->br-tun2。

路径上的qvo、qvb口和tap口都可以抓包。

dvr模式下,报文头封装及改变

以下图说明了报文的改变,主要是二层头的封装。

如上图所示,租户两个子网,红色和绿色,分别有 vm1 和 vm2,位于节点 cn1 和 cn2 上。

vm1 访问 vm2 的网包如步骤 1-6,整个过程 ip 保持不变。

  • 原始包,vm1 访问 vm2,目的 mac 为本地(红网)的路由器网关接口 r1 red mac;
  • 经过 br-int-cn1 转发,该网包通过本地(红网)网关接口扔给本地路由器 r1。
  • r1 根据路由规则,经过到绿网的接口发出,此时网包的源 mac 改为绿网的网关接口 r1 grn mac,目的 mac 改为 vm2 mac,并且带上绿网的本地 vlan tag;
  • 网包发给 br-tun-cn1 进行 tunnel,扔出去之前,将源 mac 替换为跟节点相关的特定 mac dvr cn1 mac,之后带着目标子网(绿网)的 外部 tunnel id 扔出去(实现可以为 vlan、vxlan、gre 等,功能都是一样的);
  • 节点 cn2 的网桥 br-tun-cn2 会从 tunnel 收到这个包,解封包,带上本地 vlan tag,最终抵达网桥 br-int-cn2;
  • br-int-cn2 上替换网包的源 mac(此时为 dvr-cn1-mac)为本地路由器的绿网网关接口,然后发给 vm2。

分析排查

通过openstack命令,查到虚机的port,所在计算节点信息,所连接的qrouter信 息。

  • 查看虚机的port信息

~# openstack port list –server ed079656-c1d5-415e-bb79-c24dbbc54cdf

  • 查看虚机所在计算节点

~# openstack server show ed079656-c1d5-415e-bb79-c24dbbc54cdf | grep host

  • 查看虚机所在的网络

~# openstack port show 74df9649-bd57-4a5e-8b7e-181c3e7a2a40 | grep network

  • 查看接入qrouter的port

~# openstack port list –long –network c0ad68cc-2388-406c-9da0-e2ec4fe71b5e | grep dis

  • 根据port查到qrouter的id

~# openstack port show 8d2bd1cf-bcf1-43e3-bf57-0c965a88e0e0 | grep device

device_id即是qrouter的id。

报文抓包

  • 登陆计算节点
  • 首先从报文的tap口抓包,确认流量是不是正常发出。
  • qbr抓包,确认liunux桥的安全组是否已经放行。如果tap口能抓到包,但qbr 没有,说明安全组规则把包拦截了。
  • qrouter抓包,确认是否正常
  • br-tun查看报文是否正常发送出去

期间如果抓不到正常的报文,需要排查原因。

qbr抓不到包

qbr抓不到报文,但tap口正常。这种情况,应该是安全组规则把报文拦截了。需 要排查计算节点上的安全组规则。安全组的排查方式,参考安全组相关文档。

pbr规则排查

查看qrouter上的规则

~# ip netns exec qrouter-e6d4c905-4c62-4f06-a879-0bd6f4a8330d bash

~# ip rule

~# ip route show table 2886729985

正常发送出去,但对端没收到

从计算节点的物理口上抓包,查看是否正常收到报文。

总结

根据虚机发送报文时,沿着报文的路径进行抓包,对没有收到包的前一个节点重 点排查。