场景:
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:~$