在Puppet中,模块是服务器配置的构建块。模块安装和配置包,创建目录,并生成用户在模块中包含的任何其他服务器更改。Puppet模块旨在执行特定任务的所有部分,例如下载Apache包,配置所有文件,更改MPM数据以及设置虚拟主机。反过来,模块被分解为扩展名为.pp
的类文件,这些文件旨在将模块简化为各种任务,并提高模块的可读性。
在本指南中,Apache和PHP模块将从头开始创建,MySQL模块将改编自Puppet Forge上的PuppetLab的MySQL模块。这些步骤将在您的服务器上创建一个完整的LAMP堆栈,并提供各种使用模块的方式的概述。
注意
本指南假设您使用的是Pbupet 设置指南中配置的Ubuntu 14.04 LTS Puppet master和CentOS 7和Ubuntu 14.04节点。如果使用不同的设置,请进行相应调整。
创建Apache模块
- 从Puppet Master,导航到Puppet的模块目录并创建apache目录:
cd /etc/puppet/modules
sudo mkdir apache
- 从内部
apache
目录,创建manifests
,templates
,files
,和examples
目录:
cd apache
sudo mkdir {manifests,templates,files,examples}
- 导航到
manifests
目录:
cd manifests
从这里开始,模块将根据特定代码段的目标分成几类。在这个例子中,将有一个init.pp
类用于下载Apache包,一个params.pp
用于定义任何变量和参数,config.pp
文件用于管理Apache服务本身的任何配置文件,以及一个vhosts.pp
用于定义虚拟主机的文件。该模块还将利用Hiera数据存储每个节点的变量。
创建Apache初始化类和参数
- 在manifests目录中,init.pp需要创建一个类。这个类的名称应该和模块名称一致:
/etc/puppet/modules/apache/manifests/init.pp
代码语言:txt复制class apache {
}
该文件将用于安装Apache包。但是,Ubuntu 14.04和CentOS 7下的Apache包名并不一样,因此,将使用变量进行处理:
/etc/puppet/modules/apache/manifests/init.pp
代码语言:txt复制class apache {
package { 'apache':
name => $apachename,
ensure => present,
}
}
该package
资源允许管理包,用于添加,删除或确保包存在。在大多数情况下,资源的名称('apache',见上文)应为要管理的包的名称。但是,由于命名约定的不同,这个资源只是简单的命名为apache
,而使用名称引用调用包的实际名称。在上面的实例中,.name
调用尚未定义的变量$apachename
,ensure
引用则用来确保包存在。
- 既然有变量需要定义,那么这个
params.pp
类就会发挥作用。虽然可以在init.pp
代码中定义这些变量,但是因为有很多变量需要在资源类型本身之外使用,使用params.pp
类可以在if
块中定义变量并在多个类中使用。
创建并打开params.pp
:
/etc/puppet/modules/apache/manifests/params.pp
代码语言:txt复制class apache::params {
}
在原始init.pp
类之外,每个类名都应为apache
分支。因此,这个类被称为apache::params
。双冒号后面的名称应与文件名相同。
- 现在应该定义参数。为此,我们将添加一个
if
块,从已经安装在Puppet master上的Facter提供的信息中提取。在本案中,Facter将用于下拉操作系统系列(osfamily
),以识别它是基于Red Hat还是基于Debian。if
块的骨架应类似于以下内容:
/etc/puppet/modules/apache/manifests/params.pp
代码语言:txt复制class apache::params {
if $::osfamily == 'RedHat' {
} elseif $::osfamily == 'Debian' {
} else {
print "This is not a supported distro."
}
}
一旦我们添加了已经引用的变量:
/etc/puppet/modules/apache/manifests/params.pp
代码语言:python代码运行次数:0复制class apache::params {
if $::osfamily == 'RedHat' {
$apachename = 'httpd'
} elseif $::osfamily == 'Debian' {
$apachename = 'apache2'
} else {
print "This is not a supported distro."
}
}
注意
在本指南的持续时间内,当需要将某些内容添加到参数列表中时,将提供Red Hat和Debian所需的变量,但不会显示扩展代码。可在此处查看
params.pp
的完整副本。
- 随着参数的定义完成,我们需要将
params.pp
文件和参数引入到init.pp
。要做到这一点,需要在类名之后、花括号({
)之前添加参数:
/etc/puppet/modules/apache/manifests/init.pp
代码语言:txt复制class apache (
$apachename = $::apache::params::apachename,
) inherits ::apache::params {
值字符串$::apache::params::value
告诉Puppet从apache
模块的params
类中提取值,然后是参数名称。该片段inherits ::apache::params
允许init.pp
继承这些值。
管理配置文件
Apache有两个不同的配置文件,取决于您是在使用基于Red Hat还是基于Debian的系统。这些文件可以从服务器中拉取,或者在这里查看:httpd.conf(Red Hat),apache2.conf(Debian)。
- 将
httpd.conf
和apache2.conf
文件复制到files
目录。位于/etc/puppet/modules/apache/files/
。 - 需要编辑这两个文件将
KeepAlive
设置设置为Off
。需要在httpd.conf
文件中添加此设置,否则,应将以下注释添加到每个文件的顶部:
/etc/puppet/modules/apache/files/httpd.conf
代码语言:txt复制# This file is managed by Puppet
- 现在需要将这些文件添加到
init.pp
文件中,使Puppet知道它们在主服务器和代理节点上的位置。为此,使用file
资源:
/etc/puppet/modules/apache/manifests/init.pp
代码语言:txt复制file { 'configuration-file':
path => $conffile,
ensure => file,
source => $confsource,
}
由于配置文件位于两个不同的位置,因此将为资源指定通用名称configuration-file
,并将文件路径定义为具有该path
属性的参数。ensure
确保它是一个文件。source
是另一个参数,它将调用上面创建的主文件位于Puppet master上的位置。
- 打开
params.pp
文件。$conffile
与$confsource
变量需要在if
语句块中定义:
/etc/puppet/modules/apache/manifests/params.pp
代码语言:txt复制if $::osfamily == 'RedHat' {
...
$conffile = '/etc/httpd/conf/httpd.conf'
$confsource = 'puppet:///modules/apache/httpd.conf'
} elsif $::osfamily == 'Debian' {
...
$conffile = '/etc/apache2/apache2.conf'
$confsource = 'puppet:///modules/apache/apache2.conf'
} else {
...
根据附加参数的示例,还需要将这些参数添加到init.pp
文件中。init.pp
文件的完整副本可在此处查看。
- 更改配置文件后,Apache需要重新启动。要自动执行此操作,可以结合
notify
属性使用service
资源,只要配置文件发生更改,就会调用该资源:
/etc/puppet/modules/apache/manifests/init.pp
代码语言:txt复制file { 'configuration-file':
path => $conffile,
ensure => file,
source => $confsource,
notify => Service['apache-service'],
}
service { 'apache-service':
name => $apachename,
hasrestart => true,
}
service
资源使用已创建的参数,该参数在Red Hat和Debian系统上定义了Apache名称。hasrestart
属性将触发已定义服务的重新启动。
创建虚拟主机文件
虚拟主机文件将以不同方式进行管理,具体取决于服务器是基于Red Hat还是Debian发行版。因此,虚拟主机的代码将被包含在if
语句块中,类似于params.pp
类中使用的语句,但包含实际的Puppet资源。下面将提供在Puppet代码中使用if
语句块的示例。
- 在
apache/manifests/
目录中,创建并打开vhosts.pp
文件。 - 创建
if
语句块的框架:
/etc/puppet/modules/apache/manifests/vhosts.pp
代码语言:txt复制class apache::vhosts {
if $::osfamily == 'RedHat' {
} elsif $::osfamily == 'Debian' {
} else {
}
}
- 在CentOS 7服务器上的虚拟主机文件的位置是
/etc/httpd/conf.d/vhost.conf
。此文件需要在Puppet master上创建为模板。对于Ubuntu服务器,需要做同样的事情,该文件位于/etc/apache2/sites-available/example.com.conf
,使用服务器的FQDN替换example.com
。还需要在Puppet主服务器上创建此文件的模板。导航到apache模块中的templates
文件夹,然后为虚拟主机创建两个文件:
对于Red Hat系统:
/etc/puppet/modules/apache/templates/vhosts-rh.conf.erb
代码语言:txt复制<VirtualHost *:80>
ServerAdmin <%= @adminemail %>
ServerName <%= @servername %>
ServerAlias www.<%= @servername %>
DocumentRoot /var/www/<%= @servername -%>/public_html/
ErrorLog /var/www/<%- @servername -%>/logs/error.log
CustomLog /var/www/<%= @servername -%>/logs/access.log combined
</Virtual Host>
对于Debian系统:
/etc/puppet/modules/apache/templates/vhosts-deb.conf.erb
代码语言:txt复制<VirtualHost *:80>
ServerAdmin <%= @adminemail %>
ServerName <%= @servername %>
ServerAlias www.<%= @servername %>
DocumentRoot /var/www/html/<%= @servername -%>/public_html/
ErrorLog /var/www/html/<%- @servername -%>/logs/error.log
CustomLog /var/www/html/<%= @servername -%>/logs/access.log combined
<Directory /var/www/html/<%= @servername -%>/public_html>
Require all granted
</Directory>
</Virtual Host>
在这些文件中使用了两个变量:adminemail
和servername
。这些变量将在每个节点的site.pp
文件中进行定义。
- 回到
vhosts.pp
文件,现在可以在代码中引用创建的模板: /etc/puppet/modules/apache/manifests/vhosts.pp
class apache::vhosts {
if $::osfamily == 'RedHat' {
file { '/etc/httpd/conf.d/vhost.conf':
ensure => file,
content => template('apache/vhosts-rh.conf.erb'),
}
} elsif $::osfamily == 'Debian' {
file { "/etc/apache2/sites-available/$servername.conf":
ensure => file,
content => template('apache/vhosts-deb.conf.erb'),
}
} else {
print "This is not a supported distro."
}
}
两个分发系列都调用file
资源并在相应的分发上获取虚拟主机位置的标题。对于Debian,这再次意味着引用$servername
值。content
属性调用相应的模板。
注意
变量(例如上面的Debian文件资源的名称)需要用双引号括起来(
"
)。单引号('
)中的任何变量都完全按照写入进行解析,不会引入变量。
- 默认情况下,两个虚拟主机文件都引用两个不在分发中的目录。这些目录可以通过使用
file
资源创建,每个资源都位于if
语句块中。完整的vhosts.conf
文件应该类似于: /etc/puppet/modules/apache/manifests/vhosts.pp
class apache::vhosts {
if $::osfamily == 'RedHat' {
file { '/etc/httpd/conf.d/vhost.conf':
ensure => file,
content => template('apache/vhosts-rh.conf.erb'),
}
file { "/var/www/$servername":
ensure => directory,
}
file { "/var/www/$servername/public_html":
ensure => directory,
}
file { "/var/www/$servername/log":
ensure => directory,
}
} elsif $::osfamily == 'Debian' {
file { "/etc/apache2/sites-available/$servername.conf":
ensure => file,
content => template('apache/vhosts-deb.conf.erb'),
}
file { "/var/www/$servername":
ensure => directory,
}
file { "/var/www/html/$servername/public_html":
ensure => directory,
}
file { "/var/www/html/$servername/logs":
ensure => directory,
}
} else {
print "This is not a supported distro."
}
}
测试和运行模块
- 定位到
apache/manifests/
目录,运行puppet parser
验证所有文件,以确保Puppet编码正确:
sudo puppet parser validate init.pp params.pp vhosts.pp
返回结果应该为空,除非出现任何问题。
- 导航到
apache
模块中的examples
目录。创建一个init.pp
文件并包含创建的类。为servername
和提供变量adminemail
: /etc/puppet/modules/apache/examples/init.pp
$serveremail = 'webmaster@example.com'
$servername = 'example.com'
include apache
include apache::vhosts
- 执行
puppet apply
并附加--noop
标记来测试模块:
sudo puppet apply --noop init.pp
它应该不返回任何错误,并且会响应事件更新输出。如果需要在Puppet主服务器上安装和配置apache,可以不带--noop
标签再次运行puppet apply
。
- 导航回Puppet主目录,然后导航到
manifests
文件夹(不是位于Apache模块中的文件夹)。如果您从Puppet设置指南继续本指南,则应该已经创建了一个名为site.pp
的文件。如果没有,请立即创建一个。node 'ubuntuhost.example.com' { $adminemail = 'webmaster@example.com' $servername = 'hostname.example.com' include accounts include apache include apache::vhosts resources { 'firewall': purge => true, } Firewall { before => Class['firewall::post'], require => Class['firewall::pre'], } class { ['firewall::pre', 'firewall::post']: } } node 'centoshost.example.com' { $adminemail = 'webmaster@example.com' $servername = 'hostname.example.com' include accounts include apache include apache::vhosts resources { 'firewall': purge => true, } Firewall { before => Class['firewall::post'], require => Class['firewall::pre'], } class { ['firewall::pre', 'firewall::post']: } } - 打开
site.pp
并为每个代理节点添加Apache模块。并输入adminemail
和servername
参数的变量。如果您遵循Puppet设置指南,其中的单个节点配置site.pp
将类似于以下内容: /etc/puppet/manifests/site.pp - 要在代理节点上运行新模块,请登录节点并运行:
sudo puppet agent -t
使用MySQL模块
许多运行服务器所需的模块已经存在于Puppet Lab的Puppet Forge中。这使得你可以像创建的模块一样进行广泛地配置这些组件,并且可以节省时间,因为无需从头开始创建模块。
通过PuppetLabs 安装Puppet Forge的MySQL模块:
代码语言:txt复制sudo puppet module install puppetlabs-mysql
这也将安装任何必备模块。
使用Hiera创建数据库
在开始为MySQL模块创建配置文件之前,考虑到您可能不希望在所有代理节点上使用相同的值,使用Hiera,Pupper支持为每个节点提供正确的数据。在本实例中,您将为每个节点提供不同的root密码,从而创建不同的MySQL数据库。
- 导航到主目录
/etc/puppet
并创建Hiera的配置文件:hiera.yamlpuppet
/etc/puppet/hiera.yaml
代码语言:txt复制:backends:
- yaml
:yaml:
:datadir: /etc/puppet/hieradata
:hierarchy:
- "nodes/%{::fqdn}"
- common
:backends:
下面的值定义您正在YAML中写入数据,而:datadir:
调用Hiera存储数据的目录。:hierarchy:
部分表示您的数据将保存在node
目录下的文件中,文件以节点的FQDN命名。一个common
文件将包含默认的变量。
- 确保在
/etc/puppet/
目录中,为hieradata
和nodes
创建目录:
sudo mkdir -p hieradata/nodes
- 导航到
nodes
目录:
cd hieradata/nodes
- 使用该
puppet cert
命令列出可用的节点,然后使用FQDN作为文件名称为每个节点创建YAML文件:
sudo puppet cert list --all
sudo touch {ubuntuhost.example.com.yaml,centoshost.example.com.yaml}
- 打开第一个节点的配置文件以定义第一个数据库。在此示例中,数据库名为
webdata1
,自定义username
和password
。该grant
值授予用户对webdata1数据库的所有访问权限: /etc/puppet/hieradata/nodes/ubuntuhost.example.com.yaml
databases:
webdata1:
user: 'username'
password: 'password'
grant: 'ALL'
重复第二个服务器。在此示例中,数据库名为webdata2
:
/etc/puppet/hieradata/nodes/centoshost.example.com.yaml
代码语言:txt复制databases:
webdata2:
user: 'username'
password: 'password'
grant: 'ALL'
保存并关闭文件。
- 返回
hieradata
目录并创建文件common.yaml
。它将用于定义root
用户的默认密码: /etc/puppet/hieradata/common.yamlmysql::server::root_password: 'password'如果未在其他位置定义变量,则使用common.yaml
文件。这意味着所有服务器将共享相同的MySQL root密码。这些密码也可以进行哈希处理以提高安全性。class mysql::database { include mysql::server create_resources('mysql::db', hiera_hash('databases')) } - Puppet现在需要知道使用Hiera中的信息输入来创建定义的数据库。移动到
mysql
模块目录并在manifests
目录创建database.pp
文件。在这里,您将定义一个将mysql::db
资源链接到Hiera数据的类。它也会调用mysql::server
类,因此不必在以后包含它: /etc/puppet/modules/mysql/manifests/database.pp - 在您的
site.pp
文件中两个节点包含include mysql::database
。
创建PHP模块
- 创建
php
目录modules
路径,随后创建files
,manifests
,templates
,和examples
子文件夹:
sudo mkdir php
cd php
sudo mkdir {files,manifests,examples,templates}
- 创建并打开
init.pp
。因为所有要做的就是PHP服务正确安装,并且能够在启动时启动,所有代码都将包含在此文件中。class php { package { 'php': name: $phpname, ensure: present, } package { 'php-pear': ensure: present, } }因为php
程序包在Ubuntu和CentOS上具有不同的名称,所以它将再次需要使用参数进行定义。但是,因为这是我们需要的唯一参数,所以它将直接添加到init.pp
文件中: /etc/puppet/modules/php/manifests/init.pp - 将安装两个软件包:PHP软件包和PHP扩展和应用程序库。使用此
package
资源: /etc/puppet/modules/php/manifests/init.pp
class php {
$phpname = $osfamily ? {
'Debian' => 'php5',
'RedHat' => 'php',
default => warning('This distribution is not supported by the PHP module'),
}
package { 'php':
name => $phpname,
ensure => present,
}
package { 'php-pear':
ensure => present,
}
}
- 使用该
service
资源确保PHP已启用并设置为开机启动: /etc/puppet/modules/php/manifests/init.ppclass php { $phpname = $osfamily ? { 'Debian' => 'php5', 'RedHat' => 'php', default => warning('This distribution is not supported by the PHP module'), } package { 'php': name => $phpname, ensure => present, } package { 'php-pear': ensure => present, } service { 'php-service': name => $phpname, ensure => running, enable => true, } } - 添加
include php
到sites.pp
文件中的主机中,并在代理节点上运行puppet agent -t
,以便对服务器进行任何更改。