接触过 TripleO 的小伙伴应该已经领略过它的网络结构了,不得不说,还是蛮复杂的。那对于 TripleO-QuickStart 这玩意儿是否有过好奇,那么多结构是怎么在一台机器里面虚拟实现出来的?
之前花了一天的时间研究过一遍,当时的感受就是,厉害了,网络还可以这么玩。但由于一直在开发 Policy-based Routing,没时间将细节记录下来。
这就导致经常有小伙伴来找我解决相关问题时,我要把那玩意儿的网络结构再现撸一遍。就是今天,又有小伙伴问我怎么把服务面板暴露出去,easy,一层一层写 iptables 映射出去啊。
How?mmmp,又要撸一遍网络是怎么实现的。所以这次手头再忙,我也要把这玩意儿网络结构的大概给记录下来!!!

简介

嗯…在说 tripleo-quickstart前,可能首先需要了解一波什么是 tripleo 吧。
^-^我把东家的 tripleo 部署文档直接搬来吧:TripleO 部署文档

TripleO-Quckstart 是一个用来快速搭建 TripleO 测试环境的 Ansible 程序。
在部署生产环境时,会用到 instack-undercloud 这个项目来部署 undercloud,在该项目中有一个叫做 instack-virt-setup 的脚本,用来搭建测试 tripleo 用的虚拟环境,该脚本在 Ocata 版本被废弃,tripleo-quickstart 就是用来取代它的。
tripleo-quickstart 通过一系列 playbook,不仅可以用来搭建虚拟环境,还能在其上部署 undercloud 和 overcloud,而且支持多种部署模式,部署完成之后,还能跑多种测试,检验部署结果。
quickstart已经形成了一个完整的体系,而且使用方便,现在已经被社区用来跑TripleO的CI程序。

和tripleo-quickstart相关的还有一个叫做tripleo-quickstart-extras的项目,它是tripleo-quickstart功能的扩展。
其实tripleo-quickstart本身只包含搭建虚拟测试环境的功能,包括环境检查,网络/存储/虚拟机的建立等等,而具体的搭建undercloud,overcloud的功能则是在tripleo-quickstart-extras中实现的,也包括测试验证,这些功能都被抽象成了ansible中的role。
tripleo-quickstart-extras对tripleo-quickstart是没有依赖关系的,只要有环境,tripleo-quickstart-extras就用来部署undercloud/overcloud,不论是否是虚拟环境,因此在部署生产环境时也可以使用tripleo-quickstart-extras。
其实本身tripleo的部署步骤就不复杂,tripleo-quickstart-extras只是将其中一些需要手动执行的命令编排了一下,让部署变得更加简单高效了。

TripleO-Quickstart默认定义很多的部署模式,主要有以下几种:

  • minimal,只部署一台controller和一台compute节点
  • ha,部署三台controller和一台compute节点,三台controller的HA使用pacemaker管理
  • ha_big,部署三台controller和三台compute,三台controller的HA使用pacemaker管理
  • ceph,支持部署Ceph的Storage节点

其实这些都是通过简单的配置文件来设置的,tripleo-quickstart底层已经进行了很好的抽象,上层只需要简单的定义就可以支持多种部署模式了。

TripeO-Quickstart-Extras中还包含了很多验证部署结果的playbook,对部署完的集群功能是否正常进行有效验证,目前实现的主要有下面几种:

  • validate-simple,简单验证,通过执行一系列OpenStack命令,比如创建网络,建虚拟机,创建stack,来验证基本的功能是否OK
  • validate-tempest,功能验证,通过对overcloud来跑tempest测试来进行API层面的全面验证
  • validate-ha,验证HA功能,通过关停一些节点和服务来验证HA的功能
  • validate-undercloud,通过重装undercloud或者是跑一些常用OpenStack命令来验证undercloud功能

TripleO-Quickstart使用方便,环境要求简单,可以用来搭建开发测试环境,并且适合新手快速上手TripleO和OpenStack。

解析

TripeleO-Quickstart是使用Ansible Playbook进行编排的,抽象出了一系列role。
role中包含了各种具体的task,然后通过playbook对指定host进行编排。
Ansible程序写的非常好,是一个很好的典范,这里对整个流程做下解析,方便加深对其的掌握,理解其原理。
下图为执行quickstart过程中一些主要的步骤:
tripleo-quickstart-analysis

整个过程大体可以分为4个阶段,上图中分别用4种颜色标识:

  • 第一个阶段,即浅红色部分
    主要工作是清理上一次跑quickstart留下的环境,其中的non_root_user是在裸机上创建的一个用户,默认为stack,具有sudo权限,之后在裸机上执行的所有操作都是以这个用户的身份完成的。
  • 第二个阶段,即浅黄色部分
    环境的准备阶段,因为是要在一台裸机上装虚拟机测试TripleO,所以要安装kvm,libvirt等包,而且要创建虚拟机使用的volume pool和libvirt network,下载镜像,然后定义undercloud和overcloud虚拟机,并且启动undercloud虚拟机等待下一个阶段使用。
    需要注意的是,这里仅仅下载了undercloud的镜像,因为undercloud镜像中已经包含了overcloud镜像,所以不需要额外下载。
  • 第三个阶段,即浅绿色部分
    部署阶段,首先部署undercloud,然后部署overcloud,并且生成相应的rc文件,方便后面使用。
    因为本身tripleo本身就用了OpenStack中的很多组件,尤其是heat,已经进行了非常高度的抽象,因此部署步骤就很简单,quickstart将部署的命令都封装在了相应的脚本里,使用时,从ansible的模板生成,填上相应参数,传到undercloud的机器里执行。
  • 第四个阶段,即浅蓝色部分
    验证阶段,验证OverCloud部署是否正常,验证HA是否正常,跑tempest进行功能验证等等。

这四个阶段,前两个阶段的步骤基本上都是在物理机上执行的,属于环境准备阶段,搭建起了TripleO的基本环境,这部分功能是在tripleo-quickstart中实现的。
后两个阶段基本上都是在undercloud上执行的,是实际的部署验证阶段,这部分功能是在tripleo-quickstart-extras中实现的。

部署

TripleO-Quickstart的部署要求必须有一台物理服务器,在quickstart中称作VIRTHOST,因为要建多台虚拟机,所以配置至少是16G内存,32G更好,对网络没有特殊要求,能通公网就行。

除了有一台物理服务器外,还需要有一个客户端机器,能够ssh到物理服务器,操作系统需要是RedHat系的。
在quickstart中称为localhost,需要将quickstart的程序放到localhost中,然后ssh到物理服务器上执行相应的ansible程序。

本次测试将会部署一个HA模式的TripleO环境,有3个控制节点和1个计算节点,控制节点同时充当网络节点。
执行过程如下:

1
2
3
4
[root@localhost ~] export VIRTHOST='test.example.com'
[root@localhost ~] wget https://raw.githubusercontent.com/openstack/tripleo-quickstart/master/quickstart.sh
[root@localhost ~] bash quickstart.sh --install-deps
[root@localhost ~] bash ./quickstart.sh --tags all --config ~/.quickstart/tripleo-quickstart/config/general_config/ha.yml $VIRTHOST

其实我建议采用分步骤部署方式,方便定位问题,上面这种一把梭模式是在不敢恭维,是真的很难很难跑出来。
下次有空了在写一篇分步骤部署的教程吧,^-^嗯,「下次」。

在quickstart中,基本上为每一个task都通过tag做了分类,可以通过–tags来选择执行某些task,上面使用all即执行所有的task,也就是要搭建一个完整的环境。
使用–config可以指定部署模式,这里选择的是ha模式,此外还有多种模式可以选择,该配置文件还定义了一些其他参数,比如虚拟机的配置,是否跑tempest等。
因为在安装过程中要去装各种包,而且要下载undercloud的镜像,国外的网络环境较好,会遇到比较少的坑。

等待一杯咖啡的时间(这是一个同事们经常用的梗了,如果你对tripleo进行了实践,请自行体会),一个具备HA的OpenStack虚拟环境就部署好了,包含三个控制节点,一个计算节点。

网络实现原理

由于在OpenStack中最复杂最难懂的就是网络了,尤其是在虚拟环境中,网络拓扑要比物理环境还要复杂,而且是在一台物理服务器上安装一个具备完整功能的OpenStack环境。
因此,下面重点介绍下用tripleo-quickstart部署出来的集群的网络拓扑,如下图:
(好了好了,总算把上下文交代的差不多了,切我想要记录的正题。)
tripleo-undercloud-topology

在物理服务器上,通过libvirt network建立了两个linux bridge,分别为brext和brovc。
brext用来桥接undercloud,brovc用来桥接overcloud节点,undercloud虚拟机有两个网卡,分别桥接在brext和brovc上。
brext提供了访问公网的能力,brovc将多个overcloud和undercloud节点连接在一起。

192.168.23.0/24 是连通物理宿主机的网络,宿主机会建立一个名为 brext 的网卡资源,桥接在 brext 桥上,并作为该网段的网关。上文所述的undercloud其中桥接brext网桥的网卡就属于这个网络。
192.168.24.0/24 是分配给 brovc 连接的广播域的 cidr,即 overcloud 节点所在的广播域的 cidr。也就是说,overcloud 的节点 host 通过这个网络进行通信,具体IP配置在节点中桥接在提供外部网络网桥的代表该网桥的网卡资源上,注意可不是节点本身对应实体资源(虽然这里也是虚拟出来的)的网卡(这里只undercloud的eth1和overcloud的eth0),至于这个提供外部网络的网桥要看openstack二层实现的具体driver,比如这里采用的ovs,那就是br-ex。

Undercloud是一个单机版的OpenStack,安装了Nova, Neutron, Ironic, Heat等组件。
Ironic通过使用pxe_ssh driver来管理overcloud节点,Neutron为overcloud节点提供网络环境,Heat则在TripleO中被用来编排,创建整个overcloud的stack。
默认的TripleO会在undercloud中创建下面几个网络:

1
2
3
4
5
6
7
8
9
10
11
[stack@undercloud ~]$ neutron net-list
+--------------------------------------+--------------+------------------------------------------------------+
| id | name | subnets |
+--------------------------------------+--------------+------------------------------------------------------+
| 0a5f9e61-7f2a-4d1b-9b44-4f82a1412ef4 | internal_api | 0fe319dd-ec16-47c5-b039-707373b7875c 172.16.2.0/24 |
| 305526f7-d0bf-49b5-947a-d25778836cba | tenant | a71b5b1c-5f52-4efd-af21-705192bf2a70 172.16.0.0/24 |
| 9e0930f3-8180-4fa3-a955-73aca0134795 | storage_mgmt | e596d585-7c12-471e-89de-eea48cabc0df 172.16.3.0/24 |
| be6f07e5-e212-4e9e-bc7b-0edd4eb11b13 | ctlplane | ad8a6a4d-c5a3-4c44-a17d-1d1a9341f33b 192.168.24.0/24 |
| f303022b-907e-4ce6-a2c0-c1ce7fabe9ac | external | 4a47bc1b-a7f2-45a4-bd40-2f3032198b34 10.0.0.0/24 |
| fcdff6b1-43d2-4787-b458-368b48b97a73 | storage | 6de1e1b3-4972-49b1-ae19-20e163af010c 172.16.1.0/24 |
+--------------------------------------+--------------+------------------------------------------------------+

这几个网络都是Flat模式的网络(其实是使用vlan模拟出来的,虽然vlan也是模拟的,这要看在哪个层面看问题了,所以说这网络6么,一层一层的虚拟化),internal_api在overcloud中被用来作为内部API交互的网络,tenant是SDN网络,storage_mgmt是存储管理网络,ctlplane是管理网络,即ssh网络,external是外部网络,storage是存储网。

在上面的网络中,只有ctlplane的子网开启了DHCP功能,为overcloud的管理网络分配IP,因此在undercloud中有一个DHCP的namespace,通过veth tap桥接在br-int ovs网桥上。

external网络是用来开放API和面板的,跟internal_api对应,在overcloud中,API和面板分别绑定在了internal_api和external网络上,在undercloud的br-ctlplane ovs网桥上,创建了一个vlan10的port,并且在undercloud中加上了相应的路由信息,这样在undercloud中就可以直接通过这个网络访问overcloud中的API了:

1
2
3
[stack@undercloud ~]$ ip r
default via 192.168.23.1 dev eth0
10.0.0.0/24 dev vlan10 proto kernel scope link src 10.0.0.1

在overcloud中,通过在br-ex ovs网桥上绑定多个带tag的port,并且每个port分配了IP,来模拟多个网络,分别对应undercloud中创建的网络。在br-ex中的每个port都带着vlan tag,模拟交换机的access口,通过不同的vlan互相隔离。

控制节点和计算节点之间的SDN网络,即tenant网络,在上面图中使用黄色标注,即vlan50,通过vxlan建立隧道,使用vlan50上的ip作为对端IP。

其他就是标准的Neutron网络了。

那么跟 devstack 面临一样的问题来了(详见 devstack网络实现简述 ),怎样使建立出来的 tenant 虚机访问 Internet 呢?
这里可不能随便建一个网络指定成 external 网络(设定成 external 网络即代表会做端口复用的snat),再使用 iptables 做映射就行了,因为QS在外面一层要模拟真实网络的广播域环境,即在这里映射成上文中的各个’假’flat网络。
这不,external 已经给你建好了。接下来,我们需要进行一下操作:

  1. 在undercloud上,使用 iptables 给 external 网络做 masquerade (即把10.0.0.0/24来源数据包在undercloud上连接宿主机网络的网口上,这里是192.168.23.10,进行端口复用)
  2. 在物理宿主机上,使用 iptables 给 192.168.23.0/24 这个网络做 masquerade (即把192.168.23.0/24来源数据包在宿主机物理真实网卡上进行端口复用)
  3. 前两步操作进行的系统上,看看 iptables 有没有禁止相关流量,有的话取消掉

最后,来看看怎么暴露出面板服务接口吧!
我最先给出小伙伴的解决方案比较麻烦:

  1. 在宿主机上创建一个连接overcloud节点广播域的网卡资源,即桥接至 brovc,封上vlan10的 tag
  2. 将新创建网卡ip(10.0.0.0/24段)与服务endpoint做静态映射
  3. 新创建网卡ip和真实物理网卡ip的端口映射

结果就是,外部访问到宿主机ip端口,映射成undercloud的24段ip,再接着映射成endpoint。

然而现在经过前面的分析,我们可以直接省略掉打通24段广播域这一步,转向使用23段。
具体步骤类似:

  1. 将endpoint与undercloud 23段的ip做端口映射
  2. 宿主机上,undercloud 23段的 ip 与真实物理网卡做端口映射
  3. 注意 iptables 的 filter 表限制

我将最后方案的实现写成了脚本(需要用到 ansible),需要的小伙伴请自取:
TripleO-QuickStart-PortForwarding