一、Puppet模块、 类、 模板

   资源、 类、 模块、 模板构建成了Puppet的核部分。 通过资源的定义告诉Puppet应该去做什么; 可 将多个资源封装成类; 为管理便, 还会将多个类组合成模块。 可由节点直接引类名, 有系统变量时可通过模板来传递。

  • 模块( Module) , 多个类的集合。 个应编写个模块。 

  • 类( Class) , 多个资源的集合。 对应实例的不同功能进封装。 

  • 模板( Template) , ERB模板。 根据服务器硬件信息定制化不同配置件。

1、模块结构

   Puppet模块包含代码和数据包。 可以按Puppet语法规范编写的模块, 然后分享到互联供他 使, 也可以使Puppet Forge和Example42从上下载后直接使或修改后使。 下我们通过图1来了解Puppet模块结构。 

   图1以nginx模块为例对Puppet模块进了简单的剖析, 并没有包含全部, 但以说明它的内部核 结构及组成。 Puppet模块核组成包括: manifests、 files、 templates( erb) 、 lib, 还可以包括tests、 spec。查看图1的录树, 具体如下:

$ tree /etc/puppet/modules/nginx
├── LICENSE
├── Modulefile
├── README
├── files  //文件存储目录
│ └── nginx.conf
├── manifests  //清单存储目录
│ └── init.pp   //必须包含且只能包含一个与模块同名的类
│ └── vhost.pp
│ └── config.pp  //每个清单文件通常只包含一个类
├── templates   //模板存储目录
│ └── vhost.conf.erb

自动化运维工具puppet(三)_puppet

2、模块管理

   要进模块管理需要先了解modulepath。 将模块存放在modulepath录, 以便Puppet可以查找得 到。 如果是创建模块, 建议在模块根录创建Modulefile和README: Modulefile对模块版本进说明, README对模块使进说明。 

实例: 创建个模块

   在创建模块前我们需要先了解模块的录modulepath。 可以在终端下使puppet apply命令和 modulespath参数查看当前Puppet的模块配置录:

# puppet apply --configprint modulepath
/etc/puppet/modules:/opt/puppet/share/puppet/modules

   通常, 默认录为/etc/puppet/modules, 因此我们需要将编写的模块信息放在此录中, 以便 Puppet可以查找得到。以图1为例, 创建个nginx模块。 为快速了解模块结构, 本例只创建init.pp、 nginx.conf.erb及模 块说明件。

  • 创建模块所需要的录。 

$ cd /etc/puppet/modules
$ mkdir -p nginx/{manifests,templates,files}

为了简便起见, 本测试实例仅创建三个核录, 具体如下:

  • 创建模块配置件manifests代码。 

$ cd /etc/puppet/modules/nginx/manifests
$ vim init.pp
class nginx {
package { 'nginx':
ensure => installed,
}
service { 'nginx':
name => nginx,
ensure => running,
enable => true,
subscribe => File['nginx.conf'],
} 
file { 'nginx.conf':
ensure => present,
mode => 644, owner => root, group => root,
path => '/etc/nginx/nginx.conf',
content => template("nginx/nginx.conf.erb"),
}}

manifests代码主要是init.pp, 具体如下:

   manifests代码中定义了个类, 类名为nginx, 类中包含3个资源: 软件包、 服务及件。 其中服务资源依赖于件资源, nginx.conf件内容采content属性定义来源于template中对应的nginx.conf.erb模板内容。 

  • 使template函数创建ERB模板。 

$ cd /etc/puppet/modules/nginx/templates
$ sudo vim nginx.conf.erb
user daemon daemon;
worker_processes<%= processorcount %>;
pid /var/run/nginx.pid;
error_log /var/log/nginx/error.log;
worker_rlimit_nofile 51200;
events
{
use epoll;
worker_connections 51200;
}
http
{
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_names_hash_bucket_size 128;
server {
listen 80;
server_name _;
location /nginx_status {
stub_status on;
access_log off;
}
}
}

模板的内容为nginx主配置件nginx.conf。 其中作进程数worker_processes由facts进传递。 实 现代码如下: 

  • 创建说明件, 实现代码如下: 

$ cd /etc/puppet/modules/nginx
$ sudo vim Modulefile
name 'nginx'
version '0.0.1'
author 'liuyu'
license 'Apache License Version 2.0'
summary 'Puppet NGINX management module'
description 'This module can be used for basic NGINX Management'
project_page 'http://xxxx/nginx'
$ sudo vim README
# NGINX Module
Yu Liu <liuyu105@gmail.com>
This module manages NGINX from within Puppet.
USAGE:
# Standard Classes
include nginx

模块布局:

   在使模块前我们先看下Puppet针对模块的布局是什么样的。 我们将按照录层次来逐进 介绍。 假设我们创建的模块my_module包括如下代码: 

/etc/puppet/modules/my_module/
|-- files
|-- lib
|-- manifests
| |-- config.pp
| |-- implementation
| | `-- foo.pp
| |-- init.pp
| `-- vhost.pp
|-- templates
| `-- vhost.conf.erb
`-- tests

#级目录, 模块名my_module

#级目录,manifests、 templates、 files、 lib、 tests

#三级目录, 可定义, 例如, implementation

#级目录manifests定义模块清单

| |-- config.pp #配置件定义, 使法: my_module::config

| |-- implementation

| | `-- foo.pp #使my_module::implementation::foo

| |-- init.pp #包含类的所有定义, 类名需要与模块名匹配

| `-- vhost.pp #虚拟主机件定义, 使的法为my_module::vhost

|-- files #静态件, 节点下载使

|-- templates #模板清单件

|--vhost.conf.erb

|-- lib #插件, 定义facts与定义资源类型

|-- tests #展如何使资源、 类等

对于在前面创建的nginx模块, 其布局如下:

# tree/etc/puppet/modules/nginx
/etc/puppet/modules/nginx
|-- Modulefile
|-- README
|-- files
|-- manifests
| `-- init.pp
`-- templates
|-- nginx.conf.erb

通过README的说明, 在节点配置件中进include nginx配置就可以引nginx模块中的nginx 类。 定义节点agent.domain.com的配置件如下: 

$ sudo vim /etc/puppet/manifests/agent.domain.com.pp
node 'agent.domain.com' {
include nginx
}

在agent.domain.com客户端执如下puppet命令:

# puppet agent --test --server puppet.domain.com
Info: Retrieving plugin
Info: Caching catalog for agent.domain.com
Info: Applying configuration version '1358083364'
#省略中间过程
Finished catalog run in 3.91 seconds

   到此为我们已经完成模块的创建, 在创建过程过学习了模块的布局。 当在模块中定义的类和使 的资源较多时, 资源之间依赖关系将变得较为复杂, 这给我们编写模块带来了不便。 Puppet提供资源依赖图, 在客户端执puppet命令时加上graph参数可以成关系依赖图。 刚才编写的nginx模块中到的资源关系依赖图如图2所。

自动化运维工具puppet(三)_puppet_02

3、类管理

   Class是用于通用目标或目的的一组资源,因此,它是命名的代码块,在某位置创建之后可在puppet全局使用。类似于其它编程语言中的类的功能,puppet的类可以继承,也可以包含子类。类名在manifests的实现代码中的init.pp中进定义, 个模块也可以创建多个类, 在init.pp中定 义的类可以称为基础类, 通常基础类名与模块名致。

类的定义 :

 类的定义通过: 个关键字及

个代码块实现, 具体如下:

class class_name { … }

如果在同个模块定义了多个类, 可以采双冒号( :: ) 。 例如定义个nginx模块, 模块中 定义三个类: 

class nginx { … }
class nginx::config { … }
class nginx::vhost { … }

在前面我们约定config与vhost同为nginx的类, nginx类声明这两个类时使了require:

class nginx {
require nginx::config
require nginx::vhost
…}

类的继承 :

类的继承主要是个类继承另个类, 且可以实现覆盖资源属性、 追加资源属性。 下以nginx模 块代码为例来介绍类的继承。 

定义nginx为类, nginx: : foo为类。 类的代码如下:

nginx {
service { 'nginx':
name => nginx,
ensure => running,
enable => true,
require => File['nginx.conf'],
}
}
  • 继承资源属性 

nginx: : foo继承nginx类的资源属性且不做修改, 代码如下:

nginx::foo inherits nginx {
service['nginx'] { ensure => running, enable => true }
}

注意 :当有基类( base class) 的继承关系时, Puppet2.7将不再持有参数的类作为基类, 基类必须是参的。 

  • 覆盖资源属性 

nginx: : foo继承nginx类的资源属性并将enable属性覆盖, 代码如下:

nginx::foo inherits nginx {
service['nginx'] { ensure => running, enable =>false }
}

上述代码实现了将类的enable参数原值从true修改为false, 即开机时不启动nginx。 如果定义了基类, 也可以继承并修改, 代码如下: 

class base::freebsd inherits base::unix {
File['/etc/passwd'] {
group => 'wheel'
}
File['/etc/shadow'] {
group => 'wheel'
}
}

如果想取消以上代码中某个属性的值, 可以使undef值覆盖原有值, 结果就像是此属性从来都没 有被定义过样。 具体法如下: 

class base::freebsd inherits base::unix {
File['/etc/passwd'] {
group =>undef,
}
}
  • 追加资源属性 

nginx: : foo继承nginx类的资源属性, 并通过require对资源属性进值追加:

nginx::foo inherits nginx {
service { 'nginx':
require +> [ File['nginx.conf'], File['foo.conf']],
}
}

在上述代码中, 通过require+>进参数追加后, 在类nginx: : foo中所定义的service资源变为依 赖于两个件才能启动nginx, 其他参数默认将全部继承, 即nginx: : foo变为: 

nginx::foo {
service { 'nginx':
nam => nginx,
ensure => running,
enable => true,
require=> File['nginx.conf'],File['foo.conf'],
}
}

参数化类 :

   如果个类被声明多次, 并存在相互盾的参数值, 这个时候Puppet会编译失败。 有效的解决法 就是使Hiera( 可称为参数动查询) 。 为解决个类被声明多次时参数的冲突可以采如下种做法: 

  • Hiera使参数化类, 向上兼容Puppet 3.0。 

  • 使“经典”模块设计, 不使参数化类。 

  • 严格使“纯”参数化类, 可能使ENC。 

  • 使混合模式, 使Hiera或参数化类。 

   参数化类是指通过动态变量的查找将参数传递到类。 可以在个节点范围内设置些变量, 进类 的声明, 并将变量分配给范围, 这个类就会去查找所需的信息并进应。 参数化类的缺点如下: 

  • 基本上所有变量将应到全局命名空间。 这意味着需要知道所定义的所有变量, 避免重复, 否则会产冲突。 

  • 没有不完全声明个类。 没有内置的式告诉哪些参数需要设置哪个类, 所以需要记 录并维护。 

  • 较混乱。 范围的作域可以在别的地引, 这会导致作域的失效。 

   可以说参数化的类有定的好处, 但规模应时却常烦, 会增加管理成本, 这需要读者根据 的环境选择不同的配置式。 使“经典”模块化配置或参数化配置。

( 1) 参数化类的定义

class nginx ( $packages, $port ) { … }

参数化类的定义与传统式样, 类名与左括号之间采括号进参数列表的定义, 具体如下:

( 2) 参数化类的使

局部变量$packages和$port在类的定义中可作为参数名称, 也可以在类作域内引, 具体如下:

#作为参数名称
class nginx( $packages, $port ) {
package { $packages: ensure => present }
#在类作域内引
file { 'nginx.conf':
port => $port,
ensure => file,
}
}

( 3) 参数设置默认值

为某些参数指定默认值, 具体如下:

class nginx( $packages, $port = '80' ) {
…
}

或者使如下代码为所有参数指定默认值, 具体如下:

class nginx(
packages = 'nginx',
port = '80' ) {
…
}

( 4) 声明参数化类

在定义类的属性时声明指定的参数, 具体如下:

class { 'nginx' : $packages =>'nginx', $port =>'80' ,}

或者声明所有的默认值, 具体如下:

class { 'nginx' : }

( 5) 参数化类的应例

下我们将通过则判断实现来看下参数化类的应:

$ vim /etc/puppet/modules/nginx/manifests/params.pp
class nginx::params {
$packages = $operatingsystem ? {
/(?i-mx:ubuntu|debian)/ => 'nginx',
/(?i-mx:centos|fedora|redhat)/ => 'nginx2',
}
$port = $operatingsystem ? {
/(?i-mx:ubuntu|debian)/ => '80',
/(?i-mx:centos|fedora|redhat)/ => '81',
}
$ vim /etc/puppet/modules/nginx/manifests/init.pp
class nginx (
$packages = $nginx::params::packages,
$port = $nginx::params::port
) inherits nginx::params {
package { $packages: ensure => present }
file { 'nginx.conf':
port => $port,
ensure => file,
}
}

在以上代码清单中声明参数作为类定义的部分, 类的声明中包含$packages与$port两个参数。nginx类在应时会根据系统的判断传递两个变量值, 并继承nginx: : params的属性。

再来看另外个例。 声明参数作为如下类定义的部分:

class eventmachine( $version ) {
package { "eventmachine":
provider => gem,
ensure => $version,
}
}

在个节点上使如下语法来包含类:

class { "eventmachine": version => "0.12.8" }

在以上代码中, 定义的类带了个参数$version。 在节点加载eventmachine类时需要为参数

$version指定了个值。

4、模板管理

  • 定义与声明 

   Puppet模板主要是基于ERB模板语的, 是Ruby语标准库中的部分。 在模板中可以使的变 量是调此模板的当前类中的所有变量, 包含facts、 全局变量、 在类中定义的当前作域变量。 

( 1) 标签

除打上标签的内容外, ERB模板中的内容会原封不动地传送回Puppet。 ERB标签是以尖括号对在 外、 百分号对在内为标志, 其中可包含或多Ruby代码, 具体如下: 

<% document = "" %>

( 2) 打印表达式

要打印个表达式, 需要使打印标签, 就是在正常标签的左侧百分号后加个等于号。 例如, 在 打印个普通的标签sectionheader时, 可以通过如下代码实现打印个值: 

<%= sectionheader %>

或者通过以下代码实现任意复杂的Ruby表达式:

environment = <%= gitrevision[0,5] %>

这样变量$sectionheader的值会直接打印到标签所在位置。

( 3) 注释

注释代码不会被解析为代码, 也不会显式输出, 例如:

<%# This comment will be ignored. %>

( 4) 禁换

如果ERB代码有明确的写法, 可以使如下代码避免换带来的空影响美观。

<% document += thisline-%>

例如定义个模板件时需要在对应的模块录下创建相应的以.rb结尾的件。 假设模块录 为/etc/puppet/modules。 以nginx模块为例, 创建个vhost.conf.erb模板件, 在模板件中定义变量 $port, 代码如下: 

在声明这个模板时需要在资源中使content, 代码如下:

$ cd /etc/puppet/modules/nginx/templates
$ vim vhost.conf.erb
server {
listen $port;
server_name _;
location /nginx_status {
stub_status on;
access_log off;
}
}

在声明这个模板时需要在资源中使content, 代码如下:

$ vim vhost.pp
define nginx::vhost ($port) {
file { 'vhost.conf':
path => '/etc/nginx/config/vhosts/vhost.conf',
ensure => file,
require => Package['nginx'],
content => template('nginx/vhost.conf.erb')
}
}

   Puppet会查找nginx模块录下template录中的 vhost.conf.erb( /etc/puppet/modules/nginx/templates/vhost.conf.erb) 件。 ERB件的内容即 vhots.conf件的内容。 

   值得注意的是, 以上ERB模板中仅定义个变量$port。 ERB更重要的功能是: 可以通过facter命 令获取变量进传递。 如果ERB模板是数组, 也可以采如下代码进声明: 

content => template('nginx/vhost.conf.erb', 'nginx/config.erb')

Puppet会运算所有的模板, 并将所有输出合并成个字符串并返回。

  • ERB模板语法 

ERB模板的配置通常取决于所使的配置式, 它是Ruby标准库中的个模板。 常的配置语法 如下: 

%= Ruby expression %> #直接替换成表达式的值

<% Ruby code %> #Ruby代码, 包括条件、 循环等

<%# comment %> #注释

<%% or %%> #等同于<% or %>, 分别进

<%- #等同于<%, 闭合标签, 控制代码前输出量空格

-%> #等同于%>, 闭合标签, 控制代码后输出量空

(1)常规定义

在配置语法中, <%=Ruby expression %>是最常见的法, 例如将ipaddress作为变量:

<%= @ipaddress %>

#写成<%= ipaddress %> Puppet也能识别

ipaddress的值将通过facter传递:

$ facter|grep ipaddress
ipaddress => 192.168.1.126
ipaddress_en0 => 192.168.1.126
ipaddress_lo0 => 127.0.0.1

(2)引变量

   在当前范围内的变量可以作为Ruby的实例变量, 例如@fqdn、 @operatingsystem。 在当前范围内的变量也可以作为Ruby的局部变量, 使fqdn、 operatingsystem, 前没有@符号。 这种使法有可能导致变量名冲突, 所以建议使@符号。 

   Puppet传递个scope对象到模板中, 其中包含当前设定的变量, 以及其他数据( 函数) 等。 也可 以使scope对象的lookupvar法找到任何变量。 

  • 超出作域范围的变量 

如果想在本地作域外查找变量, 可以使scope.lookupvar法:

<%= scope.lookupvar('apache::user') %>

也可以像下这样使, 以确保在本地作域内能得到个变量:

<%= scope.lookupvar('::domain') %>
  • 测试个不明确的变量 

当创建的变量具有不确定因素时, 可以使if @variable的法:

<% if @myvar %>
myvar has <%= @myvar %> value
<% end %>

这时候其他模板通常会使has_variable? ( "myvar") 帮助函数, 但这可能会导致变量结果为 undef, 这需要避免。 

如果需要测试的变量在当前作域名之外, 应该将其复制到局部变量中测试, 具体如下:

  • 获取当前作域下所有变量名 

   如果使的作域在个to_hash下, 可以得到个在当前作域下的所有哈希变量定义列表。 这 个哈希列表使多个变量( osfamily) , 不是合格的名称( : : osfamily) 。 

如下代码将打印当前作域下定义的所有变量名:

<% scope.to_hash.keys.each do |k| -%>
<%= k %>
<% end -%>

(3)模板结合

如果有多个模板时, 可以使逗号进结合, 例如:

template('my_module/template1.erb','my_module/template2.erb')

(4)数组迭代

ERB模板同样持数组迭代。 如果要访问的变量是个数组, 可以循环地遍历它, 例如:

定义ERB模板, 代码如下:

<% values.each do |val| -%>
Some stuff with <%= val %>
<% end -%>

这时候输出的结果为:

Some stuff with val1
Some stuff with val2
Some stuff with otherval

这使了闭合标签-%>以避免产换。

利数组的迭代进循环遍历, 较常见的使环境就是实现四层代理软件Haproxy的后端多台 Server配置。 假设Haproxy后端有3台Web Server, 那么Haproxy.conf配置件应该配置为: 

global
…
defaults
…
listen localhost 0.0.0.0:80
mode http
option httpchk GET /index.htm
server s1 192.168.1.3:80 weight 3 check
server s2 192.168.1.4:80 weight 3 check
server s2 192.168.1.5:80 weight 3 check

要实现以上代码中的配置件, 可以定义ERB模板件内容为:

# more /etc/puppet/modules/haproxy/templates/haproxy.conf.erb
global
…d
efaults
…l
isten localhost 0.0.0.0:80
mode http
option httpchk GET /index.htm
<% instance=1 %>
<% server.each do |ip| %>server s<%=instance%> <%=ip%>:80 weight 3 check
<% instance+=1
end -%>

在节点配置中定义数组为:

# more /etc/puppet/manfiests/nodes/agent.domain.com.pp
node 'agent.domain.com' {
$server = ['192.168.1.3', '192.168.1.4', '192.168.1.5']
include haproxy
}

(5)条件表达式

ERB模板中条件表达式的使法如下:

<% if broadcast != "NONE" %> broadcast <%= broadcast %><% end %>

(6)语法检查

语法检查使的是Ruby语的检查法, 具体如下:

erb -P -x -T '-' mytemplate.erb | ruby -c

5、融合

回顾下所定义的模块内容。

  • 模块名: nginx。 

  • 类名: nginx。 

  • 类名: nginx: : configng、 inx: : vhost。 

  • 件: nginx.conf。 

  • ERB模板: vhost.conf.erb。 

  • 变量: $port 。 

  • 追加个facts变量: $ipaddress。 

要声明此类, 需要在节点代码中进include, 具体如下:

$ sudo vim /etc/puppet/manifests/nodes/agent.domain.com.pp
node 'agent.domain.com' {
#加载nginx模块
include nginx
}

再将此节点加站点件site.pp中进import, 具体如下:

$ sudo vim /etc/puppet/manifests/site.pp
#追加如下
import "nodes/agent.domain.com.pp"

通过图3可以直观地看到Puppet是如何查找定义的件并进作的。

自动化运维工具puppet(三)_puppet_03

二、应用举例

1、 使用带参数的类:

        $webserver = $operatingsystem ? {
                /^(?i-mx:redhat|centos|fedora)/  => 'httpd',
                /^(?i-mx:ubuntu|debian)/         => 'apache2',
        }
        class httpd ($pkgname = 'apache2') {
                package {"$pkgname":
                        ensure  => present,
                }
                service {"$pkgname":
                        ensure  => true,
                        require => Package["$pkgname"],
                }
        }
        class {'httpd':
                pkgname => $webserver,
        }

2、类继承

[root@example.com tmp]# vim test10.pp 
class nginx {
 package {"nginx":
  ensure =>present,
 }
}
class nginx::rproxy inherits nginx {
 file {'/etc/nginx/nginx.conf':
  ensure => file,
  source => '/tmp/nginx/nginx.reverse_proxy.conf',
  require => Package['nginx'],
  force => true,
  notify => Service['nginx'],
 }
 
 service {'nginx':
  ensure => true,
 }
}
class nginx::web inherits nginx {
 file {'/etc/nginx/nginx.conf':
  ensure => file,
  source => '/tmp/nginx/nginx.web.conf',
  notify => Service['nginx'],
 }
 
 service {'nginx':
  ensure => true,
 }
}
[root@example.com tmp]# mkdir nginx

将两者个配置文件做下区别:

[root@example.com tmp]# grep "worker_connections" nginx/nginx.web.conf 
    worker_connections  10222;
[root@example.com tmp]# grep "worker_connections" nginx/nginx.reverse_proxy.conf 
    worker_connections  10240;
[root@example.com tmp]# vim node.pp
import "/tmp/test10.pp"
include nginx::web
[root@example.com tmp]# puppet apply node.pp 
[root@example.com tmp]# grep "worker_connections" /etc/nginx/nginx.conf
    worker_connections  10222;

3、创建nginx的模块

 nginx安装 :nginx包 

做为web服务的配置文件:nginx::web  包含:file 、service 

做为反向代理的配置文件:nginx::rproxy 包含:file 、service

当前系统puppet查找的默认配置目录:

[root@www.example.com  modules]#  puppet agent --configprint modulepath
/etc/puppet/modules:/usr/share/puppet/modules
[root@www.example.com modules]# mkdir nginx/{manifests,files,templates} -pv
[root@www.example.com modules]# cd nginx/manifests/
[root@www.example.com manifests]# vim init.pp
class nginx {
        package {'nginx':
                ensure   => present,
        }
}
[root@www.example.com nginx]# cp /etc/nginx/nginx.conf files/nginx.web.conf
[root@www.example.com nginx]# cp /etc/nginx/nginx.conf files/nginx.rproxy.conf
[root@www.example.com nginx]# grep 'worker_connections' files/nginx.web.conf
    worker_connections  10222;
[root@www.example.com nginx]# grep 'worker_connections' files/nginx.rproxy.conf
    worker_connections  10240;
[root@www.example.com nginx]# cd manifests/
[root@www.example.com manifests]# vim web.pp
class nginx::web inherits nginx {
        file {'nginx.conf':
                ensure   => file,
                source   => "puppet:///modules/nginx/nginx.web.conf",
                path     => '/etc/nginx/nginx.conf',
                require  => Package['nginx'],
                mode     => '0644',
                notify   => Service['nginx'],
        }
        service {'nginx':
                ensure   => true,
                enable   => true,
                restart  => '/etc/init.d/nginx reload',
        }
}
[root@www.example.com manifests]# vim rproxy.pp
class nginx::rproxy inherits nginx {
        file {'nginx.conf':
                ensure   => file,
                source   => "puppet:///modules/nginx/nginx.rproxy.conf",
                path     => '/etc/nginx/nginx.conf',
                require  => Package['nginx'],
                mode     => '0644',
                notify   => Service['nginx'],
        }
        service {'nginx':
                ensure   => true,
                enable   => true,
                restart  => '/etc/init.d/nginx reload',
        }
}

测试:

第一种使用模块方法:

[root@www.example.com manifests]# rpm -e nginx
[root@www.example.com manifests]# rm -rf /etc/nginx/
[root@www.example.com manifests]# puppet apply -e 'include nginx::rproxy'
notice: /Stage[main]/Nginx/Package[nginx]/ensure: created
notice: /Stage[main]/Nginx::Rproxy/File[nginx.conf]/content: content changed '{md5}d9dfc198c249bb4ac341198a752b9458' to '{md5}44223269ca784ab1bdd91ce78a042feb'
notice: /Stage[main]/Nginx::Rproxy/Service[nginx]/ensure: ensure changed 'stopped' to 'running'
notice: /Stage[main]/Nginx::Rproxy/Service[nginx]: Triggered 'refresh' from 1 events
notice: Finished catalog run in 11.08 seconds
[root@www.example.com manifests]# grep 'worker_connections' /etc/nginx/nginx.conf
    worker_connections  10240;

第二种使用模块方法:

[root@www.example.com ~]# cat local.pp
node 'www.example.com' {
 include nginx ::web
}
[root@www.example.com ~]# puppet apply local.pp
notice: /Stage[main]/Nginx::Web/File[nginx.conf]/content: content changed '{md5}d9dfc198c249bb4ac341198a752b9458' to '{md5}09bd56f2a8067c5a9644380a682ff85f'
notice: /Stage[main]/Nginx::Web/Service[nginx]/ensure: ensure changed 'stopped' to 'running'
notice: /Stage[main]/Nginx::Web/Service[nginx]: Triggered 'refresh' from 1 events
notice: Finished catalog run in 0.53 seconds
[root@www.example.com ~]# grep 'worker_connections' /etc/nginx/nginx.conf
    worker_connections  10222;

4、模版的使用举例

[root@www.example.com manifests]# vim init.pp 
class nginx {
        package {'nginx':
                ensure   => present,
        }
        file {'nginx.conf':
                ensure   => file,
                content  => template('nginx/nginx.conf.erb'),
                path     => '/etc/nginx/nginx.conf',
                require  => Package['nginx'],
                mode     => 0644,
        }
}
[root@www.example.com manifests]# rm -f ../files/nginx.*
[root@www.example.com manifests]# cd ../files/
[root@www.example.com files]# ls
[root@www.example.com files]# cp /etc/nginx/conf.d/default.conf nginx.web.conf
[root@www.example.com files]# cp /etc/nginx/conf.d/default.conf nginx.rproxy.conf
[root@www.example.com files]# ls
nginx.rproxy.conf  nginx.web.conf
[root@www.example.com files]# vim nginx.web.conf
server {
    listen       80 default_server;
    server_name  www.example.com;
    #charset koi8-r;
    #access_log  logs/host.access.log  main;
    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
[root@www.example.com files]# vim nginx.rproxy.conf 
server {
    listen       80 default_server;
    server_name  _;
    #charset koi8-r;
    #access_log  logs/host.access.log  main;
    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;
    location / {
        #root   /usr/share/nginx/html;
        #index  index.html index.htm;
        proxy_pass http://192.168.1.9;
    }
[root@www.example.com files]# cp /etc/nginx/nginx.conf ../templates/
[root@www.example.com files]# cd ../templates/
[root@www.example.com templates]# vim nginx.conf 
worker_processes  <%= @processorcount %>;
[root@www.example.com templates]# mv nginx.conf nginx.conf.erb
[root@www.example.com templates]# cd ../manifests/
[root@www.example.com manifests]# vim web.pp
class nginx::web inherits nginx {
        file {'nginx.web.conf':
                ensure   => file,
                source   => "puppet:///modules/nginx/nginx.web.conf",
                path     => '/etc/nginx/conf.d/default.conf',
                require  => Package['nginx'],
                mode     => '0644',
        }
        service {'nginx':
                ensure   => true,
                enable   => true,
                restart  => '/etc/init.d/nginx reload',
                subscribe=> File['nginx.conf','nginx.web.conf'],
        }
}
[root@www.example.com manifests]# vim rproxy.pp 
class nginx::rproxy inherits nginx {
        file {'nginx.rproxy.conf':
                ensure   => file,
                source   => "puppet:///modules/nginx/nginx.rproxy.conf",
                path     => '/etc/nginx/conf.d/default.conf',
                require  => Package['nginx'],
                mode     => '0644',
        }
        service {'nginx':
                ensure   => true,
                enable   => true,
                restart  => '/etc/init.d/nginx reload',
                subscribe=> File['nginx.conf','nginx.rproxy.conf'],
        }
}
[root@www.example.com manifests]# rpm -e nginx
[root@www.example.com manifests]# rm -rf /etc/nginx/
[root@www.example.com manifests]# puppet apply -e 'include nginx::web'
notice: /Stage[main]/Nginx/Package[nginx]/ensure: created
notice: /Stage[main]/Nginx::Web/File[nginx.web.conf]/content: content changed '{md5}d5ac7759792ba2917893f73a19cc085a' to '{md5}f5a613106188b7e187f58f376cc704b9'
notice: /Stage[main]/Nginx/File[nginx.conf]/content: content changed '{md5}d9dfc198c249bb4ac341198a752b9458' to '{md5}09bd56f2a8067c5a9644380a682ff85f'
notice: /Stage[main]/Nginx::Web/Service[nginx]/ensure: ensure changed 'stopped' to 'running'
notice: /Stage[main]/Nginx::Web/Service[nginx]: Triggered 'refresh' from 2 events
notice: Finished catalog run in 13.97 seconds

查看配置是否生效:

[root@www.example.com ~]# vim /etc/nginx/conf.d/default.conf
server {
    listen       80 default_server;
    server_name  www.example.com;
    #charset koi8-r;
    #access_log  logs/host.access.log  main;
    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
[root@www.example.com ~]# vim /etc/nginx/nginx.conf
worker_processes  1;
[root@www.example.com ~]# grep 'processor' /proc/cpuinfo  
processor: 0

注意:使用模板生成文件时,使用的文件属性为content。content     => template('module_name/template_file_name')