OpenStack虚拟机网络不通的几个思路[2]

2018年六月份已经过去,刚过去的两个月是入市以来回撤最大的两个月,虽然资金量不大,但依然对未来抱有希望,说不定哪天走狗屎运咸鱼翻身了呢。本质上来说,股市也好,人生中的各种选择也好,都是一种赌博,就看你的筹码有多大,未来到底看的有多清,当然我从不屑于直接参与赌博,只是厌倦了一辈子都是如此谨谨慎慎,按部就班的生活。

2018年下半年祝福自己依然有颗勇敢的心,怀抱希望的走下去,Get busy living, Or get busy dying!

回来继续做些笔记,之前提到过OpenStack 虚拟机网络不通的几个思路,这篇笔记对其中iptable的规则来做个深入的了解:

sudo iptables -t nat -A POSTROUTING -s 192.168.42.0/24 -o eno1 -j MASQUERADE

为什么???

首先我们假设floating IP的地址和物理机的IP地址不在同一个网段,而是一个自定义的网段(后面我会探讨不同的应用场景,比如floating IP和物理机器的IP地址在需要在同一个网段的情况如何做网络配置),比如:
- 物理机的IP地址为: 192.168.18.0/24
- floating IP地址定义为: 192.168.42.0/24
这里floating IP地址其实是一个不存在的网络,是需要通过OpenStack去创建的一个网络。和之前的定义不一样,这里我们只对192.168.42.0/24网段的IP进行地址伪装,伪装为eno1的IP地址出去,192.168.42.0/24是floating IP地址。如果没有上面定义的这个规则,虚拟机则无法访问外网(公司内网),因为外部网络是不知道floating IP地址存在的,通过这个规则,从虚拟机出来的流量
将得以访问外网。

假设OpenStack的环境是通过DevStack安装起来的,那么你可以看到DevStack脚本已经帮你创建好了这个规则:

$ sudo iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 192.168.42.0/24 -o eno1 -j MASQUERADE  <- 看这里
-A DOCKER -i docker0 -j RETURN

应用场景

我们来想这样一个场景,物理机上有多个网卡,比方说eno1连接的是公司内部的网络,eno2连的是公网,通过在DevStack的localrc文件里做如下的配置

FLAT_INTERFACE=eno1

注:

新版本中已经不建议采用nova network, 而是用neutron来提供网络服务,这样FLAT_INTERFACE将 不再起作用,取而代之的是PUBLIC_INTERFACE这个属性,而这两个属性所代表的意思是不同的,参考后面的源码分析。

DevStack会自动配置好了iptables,我们假设网络没有绑定任何物理网卡,那么应该走的是系统的默认路由,一般情况下,物理机上会配置一个默认路由,像下面这样:

$ sudo ip route
default via 192.168.18.1 dev eno1  proto static  metric 100
default via 192.168.8.1 dev eno2  proto static  metric 101
...
192.168.16.0/21 dev eno1  proto kernel  scope link  src 192.168.20.132
192.168.42.0/24 dev br-ex  proto kernel  scope link  src 192.168.42.1

这样虚拟机通过floating IP应该可以访问公司的内网了,但是有一天,虚拟机需要访问外部的公网了,怎么办?
修改物理机的默认路由?例如默认路由修改为:

default via 192.168.8.1 dev eno2 proto static metric 100
default via 192.168.18.1 dev eno1 proto static metric 101

是否可以了呢?做个测试,在虚拟机里ping 8.8.8.8,然后通过tcpdump可以来检测eno2看的网络请求:

$ sudo tcpdump -n -i eno2 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno2, link-type EN10MB (Ethernet), capture size 262144 bytes
18:26:57.424083 IP 192.168.42.20 > 8.8.8.8: ICMP echo request, id 5155, seq 1, length 64
18:26:58.432816 IP 192.168.42.20 > 8.8.8.8: ICMP echo request, id 5155, seq 2, length 64
18:26:59.440803 IP 192.168.42.20 > 8.8.8.8: ICMP echo request, id 5155, seq 3, length 64
18:27:00.448842 IP 192.168.42.20 > 8.8.8.8: ICMP echo request, id 5155, seq 4, length 64
18:27:01.456825 IP 192.168.42.20 > 8.8.8.8: ICMP echo request, id 5155, seq 5, length 64
18:27:02.464842 IP 192.168.42.20 > 8.8.8.8: ICMP echo request, id 5155, seq 6, length 64

虽然eno2上能检测测ping请求,但是没有reply,虚拟机无法ping通外部网络!
所以,手动修改iptables的规则就该上场了:

sudo iptables -t nat -A POSTROUTING -s 192.168.42.0/24 -o eno2 -j MASQUERADE

再ping一次试试:

$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=38 time=99.6 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=38 time=97.7 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=38 time=83.0 ms
...

看看系统上的iptables的规则:

$ sudo iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 192.168.42.0/24 -o eno1 -j MASQUERADE
-A POSTROUTING -s 192.168.42.0/24 -o eno2 -j MASQUERADE   <- 看这里
-A DOCKER -i docker0 -j RETURN

看来虽然我们对网段192.168.42.0/24加了两个MASQUERADE规则,但它们并不互斥,这周就到这里吧。

源码分析

这里的源码来自于pike release版本,上面所讲的都是我们能看到的现象,我们看看代码里是如何实现的。
打开DevStack里这个文件,我们可以看的一清二楚:

# /lib/neutron_plugins/services/l3
98 default_v4_route_devs=$(ip -4 route | grep ^default | awk '{print $5}')
...
126     if [[ -n "$PUBLIC_INTERFACE" ]]; then
127         _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" True False "inet"
128
129         if [[ $(ip -f inet6 a s dev "$PUBLIC_INTERFACE" | grep -c 'global') != 0 ]]; then
130             _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" False False "inet6"
131         fi
132     else
133         for d in $default_v4_route_devs; do
134             sudo iptables -t nat -A POSTROUTING -o $d -s $FLOATING_RANGE -j MASQUERADE
135         done
136     fi
137 }

所以,当有设置这个PUBLIC_INTERFACE这个属性时,将会对应的物理网卡绑定到bridge上去,如果没有设置,则会对系统的默认路由对应的所有的所有物理网卡设备定义MASQUERADE规则,以实现虚拟机与外网访问的目的。

从这里我们可以看出,配置OpenStack需要至少配置两个不同的网络的原因所在:

  • 集群内部需要一个可以连接的外部网络,每个节点都有配置一个该网段的IP地址,网络节点需要将此网卡绑定到bridge上,这样虚拟机可以通过此网络访问外网,floating IP也可以配置在同一个网络里,这样其它物理节点可以直接访问虚拟机(比如虚拟机提供一些web服务那么可以直接在其它节点访问)。

  • 还需要一个可以让终端用户去访问的管理机器的网络,此网络可以是内部管理网即OpenStack API服务所在的网络。实际生产环境比这个要复杂的多,比如需要一个存储网络,租户网络,部署(Provision)网络等。

附:

  1. 查看某个table上的rules
    sudo iptables -nL -t nat –line-number

  2. 删除某个规则
    sudo iptables -D POSTROUTING 3 -t nat


个人博客:http://www.jungler.cn/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值