puppet-openstack-integration
Puppet-openstack-integration
模块确保社区可以持续地测试和验证使用 Puppet modules 部署的 Openstack 集群。
建议在阅读其他 module 前,优先阅读本节内容。
本节作者:余兴超
阅读级别:必读 阅读时间 1 小时
先睹为快
如果你想要使用 puppet modules 部署一套 all-in-one 的 openstack 集群,那么可以在虚拟机(Ubuntu 14.04 或者 CentOS 7.x) 的终端下执行以下命令:
git clone git://git.openstack.org/openstack/puppet-openstack-integration
cd puppet-openstack-integration
./all-in-one.sh
或者
curl -sL http://git.openstack.org/cgit/openstack/puppet-openstack-integration/plain/all-in-one.sh | bash
整个过程约需要 20 分钟。
我们分析以下这是怎么做到的?
all-in-one.sh 是一个逻辑比较简单的脚本,其调用了 run_tests.sh 脚本。 这个脚本的主要作用有 3 点:
- 安装 Puppet 相关软件包,
- 执行 puppet apply 命令,完成相应服务的安装配置
- 安装配置 tempest 并相应运行 smoke 测试
这里面主要讲解一下是如何实现服务的安装配置,主要使用的是 run_puppet 函数。
# 函数定义
PUPPET_ARGS="${PUPPET_ARGS} --detailed-exitcodes --color=false --test --trace"
PUPPET_FULL_PATH=$(which puppet)
function run_puppet() {
local manifest=$1
$SUDO $PUPPET_FULL_PATH apply $PUPPET_ARGS fixtures/${manifest}.pp
local res=$?
return $res
}
在下面连续调用了两次 run_puppet 函数:
# SCENARIO 即要运行的 manifests 文件,决定了安装哪些服务
print_header "Running Puppet Scenario: ${SCENARIO} (1st time)"
run_puppet $SCENARIO
RESULT=$?
set -e
if [ $RESULT -ne 2 ]; then
print_header 'SELinux Alerts (1st time)'
catch_selinux_alerts
exit 1
fi
# Run puppet a second time and assert nothing changes.
set +e
print_header "Running Puppet Scenario: ${SCENARIO} (2nd time)"
run_puppet $SCENARIO
RESULT=$?
set -e
if [ $RESULT -ne 0 ]; then
print_header 'SELinux Alerts (2nd time)'
catch_selinux_alerts
exit 1
fi
核心代码讲解
目前 Openstack Intra 一共使用了三个测试场景,用于跑 puppetopenstack 的集成测试: scenario001, scenario002,scenario003.
而 scenario-aio manifest 是提供给想要了解和学习 PuppetOpenstack 项目的用户。它们之间的区别参见下表:
- | scenario001 | scenario002 | scenario003 | scenario-aio |
---|---|---|---|---|
ssl | yes | yes | yes | no |
ipv6 | centos7 | centos7 | centos7 | no |
keystone | X | X | X | X |
tokens | uuid | uuid | fernet | uuid |
glance | rbd | swift | file | file |
nova | rbd | X | X | X |
neutron | ovs | ovs | linuxbridge | ovs |
cinder | rbd | iscsi | iscsi | |
ceilometer | X | |||
aodh | X | |||
gnocchi | rbd | |||
heat | X | |||
swift | X | |||
sahara | X | |||
trove | X | |||
horizon | X | X | ||
ironic | X | |||
zaqar | X | |||
ceph | X | |||
mongodb | X |
scenario-aio
这里我们以 scenario-aio 来解释它是如何部署起一个 Openstack All-in-One 的环境的。 scenario-aio 的文件路径为: fixtures/scenario-aio.pp
#从类的名称我们就可以知道 aio 安装了 mq,mysql,keystone,glance,neutron 等服务
include ::openstack_integration
include ::openstack_integration::rabbitmq
include ::openstack_integration::mysql
include ::openstack_integration::keystone
include ::openstack_integration::glance
include ::openstack_integration::neutron
include ::openstack_integration::nova
include ::openstack_integration::cinder
include ::openstack_integration::horizon
include ::openstack_integration::provision
# aio 中还配置了 tempest,除了默认支持的 nova,keystone,glance 等服务外,开启了对于 horizon 和 cinder 的测试集
class { '::openstack_integration::tempest':
horizon => true,
cinder => true,
}
那么接下来,我们进入到这些被调用的类中一探究竟。为了节省篇幅,我们分别挑选了 mq 和 glance 进行解释和说明。
class openstack_integration::rabbitmq
我们可以理解为在 openstack_integration 的 manifests 目录下,所有和服务相关的类都是转发层,即对某个服务模块的调用。
在 openstack_integration::rabbitmq 中,通过调用 class rabbitmq 完成了对 rabbitmq 的安装和配置,并创建了一个路径为'/'的 vhost,更多对 rabbitmq 类的介绍,请参见 puppet-rabbitmq 模块。
class openstack_integration::rabbitmq {
include ::openstack_integration::params
include ::openstack_integration::config
if $::openstack_integration::config::ssl {
file { '/etc/rabbitmq/ssl/private':
ensure => directory,
owner => 'root',
mode => '0755',
selinux_ignore_defaults => true,
before => File["/etc/rabbitmq/ssl/private/${::fqdn}.pem"],
}
openstack_integration::ssl_key { 'rabbitmq':
key_path => "/etc/rabbitmq/ssl/private/${::fqdn}.pem",
require => File['/etc/rabbitmq/ssl/private'],
notify => Service['rabbitmq-server'],
}
class { '::rabbitmq':
package_provider => $::package_provider,
delete_guest_user => true,
ssl => true,
ssl_only => true,
ssl_cacert => $::openstack_integration::params::ca_bundle_cert_path,
ssl_cert => $::openstack_integration::params::cert_path,
ssl_key => "/etc/rabbitmq/ssl/private/${::fqdn}.pem",
environment_variables => $::openstack_integration::config::rabbit_env,
}
} else {
class { '::rabbitmq':
package_provider => $::package_provider,
delete_guest_user => true,
environment_variables => $::openstack_integration::config::rabbit_env,
}
}
rabbitmq_vhost { '/':
provider => 'rabbitmqctl',
require => Class['::rabbitmq'],
}
}
class openstack_integration::glance
挑选 glance 的原因在于其代码相比其他服务更简洁一些,读者理解起来会稍微容易一些。 我们可以看到其
- 调用 glance::api 和 glance::resgistry 完成了 glance 服务的配置
- 调用 glance::notify::rabbitmq 完成了 MQ 的配置
- 调用 glance::db::mysql 完成数据库的配置
- 调用 glance::client 完成 client 的配置
- 调用 glance::keystone::auth 完成 glance keystone 相关的配置
- 通过传递的参数值,选择调用 glance::backend::file/glance::backend::rbd/glance::backend::swift 完成后端存储的配置
class openstack_integration::glance (
$backend = 'file',
) {
include ::openstack_integration::config
include ::openstack_integration::params
if $::openstack_integration::config::ssl {
openstack_integration::ssl_key { 'glance':
notify => [Service['glance-api'], Service['glance-registry']],
}
Package<| tag == 'glance-package' |> -> File['/etc/glance/ssl']
$key_file = "/etc/glance/ssl/private/${::fqdn}.pem"
$crt_file = $::openstack_integration::params::cert_path
Exec['update-ca-certificates'] ~> Service['glance-api']
Exec['update-ca-certificates'] ~> Service['glance-registry']
} else {
$key_file = undef
$crt_file = undef
}
rabbitmq_user { 'glance':
admin => true,
password => 'an_even_bigger_secret',
provider => 'rabbitmqctl',
require => Class['::rabbitmq'],
}
rabbitmq_user_permissions { 'glance@/':
configure_permission => '.*',
write_permission => '.*',
read_permission => '.*',
provider => 'rabbitmqctl',
require => Class['::rabbitmq'],
}
class { '::glance::db::mysql':
password => 'glance',
}
include ::glance
include ::glance::client
class { '::glance::keystone::auth':
public_url => "${::openstack_integration::config::base_url}:9292",
internal_url => "${::openstack_integration::config::base_url}:9292",
admin_url => "${::openstack_integration::config::base_url}:9292",
password => 'a_big_secret',
}
case $backend {
'file': {
include ::glance::backend::file
$backend_store = ['file']
}
'rbd': {
class { '::glance::backend::rbd':
rbd_store_user => 'openstack',
rbd_store_pool => 'glance',
}
$backend_store = ['rbd']
# make sure ceph pool exists before running Glance API
Exec['create-glance'] -> Service['glance-api']
}
'swift': {
Service<| tag == 'swift-service' |> -> Service['glance-api']
$backend_store = ['swift']
class { '::glance::backend::swift':
swift_store_user => 'services:glance',
swift_store_key => 'a_big_secret',
swift_store_create_container_on_put => 'True',
swift_store_auth_address => "${::openstack_integration::config::keystone_auth_uri}/v3",
swift_store_auth_version => '3',
}
}
default: {
fail("Unsupported backend (${backend})")
}
}
$http_store = ['http']
$glance_stores = concat($http_store, $backend_store)
class { '::glance::api':
debug => true,
database_connection => 'mysql+pymysql://glance:glance@127.0.0.1/glance?charset=utf8',
keystone_password => 'a_big_secret',
workers => 2,
stores => $glance_stores,
default_store => $backend,
bind_host => $::openstack_integration::config::host,
auth_uri => $::openstack_integration::config::keystone_auth_uri,
identity_uri => $::openstack_integration::config::keystone_admin_uri,
registry_client_protocol => $::openstack_integration::config::proto,
registry_client_cert_file => $crt_file,
registry_client_key_file => $key_file,
registry_host => $::openstack_integration::config::host,
cert_file => $crt_file,
key_file => $key_file,
}
class { '::glance::registry':
debug => true,
database_connection => 'mysql+pymysql://glance:glance@127.0.0.1/glance?charset=utf8',
keystone_password => 'a_big_secret',
bind_host => $::openstack_integration::config::host,
workers => 2,
auth_uri => $::openstack_integration::config::keystone_auth_uri,
identity_uri => $::openstack_integration::config::keystone_admin_uri,
cert_file => $crt_file,
key_file => $key_file,
}
class { '::glance::notify::rabbitmq':
rabbit_userid => 'glance',
rabbit_password => 'an_even_bigger_secret',
rabbit_host => $::openstack_integration::config::ip_for_url,
rabbit_port => $::openstack_integration::config::rabbit_port,
notification_driver => 'messagingv2',
rabbit_use_ssl => $::openstack_integration::config::ssl,
}
}
小结
puppet-openstack_integration 模块为 PuppetOpenstack 项目提供了集成测试的功能,同时也为用户提供了快速部署 AIO 测试环境的脚本。如果你是刚开始了解该项目,那么这个模块是快速熟悉 Openstack 各个基础模块的一条路径。
动手练习
- 在 aio 场景中添加 sahara 服务
- 在 install_module.sh 中的 r10k 命令的作用是?
- bundler 的作用是什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论