Open vSwitch和KVM一个奇怪的问题

场景:

1:VMware Fusion里安装Ubuntu 14.04 desktop版

2:Ubuntu里安装Open vSwitch和KVM

sudo apt-get install kvm libvirt-bin virtinst
sudo apt-get install openvswitch-*

3:KVM里安装Debian7

sudo qemu-system-x86_64 forqemu.qcow2 -m 512 -net nic,model=virtio,macaddr=00:16:3e:22:22:22  -net tap,ifname=tap124

forqemu.qcow2是磁盘镜像,跟VMware的vmdk一个意思,直接打开,只不过是针对KVM,512是内存,最后tap124是创建的与虚拟机相连的tap设备名

 

下面主要研究KVM里debian虚拟机同外面的ubuntu的通信状况,虽然ubuntu实际上也是虚拟机,这里就忽略两层虚拟机的问题

1:给debian操作系统配置IP地址

sudo ip addr add 10.10.10.10/16 dev eth0

也就是虚拟机IP地址为10.10.10.10,因为都是虚拟子网,所以随便设,然后不停地

ping 10.10.10.11

2:剩下的都是在debian的宿主机ubuntu里来操作

首先查看下bridge

lihui@kvm:~$ sudo ovs-vsctl show
e8ce072f-1b58-4a16-9895-6171aa132cc0
    Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
    ovs_version: "2.0.2"

这里的安装Open vSwitch之后默认会存在一个bridge br-int,注意这是ovs创建的,而不是linux来创建的

其次,在安装debian虚拟机的时候,指定了一个tap设备tap124,也可以在宿主机里查到

lihui@kvm:~$ ifconfig tap124
tap124    Link encap:Ethernet  HWaddr 26:23:c5:08:95:68  
          inet6 addr: fe80::2423:c5ff:fe08:9568/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:24 errors:0 dropped:0 overruns:0 frame:0
          TX packets:30 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:6120 (6.1 KB)  TX bytes:4442 (4.4 KB)

由于它是和虚拟机相连的,因此显然只需要给tap124配置一个与虚拟机debian系统同子网的IP地址,那么ubuntu和debian显然就能进行数据通信了

配置IP地址

lihui@kvm:~$ sudo ip addr add 10.10.10.11/16 dev tap124
lihui@kvm:~$ ifconfig tap124
tap124    Link encap:Ethernet  HWaddr 26:23:c5:08:95:68  
          inet addr:10.10.10.11  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::2423:c5ff:fe08:9568/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:30 errors:0 dropped:0 overruns:0 frame:0
          TX packets:44 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:8172 (8.1 KB)  TX bytes:7463 (7.4 KB)

看下路由表

lihui@kvm:~$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
10.10.0.0       0.0.0.0         255.255.0.0     U         0 0          0 tap124
192.168.135.0   0.0.0.0         255.255.255.0   U         0 0          0 eth0

这样肯定就能和虚拟机互通了,为了保证正确性,通过虚拟机(10.10.10.10)来ping,宿主机(10.10.10.11)来抓包,不知道虚拟机里tcpdump为什么很卡,就直接用tshark来抓

lihui@kvm:~$ sudo tshark -i tap124 icmp
Running as user "root" and group "root". This could be dangerous.
Capturing on 'tap124'
  1   0.000000  10.10.10.10 -> 10.10.10.11  ICMP 98 Echo (ping) request  id=0x0d8a, seq=97/24832, ttl=64
1   2   0.000037  10.10.10.11 -> 10.10.10.10  ICMP 98 Echo (ping) reply    id=0x0d8a, seq=97/24832, ttl=64 (request in 1)
2   3   1.002004  10.10.10.10 -> 10.10.10.11  ICMP 98 Echo (ping) request  id=0x0d8a, seq=98/25088, ttl=64
3   4   1.002042  10.10.10.11 -> 10.10.10.10  ICMP 98 Echo (ping) reply    id=0x0d8a, seq=98/25088, ttl=64 (request in 3)
4   5   2.004785  10.10.10.10 -> 10.10.10.11  ICMP 98 Echo (ping) request  id=0x0d8a, seq=99/25344, ttl=64
5   6   2.004820  10.10.10.11 -> 10.10.10.10  ICMP 98 Echo (ping) reply    id=0x0d8a, seq=99/25344, ttl=64 (request in 5)

这样就已经OK了,下面假如有新的要求,需要创建一个Open vSwitch,然后将tap设备绑到ovs上去,干点其它的

创建Open vSwitch,这里就不用br-int了,重新创建一个新的

lihui@kvm:~$ sudo ovs-vsctl add-br br-new
lihui@kvm:~$ sudo ovs-vsctl show
e8ce072f-1b58-4a16-9895-6171aa132cc0
    Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
    Bridge br-new
        Port br-new
            Interface br-new
                type: internal
    ovs_version: "2.0.2"

绑上tap124

lihui@kvm:~$ sudo ovs-vsctl add-port br-new tap124
lihui@kvm:~$ sudo ovs-vsctl show
e8ce072f-1b58-4a16-9895-6171aa132cc0
    Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
    Bridge br-new
        Port br-new
            Interface br-new
                type: internal
        Port "tap124"
            Interface "tap124"
    ovs_version: "2.0.2"

但特别要注意的是,设备绑上bridge后,它的设备信息就会失效了,所以得重新分配一次IP地址,切记别忘

sudo ip addr add 10.10.10.11/16 dev tap124

也就是说,从创建OVS开始,做了这么多,实际上也就是将tap124绑到了bridge上,没做任何其它的动作,IP也重新分配了,顺便再看看路由表

lihui@kvm:~$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
10.10.0.0       0.0.0.0         255.255.0.0     U         0 0          0 tap124
192.168.135.0   0.0.0.0         255.255.255.0   U         0 0          0 eth0

理论上与虚拟机debian的通信,应该不会有任何问题才对,因为tap124还和虚拟机相连着呢,可是tshark已经抓不到包了,虚拟机里的ping也不通,由于我就做了一个动作,tap124绑br-new,于是,又做了下面几个动作来测试:

1:将tap124和br-new解绑

lihui@kvm:~$ sudo ovs-vsctl del-port br-new tap124
lihui@kvm:~$ sudo ovs-vsctl show
e8ce072f-1b58-4a16-9895-6171aa132cc0
    Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
    Bridge br-new
        Port br-new
            Interface br-new
                type: internal
    ovs_version: "2.0.2"

此时tap124的ip信息如下

6: tap124: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/ether 22:c3:b9:0e:3e:e5 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::20c3:b9ff:fe0e:3ee5/64 scope link 
       valid_lft forever preferred_lft forever

然后立马就ping通了,说明了是绑定这一步的影响,虽然难以接受,但事实就是如此

2:解绑的前提下,重启宿主机Ubuntu,重启后,虚拟机重新分配IP(10.10.10.10),宿主机tap再次绑bridge

,分配IP(10.10.10.11)

虚拟机
sudo ip addr add 10.10.10.10/16 dev eth0

宿主机
lihui@kvm:~$ sudo ovs-vsctl add-port br-new tap124
lihui@kvm:~$ sudo ip addr add 10.10.10.11/16 dev tap124
lihui@kvm:~$ sudo ovs-vsctl show
e8ce072f-1b58-4a16-9895-6171aa132cc0
    Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
    Bridge br-new
        Port br-new
            Interface br-new
                type: internal
        Port "tap124"
            Interface "tap124"
    ovs_version: "2.0.2"

结果还是没法ping通,此时(重启后重新手绑)tap124的ip信息如下

6: tap124: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master ovs-system state UNKNOWN group default qlen 500
    link/ether 22:c3:b9:0e:3e:e5 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::20c3:b9ff:fe0e:3ee5/64 scope link 
       valid_lft forever preferred_lft forever

3:bridge和tap不解绑(上面已经绑上了),重启,然后虚拟机重新分配IP(10.10.10.10),宿主机分配IP(10.10.10.11)

虚拟机
sudo ip addr add 10.10.10.10/16 dev eth0

宿主机
sudo ip addr add 10.10.10.11/16 dev tap124

结果神奇地ping通了,此时tap124的IP信息如下

6: tap124: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/ether 22:c3:b9:0e:3e:e5 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::20c3:b9ff:fe0e:3ee5/64 scope link 
       valid_lft forever preferred_lft forever

根据这三次对比测试,大概可以得到下面信息:

(1)任何情况下重新ovs来绑定tap,然后给tap分配IP,肯定是无法ping通虚拟机,而绑定tap前提下重启再给tap分配IP是可以ping通的

(2)通和不通的情况下,或者说绑定tap重启和不重启tap124的IP信息其实有一个差别master ovs-system,也没搜出信息量,但肯定代表着什么

(3)第三次测试,在没有解绑的情况下,重启,tap分配IP就ping通了,说明ovs绑了之后重启过程中某些因素发生了改变

为了验证第三点,可以通过重启某些服务而不是整个宿主机,看能否达到重启整个宿主机的效果,目的就是为了找到是否某些服务的影响,做法:

(1)重启网络,结果无效

(2)重启openvswitch-*等服务,结果还是无效

对于第二点,IP信息的差别,只能怀疑重启之后是否bridge和tap根本没绑,一方面原因是绑着重启跟没绑的IP信息是一样的,另一方面假如是没绑,是肯定能ping通的,但是通过下面命令一直看到能绑着的

lihui@kvm:~$ sudo ovs-vsctl show
[sudo] password for lihui: 
e8ce072f-1b58-4a16-9895-6171aa132cc0
    Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
    Bridge br-new
        Port br-new
            Interface br-new
                type: internal
        Port "tap124"
            Interface "tap124"
    ovs_version: "2.0.2"

带着上面的一些测试结果与背后的开发大姐(感觉是)咨询了一番,终于得到了解决:

问题1:bridge绑定tap,无法ping通虚拟机

她看了linux内核源代码,得到的答案是绑定之后,ping的数据包都会被bridge给接管,而本身bridge没有配置IP地址,无法再次转给tap,这个解释容易接受,bridge绑了一个tap之后,就会让tap的ip失效,所以又要重新配置一次IP,所以它接管了,然后没转发也是情理之中

问题2:bridge绑定tap,重启虚拟机就能ping通虚拟机

这时候虚拟机一直在向宿主机ping,为了定位重启后的现象,这里用到了两个命令

lihui@kvm:~$ sudo ovs-dpctl dump-flows
lihui@kvm:~$ sudo ovs-dpctl show
system@ovs-system:
	lookups: hit:10 missed:6 lost:0
	flows: 0
	port 0: ovs-system (internal)
	port 1: br-int (internal)
	port 2: br-new (internal)

第一个命令是查看包来自哪个设备,令人诧异的是没有任何数据,第二个命令是Dump 在 Linux kernel 里的设备以及绑定情况,从这条命令可以看到tap124根本就没绑到任何设备上,这下我的心拔凉拔凉的,用ovs-vsctl show折腾了一晚,她给的解释是ovs-vsctl仅仅是用户态,而ovs-dpctl才是内核态,这样就说得通了,搜了一下的确这个才是常用的

也就是说结论就是:

1:绑定后tap和虚拟机无法ping通是因为bridge接管了

2:重启后能ping通,实际上此时的确bridge没有绑tap,所以能ping通,而我的查询命令有问题

下面是更深的正确的查询定位方法,有兴趣的可以研究下

lihui@kvm:~$ !615
sudo ovs-dpctl dump-flows
skb_priority(0),in_port(3),eth(src=00:16:3e:22:22:22,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=10.10.10.10/255.255.255.255,tip=10.10.10.11/255.255.255.255,op=1/0xff,sha=00:16:3e:22:22:22/00:00:00:00:00:00,tha=00:00:00:00:00:00/00:00:00:00:00:00), packets:11, bytes:462, used:0.729s, actions:2
lihui@kvm:~$ !616
sudo ovs-dpctl show
system@ovs-system:
	lookups: hit:62 missed:10 lost:0
	flows: 1
	port 0: ovs-system (internal)
	port 1: br-int (internal)
	port 2: br-new (internal)
	port 3: tap124
lihui@kvm:~$ 

发表回复