Packstack

简介

Packstack主要是由Redhat推出的用于概念验证(PoC)环境快速部署的工具。Packstack是一个命令行工具,它使用Python封装了Puppet模块,通过SSH在服务器上部署OpenStack。

Packstack支持三种运行模式:

  • 快速运行

  • 交互式运行

  • 非交互式运行

Packstack支持两种部署架构:

  • All-in-One,即所有的服务部署到一台服务器上

  • Multi-Node,即控制节点和计算机分离

因为Redhat官方有详细的使用文档,因此本文将简要介绍Packstack的快速运行以及交互式运行方式来部署All-in-One的Openstack。

部署前准备

在开始部署前,我们需要准备一台虚拟机,它的规格如下:

名称

要求

处理器

推荐2核以上

内存

推荐4G以上

磁盘

推荐20G以上

网卡

至少一块1G网卡

操作系统

CentOS7.2

在完成虚拟机的配置和启动后,在终端下输入以下指令:

快速运行

快速运行模式,表示用户可以对参数不做任何配置即可开始部署,用户只需要决定是单节点还是多节点的部署方式。

单节点

在packstack命令后,使用--allinonec参数在本机上部署所有服务。

多节点

使用--install-hosts参数来运行packstack,该参数值是由一个逗号隔开的IP地址列表。

Packstack在部署完成后在终端上会输出以下信息:

交互式运行

1.如果希望以交互式的方式来配置集群的部署,可以在终端下输入:

2.packstack会提示你输入一个用于保存公共密钥的路径,输入Enter,则 会使用默认的~/.ssh/id_rsa.pub

3.packstack提示输入一个默认密码,该密码将作为admin user密码, 不输入则随机生成:

4.输入每个wsgi服务的进程数,默认等于cpu的核数:

5.确认是否要安装MariaDB数据库,默认为y:

6.确认是否安装Openstack组件,可以根据需要定制服务:

7.Packstack为所有服务配置NTP服务来校准系统时间,NTP的设置只对多节点有意义:

8.是否安装Nagios监控服务:

9.哪些服务器在本次安装中被排除在外:

10.是否启用调试模式:

11.指定控制器的地址:

12.指定计算节点的地址:

13.指定网络节点的地址:

14.是否使用VMWare vCenter作为hypervisor和datastore的后端:

15.指定是否使用不支持的参数,推荐使用默认设置:

16.网卡名称是否被自动识别为子网+CIDR的格式:

17.是否为每个服务器订阅Extra Packstacks for Enterprise Linux(EPEL),建议使用默认设置:

18.是否启用自定义的软件包仓库:

19.是否启用rdo test:

20.是否启用Red Hat订阅,跳过即可:

21.ssl证书相关的操作:

22.配置AMQP服务,默认会使用RabbitMQ作为backend,不启用身份验证和SSL:

23.配置MariaDB服务

24.配置Identity服务,包括设置数据库连接的密码,创建默认的admin,demo用户等基本操作:

25.配置Image服务,包括设置数据库连接密码,glance用户密码,后端存储:

26.配置块存储服务,包括设置数据库连接密码,cinder用户和密码:

27.配置计算服务,包括flavor,资源虚拟比,迁移,虚拟化软件等参数的设置:

28.配置网络服务,包括从组件,接口,网络驱动等细节的设置:

29.设置Dashboard服务,是否开启Https服务:

30.配置对象存储服务,包括设备逻辑,zone,replicas,文件系统和块设备大小的配置:

31.是否启用Tempest服务:

32.设置Floating IP网段

33.设置测试镜像的名称,源地址,格式等配置:

34.设置Ceilometer,Aodh,Gnocchi服务:

35.设置nagios用户的密码:

36.最后一步,确认生成的配置是否符合期望,输入yes,并按回车键开始执行操作:

非交互式方式运行

使用下述命令生成一个answer file:

使用vim打开文件,每个配置项都含有详细的说明:

例如,我们不希望配置MariaDB,只需要将CONFIG_MARIADB_INSTALL设置为n:

保存并退出my_file,在终端下运行以下命令指定相应的配置文件:

深入理解Packstack

Packstack的使用非常简单,关于如何使用的介绍就到此结束。接下来才是重点,我们要深入到Packstack的核心逻辑: Plugin,并且举例说明如何编写Plugin来完成对Packstack的功能扩展。

什么是Plugin

在前面两章对于PuppetOpenstack modules的介绍中,所有服务的部署工作实际是由每个modules完成的。 在使用Packstack的时候,我们发现Packstack支持大量的服务部署,例如:nova,glance,maridb,amqp等等。在其背后每个服务的配置项管理都是由plugin实现的,其路径是在: packstack/plugins,它看起来是这样的:

  • init.py

  • amqp_002.py

  • aodh_810.py

  • ...

  • trove_850.py

每个plugin的名称都是由服务名称+下划线+三位数字编码组成,那么这些数字有什么作用?

我们来看一下packstack代码入口packstack/installer/run_setup.py是怎么加载plugins的:

在主函数入口,可以看到第一步调用了loadPlugins函数来加载插件:

接着,我们跳转到了loadPlugins函数的定义,可以看到其中使用了sorted函数对由plugin文件组成的列表进行排序:

查看函数plugin_compare的定义,我们终于找到了关键,plugin_compare使用每个plugin文件尾缀的三位数字用于排序比较:

在了解了plugin的加载顺序后,我们再看看Plugin的代码结构。实际上,每个plugin的代码结构是一致的,由两个函数组成:

  • initConfig(controller) 用于初始化Plugin的配置,主要是参数和参数组。

  • initSequences(controller) 用于定义该plugin执行的任务。

在这些plugin中,必然会有一些与众不同的plugin,比如说第一个被加载的plugin,,倒数第二个被加载的plugin,以及最后一个被加载的plugin:

  • prescript_000.py是第一个被加载的plugin,顾名思义它提供了一些全局的初始化设置,比如ssh public key,default_password,workers的进程数量,是否开启各个OpenStack服务的设置等等,同时它会在被管理的主机上执行一些预备任务:生成authorized_keys文件,安装并开启epel源和rdo源,安装puppet软件包依赖和module依赖等等。

  • puppet_950.py是一个重要的plugin,顾名思义它提供了与puppet相关的任务,例如:生成最终的manifest文件,拷贝puppet modules到指定主机,生成hieradata文件,以standalone方式运行puppet:执行puppet apply,获取puppet运行中的输出等等。

  • postscript_951.py是最后一个呗加载的plugin,它只做了一件事情,就是运行Tempest跑测试任务。

动手写一个Plugin

在了解了plugin的运行机制后,我们来动手写一个plugin,我们称之为NOOP:这是一个空Plugin,默认只输出一行信息: NOOP Plugin.

创建一个Plugin文件

在packstack/plugins目录下,我们创建一个plugin文件: noop_840.py。

设置Import和Plugin定义

每个Plugin的import可能会有所不同,但大多数都会用到packstack.installer和packstack.modules。

此外,这里有两个和plugin相关的变量:

变量

说明

PLUGIN_NAME

plugin名称,全部大写字母

PLUGIN_NAME_COLORED

plugin显示的颜色,默认使用blue即可。

定义Plugin的配置信息

我们定义一个initConfig函数,其中包含了两个变量:

  • params

  • group

params是NOOP plugin定义的配置项,每个配置项的数据类型是字典。这些配置项可以作为顺序执行的一部分,或者作为Puppet模板的变量。

选项

说明

CMD_OPTION

被命令行使用的选项名称

USAGE

选项的使用说明,同时作为answer file的注释

PROMPT

交互模式下给用户的提示

OPTION_LIST

可选值列表,可以设置为[]或移除该选项,表示对选项值无限制

VALIDATORS

验证器函数列表,用于检查输入是否符合要求

DEFAULT_VALUE

选项的默认值

PROCESSORS

处理器函数列表,处理器函数对用户的输入做了处理,比如processors.process_host将主机名转变为IP地址等等

MASK_INPUT

是否隐藏用户的输入,如password

LOOSE_VALIDATION

若为true,则即使验证器返回为false,仍然使用用户输入的选项值

CONF_NAME

在answer file中的配置项名称,你同时可以在controller.CONF dict中找到

USE_DEFAULT

若为true,在交互模式下,将不会要求用户输入此变量的值,而直接DEFAULT_VALUE

NEED_CONFIRM

若为true,则要求用户确认其输入(比如password)

CONDITION

enable/disable该选项的条件,总是设置为False即可

DEPRECATES

弃用的CONF_NAME选项列表,通常在新版本时使用

group表示组的概念,在Packstack中,会把相关的配置项分组,这样就可以通过组的方式来管理和使用。group的数据类型是字典:

选项

说明

GROUP_NAME

组名,全局唯一

DESCRIPTION

组的描述,在命令行的帮助命令下会显示此信息

PRE_CONDITION

前提条件,可以是一个配置项的值或函数的返回值匹配预期。若为False,那么该配置组处于启用状态

PRE_CONDITION_MATCH

前提条件的预期匹配值

POST_CONDITION

配置组所有参数是正确的后置条件,若设置为False,则表示不做检查。通常设置为False

POST_CONDITION_MATCH

后置条件的预期匹配值,通常设置为True

这里最重要的是PRE_CONDITION和PRE_CONDITION_MATCH,可能有些晦涩,我们以部署Cinder服务为例,只有当PRE_CONDITION中的变量CONFIG_CINDER_INSTALL为"y"时,才会显示"Cinder"组的配置选项:

最后一步,把这些已定义的选项添加controller的组中:

定义函数执行顺序

前面我们说到每个plugin除了定义一组相关的选项之外,还会执行一些任务,比如:从用户给定的变量值来渲染template,从而生成该服务的Puppet manifest文件。这些任务是由一个个函数组成,函数之间有执行的先后顺序,这个顺序就是由initSeqeuence函数来决定。

我们假设NOOP服务的安装需要数据库服务MariaDB,以及在Keystone中创建endpoint等操作:

setps是一个列表,其中每个元素的数据类型都是字典,它的格式如下:

选项

说明

title

函数的简单描述信息

functions

函数列表

最后,我们调用controller.addSequence()方法把plugin的steps添加到将要被执行的序列列表中。 通常情况下,第二个和第二个选项为空。

生成manifest文件

在讲生成manifest文件之前,我们需要花些时间来了解packstack的templates,在当前版本中packstack的templates的路径是packstack/puppet/templates,数量已经从几十个削减为3个:

  • controller

  • compute

  • network

我们以controller为例,我们选取其中的代码片段:

我们可以发现,这实质上是一个manifest文件(.pp),而非template文件(.erb),所有class或define的include不再使用erb模板的方式来渲染,而是使用了简单的条件判断来做选择。

每个函数都是接受固定的两个参数:

  • config

  • messages

Last updated

Was this helpful?