puppet-openstack-integration

  1. 先睹为快 - 一言不合,立马动手?
  2. 核心代码讲解 - scenario
  3. 小结
  4. 动手练习 - 光看不练假把式

Puppet-openstack-integration模块确保社区可以持续地测试和验证使用Puppet modules部署的Openstack集群。

建议在阅读其他module前,优先阅读本节内容。

本节作者:余兴超
阅读级别:必读
阅读时间 1小时

先睹为快

如果你想要使用puppet modules部署一套all-in-one的openstack集群,那么可以在虚拟机(Ubuntu 14.04或者CentOS 7.x)的终端下执行以下命令:

  1. git clone git://git.openstack.org/openstack/puppet-openstack-integration
  2. cd puppet-openstack-integration
  3. ./all-in-one.sh

或者

  1. 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函数。

  1. # 函数定义
  2. PUPPET_ARGS="${PUPPET_ARGS} --detailed-exitcodes --color=false --test --trace"
  3. PUPPET_FULL_PATH=$(which puppet)
  4. function run_puppet() {
  5. local manifest=$1
  6. $SUDO $PUPPET_FULL_PATH apply $PUPPET_ARGS fixtures/${manifest}.pp
  7. local res=$?
  8. return $res
  9. }

在下面连续调用了两次run_puppet函数:

  1. # SCENARIO即要运行的manifests文件,决定了安装哪些服务
  2. print_header "Running Puppet Scenario: ${SCENARIO} (1st time)"
  3. run_puppet $SCENARIO
  4. RESULT=$?
  5. set -e
  6. if [ $RESULT -ne 2 ]; then
  7. print_header 'SELinux Alerts (1st time)'
  8. catch_selinux_alerts
  9. exit 1
  10. fi
  11. # Run puppet a second time and assert nothing changes.
  12. set +e
  13. print_header "Running Puppet Scenario: ${SCENARIO} (2nd time)"
  14. run_puppet $SCENARIO
  15. RESULT=$?
  16. set -e
  17. if [ $RESULT -ne 0 ]; then
  18. print_header 'SELinux Alerts (2nd time)'
  19. catch_selinux_alerts
  20. exit 1
  21. 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

  1. #从类的名称我们就可以知道aio安装了mq,mysql,keystone,glance,neutron等服务
  2. include ::openstack_integration
  3. include ::openstack_integration::rabbitmq
  4. include ::openstack_integration::mysql
  5. include ::openstack_integration::keystone
  6. include ::openstack_integration::glance
  7. include ::openstack_integration::neutron
  8. include ::openstack_integration::nova
  9. include ::openstack_integration::cinder
  10. include ::openstack_integration::horizon
  11. include ::openstack_integration::provision
  12. # aio中还配置了tempest,除了默认支持的nova,keystone,glance等服务外,开启了对于horizon和cinder的测试集
  13. class { '::openstack_integration::tempest':
  14. horizon => true,
  15. cinder => true,
  16. }

那么接下来,我们进入到这些被调用的类中一探究竟。为了节省篇幅,我们分别挑选了mq和glance进行解释和说明。

class openstack_integration::rabbitmq

我们可以理解为在openstack_integration的manifests目录下,所有和服务相关的类都是转发层,即对某个服务模块的调用。

在openstack_integration::rabbitmq中,通过调用class rabbitmq完成了对rabbitmq的安装和配置,并创建了一个路径为’/‘的vhost,更多对rabbitmq类的介绍,请参见puppet-rabbitmq模块。

  1. class openstack_integration::rabbitmq {
  2. include ::openstack_integration::params
  3. include ::openstack_integration::config
  4. if $::openstack_integration::config::ssl {
  5. file { '/etc/rabbitmq/ssl/private':
  6. ensure => directory,
  7. owner => 'root',
  8. mode => '0755',
  9. selinux_ignore_defaults => true,
  10. before => File["/etc/rabbitmq/ssl/private/${::fqdn}.pem"],
  11. }
  12. openstack_integration::ssl_key { 'rabbitmq':
  13. key_path => "/etc/rabbitmq/ssl/private/${::fqdn}.pem",
  14. require => File['/etc/rabbitmq/ssl/private'],
  15. notify => Service['rabbitmq-server'],
  16. }
  17. class { '::rabbitmq':
  18. package_provider => $::package_provider,
  19. delete_guest_user => true,
  20. ssl => true,
  21. ssl_only => true,
  22. ssl_cacert => $::openstack_integration::params::ca_bundle_cert_path,
  23. ssl_cert => $::openstack_integration::params::cert_path,
  24. ssl_key => "/etc/rabbitmq/ssl/private/${::fqdn}.pem",
  25. environment_variables => $::openstack_integration::config::rabbit_env,
  26. }
  27. } else {
  28. class { '::rabbitmq':
  29. package_provider => $::package_provider,
  30. delete_guest_user => true,
  31. environment_variables => $::openstack_integration::config::rabbit_env,
  32. }
  33. }
  34. rabbitmq_vhost { '/':
  35. provider => 'rabbitmqctl',
  36. require => Class['::rabbitmq'],
  37. }
  38. }

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完成后端存储的配置
  1. class openstack_integration::glance (
  2. $backend = 'file',
  3. ) {
  4. include ::openstack_integration::config
  5. include ::openstack_integration::params
  6. if $::openstack_integration::config::ssl {
  7. openstack_integration::ssl_key { 'glance':
  8. notify => [Service['glance-api'], Service['glance-registry']],
  9. }
  10. Package<| tag == 'glance-package' |> -> File['/etc/glance/ssl']
  11. $key_file = "/etc/glance/ssl/private/${::fqdn}.pem"
  12. $crt_file = $::openstack_integration::params::cert_path
  13. Exec['update-ca-certificates'] ~> Service['glance-api']
  14. Exec['update-ca-certificates'] ~> Service['glance-registry']
  15. } else {
  16. $key_file = undef
  17. $crt_file = undef
  18. }
  19. rabbitmq_user { 'glance':
  20. admin => true,
  21. password => 'an_even_bigger_secret',
  22. provider => 'rabbitmqctl',
  23. require => Class['::rabbitmq'],
  24. }
  25. rabbitmq_user_permissions { 'glance@/':
  26. configure_permission => '.*',
  27. write_permission => '.*',
  28. read_permission => '.*',
  29. provider => 'rabbitmqctl',
  30. require => Class['::rabbitmq'],
  31. }
  32. class { '::glance::db::mysql':
  33. password => 'glance',
  34. }
  35. include ::glance
  36. include ::glance::client
  37. class { '::glance::keystone::auth':
  38. public_url => "${::openstack_integration::config::base_url}:9292",
  39. internal_url => "${::openstack_integration::config::base_url}:9292",
  40. admin_url => "${::openstack_integration::config::base_url}:9292",
  41. password => 'a_big_secret',
  42. }
  43. case $backend {
  44. 'file': {
  45. include ::glance::backend::file
  46. $backend_store = ['file']
  47. }
  48. 'rbd': {
  49. class { '::glance::backend::rbd':
  50. rbd_store_user => 'openstack',
  51. rbd_store_pool => 'glance',
  52. }
  53. $backend_store = ['rbd']
  54. # make sure ceph pool exists before running Glance API
  55. Exec['create-glance'] -> Service['glance-api']
  56. }
  57. 'swift': {
  58. Service<| tag == 'swift-service' |> -> Service['glance-api']
  59. $backend_store = ['swift']
  60. class { '::glance::backend::swift':
  61. swift_store_user => 'services:glance',
  62. swift_store_key => 'a_big_secret',
  63. swift_store_create_container_on_put => 'True',
  64. swift_store_auth_address => "${::openstack_integration::config::keystone_auth_uri}/v3",
  65. swift_store_auth_version => '3',
  66. }
  67. }
  68. default: {
  69. fail("Unsupported backend (${backend})")
  70. }
  71. }
  72. $http_store = ['http']
  73. $glance_stores = concat($http_store, $backend_store)
  74. class { '::glance::api':
  75. debug => true,
  76. database_connection => 'mysql+pymysql://glance:glance@127.0.0.1/glance?charset=utf8',
  77. keystone_password => 'a_big_secret',
  78. workers => 2,
  79. stores => $glance_stores,
  80. default_store => $backend,
  81. bind_host => $::openstack_integration::config::host,
  82. auth_uri => $::openstack_integration::config::keystone_auth_uri,
  83. identity_uri => $::openstack_integration::config::keystone_admin_uri,
  84. registry_client_protocol => $::openstack_integration::config::proto,
  85. registry_client_cert_file => $crt_file,
  86. registry_client_key_file => $key_file,
  87. registry_host => $::openstack_integration::config::host,
  88. cert_file => $crt_file,
  89. key_file => $key_file,
  90. }
  91. class { '::glance::registry':
  92. debug => true,
  93. database_connection => 'mysql+pymysql://glance:glance@127.0.0.1/glance?charset=utf8',
  94. keystone_password => 'a_big_secret',
  95. bind_host => $::openstack_integration::config::host,
  96. workers => 2,
  97. auth_uri => $::openstack_integration::config::keystone_auth_uri,
  98. identity_uri => $::openstack_integration::config::keystone_admin_uri,
  99. cert_file => $crt_file,
  100. key_file => $key_file,
  101. }
  102. class { '::glance::notify::rabbitmq':
  103. rabbit_userid => 'glance',
  104. rabbit_password => 'an_even_bigger_secret',
  105. rabbit_host => $::openstack_integration::config::ip_for_url,
  106. rabbit_port => $::openstack_integration::config::rabbit_port,
  107. notification_driver => 'messagingv2',
  108. rabbit_use_ssl => $::openstack_integration::config::ssl,
  109. }
  110. }

小结

puppet-openstack_integration模块为PuppetOpenstack项目提供了集成测试的功能,同时也为用户提供了快速部署AIO测试环境的脚本。如果你是刚开始了解该项目,那么这个模块是快速熟悉Openstack各个基础模块的一条路径。

动手练习

  1. 在aio场景中添加sahara服务
  2. 在install_module.sh中的r10k命令的作用是?
  3. bundler的作用是什么?