OpenStack_Project_Neutron_vertical-2-300x250.png
这篇文章翻译自这里。
其中结合了自己的一些观点和总结,内容是如何排查openstack网络问题及解决方法。笔者是openstack新手,翻译和注解过程中如有错误,欢迎指正。
话不多说,进入正题:
常见问题分类
您可能遇到的问题可以分为以下几类:
配置错误 - 遇到问题可能是因为你在neutron配置文件中进行了错误的配置。使用错误的配置工具也可能导致问题。配置错误的底层网络会影响neutron的功能,因为每个数据包最终都会通过物理层。举个例子,产生错误的原因可能是外部网络不可访问,或由于防火墙规则阻止了你的虚拟机流量通往外部。所以如果底层网络不可用,neutron也将无法正常工作。
代码中的错误 - 你可能会在代码中发现错误。幸运的是,你大概率不会是第一个遇到这个bug的人,如果有人已经上报了bug,你可以在 这里 找到答案。如果找不到这个bug,那么你可能是第一个遇到它的人,你应该报告这个bug,这样开发人员就可以开始修复它了。
问题一: 无法用private IP ping通或ssh远程登录虚拟机
这是一个常见的问题,特别是对于openstack新手来说。为了调试这个问题,我们首先应当理解虚拟机是如何获得一个IP的。
虚拟机如何获得IP?
为了回答这个问题,我们需要介绍 DHCP 代理
。如果你熟悉网络,会知道 DHCP
是分发不同网络参数(包括IP地址)的协议。
DHCP 代理通过 RPC
与 neutron-server
进行通信,它使用 namespaces
(命名空间)确保网络隔离,因此每个网络都有自己的DHCP命名空间。在这个命名空间里有一个名为 dnsmasq
的进程,它实际上服务于DHCP参数,包括IP地址。DHCP代理使用一个 lease file
(租约文件)来配置这个dnsmasq。
让我们更详细地看看IP分配过程:
vm_get_ip.png
在这个过程结束时,新的IP被提供给虚拟机。
让我们更详细地跟踪数据流。了解我们的数据流是很重要的,这将使我们知道去哪里查看问题并期待更快地找到问题。
数据流在 neutron - openvswitch
和 linux bridge
中有两个默认实现。我们从 openvswitch
开始:
openvswitch_flow.png
稍微解释一下上图:
firewall bridge
(防火墙)是一个 linux bridge,这是应用 security groups
(安全组)的地方,使用 iptables
来实现。我们不能将iptables应用到连接到 openvswitch 端口的接口,所以我们需要在中间有防火墙。
集成网桥(integration bridge,br-int)负责用与网络相关联的 VLAN ID
标记或取消标记那些来往于虚拟机的流量。每个网络都有一个VLAN ID,运用于主机内部以隔离流量(这也是为什么它被称为本地VLAN ID)。
隧道桥(tunnel bridge,br-tun)是负责连同的通道。它将分配给网络的VLAN ID转换成 segmentation id
(分段ID)。举个例子,如果你正在使用 GRE tuneel
,则 GRE tunnel ID
将是分配给网络的分段ID。
现在我们来看看linux bridge的数据流:
linux_bridge_flow.png
在linux bridge实现中,每个网络都有一个linux bridge。现在我们有net1并且虚拟机连接到net1上,同时可看到插入net1网桥的接口是eth0.100,这意味着vlan 100被分配给net1网络。
Debug步骤
首先检查虚拟机是否启动,这听起来很简单,但不能略过这一步:
$ nova list
输出应当类似下图:
nova_list.png
在上面的输出中,我们可以看到实例正在运行。如果它没有运行,我们可以在日志中查看出错的线索。查看日志总是一个明智的步骤,因为许多问题都反映在日志里。
$ grep -E -R -i "trace|error" /var/log/nova/ var/log/neutron/
笔者注:log中可能会提示代码错误,需要我们手动改动配置文件或python文件,一般都能在网上查到方法。由于我们使用openstack存在版本差异,可能在某个版本出现的bug在下个版本修复了,但依旧存在于这个版本,于是我们可以参考 github 上不同版本对比修改。
需要明确的是,错误可能是由任何因素造成的。它甚至可能与你的OpenStack部署无关,而与你的硬件有关。举个例子,也许是因为你已经没有足够的空间或内存去启动和运行虚拟机,你可以通过以下方式验证:
$ df -Ph && free -m
错误的另一个常见原因是默认的安全组规则。default security group默认情况下不允许ICMP(ping命令使用的协议),所以我们需要配置它。
笔者注:可以在openstack horizon界面中添加ICMP和ssh(TCP)规则,也可以通过命令行。命令行方式给默认安全组添加规则的方法如下:
$ nova secgroup-add-rule default icmp -l -l 0.0.0.0/0
$ nova secgroup-add-rule default tcp 22 22 0.0.0.0/0
其中,第一条命令使虚拟机能被ping通,第二条使虚拟机可以ssh远程登录。
如前所述,物理底层网络也可能导致问题,在排查问题前,应当确保openstack各个节点间能ping通。
笔者注:在引入环境变量后,可以使用如下命令查看各个节点的情况:
$ openstack compute service list
如果发现某个节点的状态是down,应当及时检查硬件设备:电源是否接通,网线是否接通。
端口绑定
如果虚拟机没有启动,请检查是否在虚拟机端口或路由器、DHCP端口上遇到了端口绑定故障。
对于虚拟机端口,将会被记录为端口绑定失败,因此很容易发现。
对于DHCP或路由器来说,并不是那么容易,因为端口是异步创建的,这意味着你不会马上看到它。以路由器为例。当你创建路由器并添加新的接口时,即使在背后创建的端口进入绑定失败状态,操作也会成功。那是因为这是异步发生的。
笔者注:针对原文下面的指令,首先我们可以从openstack horizon界面中获得端口的ID,或者通过命令行获得。我们可以通过命令行看到所有的端口ID:
$ openstack port list
查看端口绑定情况:
$ neutron port-show <port_id> -F "binding:vif_type" -F "binding:host_id"
binding_failure.png
有两种情况容易导致这个错误发生:
1.当你在路由器中添加新的子网或新的接口端口时,OVS代理已经挂掉。 这可以通过以下方式轻松验证:
$ neutron agent-list
你可以在openvswitch agent那行查看状态,如果正常,在alive栏会看到笑脸。
笔者注:笔者在安装openstack的时候参照的是官方文档,并没有用到 openvswitch
。但上述指令不失为一种检测网络代理是否正常的方法。笔者上次遇到错误就是发现 Linux bridge agent 出错,然后在log中找到了问题。
另一种OVS代理挂掉的症状是tap设备下没有VLAN标记。你可以通过以下方式验证:
$ ovs-vsctl show | grep tap -A 3
这种情况下唯一的解决方法就是重新创建虚拟机。
2.代理或服务器配置文件中的配置错误。这通常是因为在配置文件中使用了一些非默认值。
虚拟机是否接受到IP?
既然我们知道了虚拟机得到IP的过程,我们可以检查虚拟机是否接受到IP。可以在虚拟机命令行中使用如下指令:
$ ip a
如果没有IP,检查DHCP代理是否正常运行:
$ neutron agent-list
接下来,可以检查 dnsmasq 是否在你指定的网络节点正常运行。
$ ps -ef | grep dnsmasq | grep <network_id>
还可以检查 lease file(租约文件)是否存在并且虚拟机的mac地址在host 文件中。
$ cat /var/lib/neutron/dhcp/<network_id>/host
如果以上都排查了发现没有IP并且其他一切都看起来很正常,那么可以检查DHCP代理的log文件:
$ less /var/log/neutron/dhcp-agent.log
此时,还需要确保没有跨节点连接问题,所以请尝试在主机和虚拟机之间进行ping操作。不要忘记给主机设定正确的静态IP。
要记住的是,如果底层网络有问题,它会影响neutron的运行。 例如,如果物理交换机中不允许使用某些vlan ID,它将反映在neutron中,并且可能存在连接问题。
如果还没有找到问题,那么是时候拿出终极武器了—— tcpdump
。tcpdump将允许你跟踪数据包的完整过程,并查看它们在每个步骤中的变化情况。有很多很棒的在线教程解释了如何使用它,对于最基本的使用,试试运行:
$ tcpdump -i <name_of_the_device>
问题二: 虚拟机无法访问外部网络
为了解决这个问题,我们需要了解L3 agent(L3代理)的工作原理。其主要职责是允许L3连接和路由,也提供NAT,并使用命名空间进行网络隔离。通常它将被安装在网络节点上,也是提供访问外部网络的代理。
笔者注:在官网的安装文档上并没有网络节点,而是把网络服务分装在控制节点和计算节点上,这里所说的网络节点应当就是我们平时配置的控制节点。
让我们看看虚拟机尝试访问外部网络的过程:
l3_external_flow.png
和解析虚拟机如何获得IP类似,下图是linux bridge数据流:
l3_external_linux_bridge_flow.png
Debug步骤
首先,确保在环境中配置了正确的安全组规则,需要明确地允许ssh和ping。(这在上文中已经讲过,如下指令可以查看环境中的所有安全组都具有哪些规则,也可以在horizon界面中查看)
$ neutron security-group-rule-list
检查是否可以ping通 private IP。如果不能,就不必指望浮动IP起作用。请检查虚拟机是否可以到达路由器,因为如果不能到达路由器,必然不能到达外部网络。
笔者注:官网教程 创建一个虚拟机 中写了如何创建 provider network
和 self-service network
。在self-service netwrok中,创建的网络有一个内部IP和一个外部IP。创建self-service network时,需要有一个provider network,并创建一个路由,把self-service network的子网作为路由的一个接口,再把路由连接到provider网络上。这时运行以下命令,可以看到provider网络的两个网关:
$ neutron router-port-list router
fix_ip.png
如上图,其中 172.16.1.1
是self-service network的内部网关,是无法从外部ping通的,203.0.113.102
是外部网关,可以从外部ping通。如上所说,在创建self-service network时,会通过建立一个路由把该网络和一个provider network连接以保证self-service network可以访问外部网络。
在self-service network中创建虚拟机,需要给虚拟机分配一个浮动IP,如果我们想ping通虚拟机,应当使用这个浮动IP。
上文的ping通private IP笔者略有疑惑,可能指的是从虚拟机内部ping 类似 172.16.1.1
的内部网关,也可能是从外部ping虚拟机绑定的浮动IP。
接下来,从路由器命名空间尝试使用浮动IP来ping 虚拟机:
$ sudo ip netns exec qrouter-xxx-xxx-xxx ping <vm_floating_ip>
笔者注:上面命令的命名空间可以用如下指令获得:
$ ip netns
用如下指令可以得到所有虚拟机的IP:
$ openstack server list
这可能是个愚蠢的检查,因为浮动IP总是处于路由器命名空间内,但至少它会告诉我们情况有多糟糕。
你还应该检查网桥配置问题。 用下面的命令检查它:
$ ovs-vsctl show
别忘了检查L3 agent的log文件:
$ sudo grep -E -i "error|trace" /var/log/neutron/l3-agent.log
用以下命令看虚拟机是否得到了IP:
$ ip a
从虚拟机里ping网关看是否能到达:
$ route -n
$ ping <default_gateway_ip>
问题三: 虚拟机无法访问元数据服务器
元数据服务器是为虚拟机提供元数据的服务。数据可以是ssh密钥,ip地址,主机名。
元数据代理负责将来自虚拟机的请求代理到元数据服务器或 nova
。 有两种方法来配置它:
路由网络 - 当你有一个连接到路由器的网络
非路由网络 - 当你有没有连接到路由器的网络,所以它是隔离的。
我们来看看路由网络的工作流:
routed_networks_metadata.png
注意:metdata代理由L3代理生成,并监听请求。当来自虚拟机的请求到达元数据代理时,它将一些信息添加到虚拟机和路由器id的头部IP中,并将其转发给元数据代理。
现在让我们更仔细地看看其他配置 - 隔离网络:
isolated_network_metadata.png
注意:为了隔离网络能工作,必须在dhcp配置文件中进行配置:
enable_isolated_metadata = True
笔者注:在以下文件中配置:
/etc/neutron/dhcp_agent.ini
我们还使用DHCP的 option 121,在向DHCP请求IP地址时向虚拟机注入路由。 所以元数据代理是到达元数据服务器的下一个跃点。
Debug步骤
首先查看metadata agent是否正常运行:
$ neutron agent-list
在metadata agent 那行应当看到alive下面的微笑。
接着,检查metadata proxy是否正常。请记住,它是由L3代理在路由器(或dhcp)命名空间中产生的,所以您应该检查它是否在命名空间的进程表中:
$ sudo ip netns exec qrouter-xxx-xxx-xxx ps -ef | grep metadata-proxy
问题会反映在metadata的log文件中,所以前去检查:
$ sudo grep -E -i "error|trace" /var/log/neutron/metadata-agent.log /var/log/neutron/neutron-ns-metadata-proxy-xxx-xxx-xxx.log
检查是否可以通过路由/DHCP到达元数据服务器:
$ sudo ip netns exec qrouter-xxx-xxx-xxx ping <metadata-server_IP>
检查创建虚拟机的镜像是否支持 option 121。如果不支持,那么虚拟机可能无法得到路由并且到达元数据服务器。
如果所有都尝试了还没有发现问题,试着使用 tcpdump
来解决问题。
问题四: VIF plugging timeout
为了理解为什么会遇到timeout问题,我们需要介绍L2代理。
L2代理在计算主机上运行,其主要职责是配置节点上的本地交换机并连接新设备,它通过RPC与neutron服务器通信,还负责提供使用iptables和ip集合的安全组规则。
让我们更详细地看看VIF如何工作:
vif_plugging.png
当Nova发送allocate_network请求时,它将超时设置为5分钟。如果Nova在5分钟内没有得到Neutron的回复,你会得到VIF plugging timeout。
debug步骤
检查日志。L2代理,neutron和nova日志可以帮助查找问题,在计算节点上输入:
$ sudo grep -E -i "error|trace" /var/log/nova/nova-compute.log /var/log/neutron/openvswitch-agent.log
在控制节点上:
$ sudo grep -E -i "error|trace" /var/log/neutron/server.log
如果系统加载缓慢,或者你正在执行压力测试,则可能需要调整/etc/nova/nova.conf
文件中的服务器配置:
尝试增加
vif_plugging_timeout
以提供更多的时间来插入接口尝试增加
rpc_thread_pool_size
和rpc_conn_pool_size
以使处理速度更快
一些好用的工具
让我们回顾一下在对neutron进行debug过程中用到的工具。
ip a
ip addr(ip a只是一个快捷方式)对于检查你的机器/命名空间中的设备非常有用。它允许你获取设备名称、查看设备是否启动、获取IP地址、MTU以及其他一些网络参数。
route -n
它会显示路由表。通过路由表,你可以知道你的数据包在流出时将采用哪个路径。
iptables -L
查看节点上存在哪些防火墙规则。如果你的数据包突然消失或没有到达最终目的地,防火墙的某些规则可能是原因。
arp
查看主机上的arp表。利用它可以查看你的节点能不能找到其他节点的地址。
tcpdump
在这篇文章中多次提到过。这是一个很棒的数据包追踪工具,容易安装,也容易使用。我将在另一篇文章中介绍它,因为有很多方法可以使用,最好花时间专门学习。对于最基本的使用,只需运行:
$ tcpdump -i <device_name>
ip netns
查看namespace。为了列出你所在节点可用的namespaces,可以使用:
$ ip netns list
你可以使用 ip netns exec
查看更多。例如,要在命名空间中显示路由表,请使用:
$ ip netns exec qrouter-xxx-xxx-xxx route -n
OpenVSwich
如果你在部署中使用openvswitch,则有几个用于调试和故障排除的工具:
ovs-vsctl show
—— 显示机器上网桥的配置
ovs-ofctl show
—— 显示数据路径
ovs-ofctl dump-flows
—— 转储安装在机器上的所有流
ovs-ofctl dump-flows br-tun
—— 转储br-tun上的所有流
ovs-ofctl dump-flows br-tun table = 21
—— 在特定表中转储br-tun上的所有流
LinuxBridge
对于linux网桥,请使用以下命令:
brctl show
—— 显示机器上网桥的配置
brctl show <bridge name>
—— 显示特定网桥的配置
补充
再介绍一些你可能想要熟悉的几个重要的网络设备。
我们从TAP设备开始。TAP设备是一个虚拟网络接口,用于连接由虚拟机管理程序(KVM,Xen等)实现的虚拟机实例。流量到达TAP设备,由虚拟机实例接收。要记住TAP设备通常是流量的起点,可以从TAP设备开始跟踪流量。
要查看TAP设备,只需运行:
$ ip a | grep -i tab
更多关于TAP设备的信息,可以在 这里 找到。
TAP设备使用Linux bridge进行桥接。通常Linux桥名以qbr开头,这是qunaum bridge的简写(qunaum是neutron以前的名字)。你可以使用brctl列出系统上的linux bridge。
$ brctl show
你会在输出中看到TAP接口和qvb接口。
qvb(Quantum veth bridge)和另一end - qvo(Quantum veth openvswitch)构成一个虚拟以太网对(Virtual Ethernet Pair)。它用来连接Linux桥和OVS桥。可以把它们想象成一条管道,任何在一个设备上进入的东西都应该从这个设备上离开。
如果你列出集成桥上的端口,你将看到其中一个端口是qvo,它将你连接到Linude Bridge。
路由器和DHCP设备直连到br-int。在列出DHCP命名空间中的接口或列出集成网桥上的端口时,可以看到TAP设备条目。
$ ip netns exec qdhcp-<network_id> ip address
$ ovs-vsctl list-ports br-int
笔者总结
在了解了neutron的基础概念,通过一些图表知道了数据流的走向后,对于我们debug最有用的还是查看log。Openstack的log都处于 /var/log 目录下,我们通过查看、解决log里的问题,并重启相应网络服务,基本可以解决问题。
笔者翻译这篇博客的过程中,对Openstack的neutron模块有了更深的了解,也利用博客里梳理的思路解决了实验室Openstack环境遇到的问题,以后会多多学习这类博客,看到好的博客会争取翻译过来。
作者:Murray66
链接:https://www.jianshu.com/p/cf6168803d2e
共同学习,写下你的评论
评论加载中...
作者其他优质文章