一.类class
官方文档:
1.概述
类是用于通用目标的一组资源(只有在打算重复使用这段代码时才有必要声明成类),因此它是命名的代码块,在某个位置创建之后可以在puppet全局使用。
类可以放在模块中,通过声明的方式进行使用,而声明时通过include这么等函数就可以实现,或者声明可以使用一个类似于资源申报语法一样的语法来使用;
它类似与其他编程语言中类的功能,puppet的类可以被继承也可以包含子类。
2.语法格式
基础语法格式:
class class_name {
puppet_code
}
类的名称只能以小写字母开头,可以包含小写字母、数字和下划线;
每个类都会引入一个新的变量作用域(scope),这意味着在任何时候访问类中的变量时,都得使用其完全限定名称(不过,在本地scope可以重新top scope中的变量赋予一个新值);
在manifest文件中定义的类不会直接被执行,它们需要实现声明后才能被执行(声明通常可以理解为调用);
示例:
不带参数的类:
class
base::linux {
file { '/etc/passwd':
owner => 'root',
group => 'root',
mode => '0644',
}
file { '/etc/shadow':
owner => 'root',
group => 'root',
mode => '0440',
}
}
带参数的类:
同一个类在不同的OS上上可能会略有不同,因此需要通过获取相应系统的fact来实现有区别对待,然而万一相应的OS没有输出类所期望的fact或者是类依赖于非fact因素时,此机制将无法满足需求,此时就需要使用带参数的类来完成此类功能,在定义参数的类时,需要将参数声明在类名后的小括号内(参数可以有默认值,如果使用多个参数,彼此间要使用逗号分隔),在类的内部使用参数的方式同使用本地变量;
语法格式:
class class_name (para1='val1',para2='val2'...) {
puppet_code
}
例如:
class
apache (String $version = 'latest') {
package {'httpd':
ensure => $version, # Using the class parameter from above
before => File['/etc/httpd.conf'],
}
file {'/etc/httpd.conf':
ensure => file,
owner => 'httpd',
content => template('apache/httpd.conf.erb'), # Template from a module
}
service {'httpd':
ensure => running,
enable => true,
subscribe => File['/etc/httpd.conf'],
}
}
3.声明(调用)类的方式
3.1使用标准方式
include
接受:
一个类的名称(如apache)或类的引用(如Class['apache']);
一个以逗号分隔的类名称或类引用的列表;
一个类名称或类引用的数组;
如:
include base::linux
include Class['base::linux'] # 声明一个类引用
include base::linux, apache # 声明一个类名的列表
$my_classes = ['base::linux', 'apache']
include $my_classes # 声明一个类名的数组
3.2使用
require(不是元属性的那个require)
通常需要在指定的代码段的位置使用require指明调用那个class就可以了,不常用;
如:
define apache::vhost (Integer $port, String $docroot, String $servername, String $vhost_name) {
require apache
...
}
In the above example, Puppet will ensure that every resource in the apache class gets applied before every resource in any apache::vhost instance;
接受:
一个类的名称(如apache)或类的引用(如Class['apache']);
一个以逗号分隔的类名称或类引用的列表;
一个类名称或类引用的数组;
3.3使用
contain
例如:
class ntp {
file { '/etc/ntp.conf':
...
require => Package['ntp'],
notify => Class['ntp::service'],
}
contain ntp::service
package { 'ntp':
...
}
}
In the above example, any resource that forms a before or require relationship with class ntp will also be applied before or after class ntp::service, respectively.
接受:
一个类的名称(如apache)或类的引用(如Class['apache']);
一个以逗号分隔的类名称或类引用的列表;
一个类名称或类引用的数组;
补充关于containing-classes的说明:
3.4使用
hiera_include
例如:
# /etc/puppetlabs/puppet/hiera.yaml
...
hierarchy:
- "%{::clientcert}"
- common
# /etc/puppetlabs/code/hieradata/web01.example.com.yaml
---
classes:
- apache
- memcached
- wordpress
# /etc/puppetlabs/code/hieradata/common.yaml
---
classes:
- base::linux
# /etc/puppetlabs/code/environments/production/manifests/site.pp
hiera_include(classes)
On the node web01.example.com in the production environment, the example above would declare the classes apache, memcached, wordpress, and base::linux. On other nodes, it would only declare base::linux.
hiera_include仅接受:
a single lookup key
3.5使用
resource-like declarations
即可以在声明一个类的时候像申报一个资源一样来调用一个类;
例如:
# Specifying the "version" parameter:
class {'apache':
version => '2.2.21',
}
# Declaring a class with no parameters:
class {'base::linux':}
3.6使用ENC的机制来声明
二.类的继承与覆盖
puppet运维管理中,为了方便使用代码,我们通常都是写成类,而为更加好的重用代码,比如,在另外一个地方引出,你不可能又复制代码过去,这样对以后的修改或者说维护都很不方便,这时候,人们就把相同的代码给抽出来了,在别的地方需要用的时候(子类),直接引用(父类),继承父类的特性,后来为了更方便与扩展,可以允许(子类)有其它特性,也可以覆盖父类的特性,包括:
继承资源属性
覆盖资源属性:(=>)
追加资源属性:(+>)
一般格式:
class class_name inherits parent_class_name {
puppet_code
}
一般的,子类的命名方式为"父类名::子类名"
例如:
class nginx {
package {'nginx':
ensure => present,
}
file {'/etc/nginx/nginx.conf':
ensure => file,
source => '/tmp/nginx/nginx.conf',
require => Package['nginx'],
}
}
class
nginx_sub inherits nginx {
file {'/etc/nginx/nginx.conf':
ensure => present,
source => '/usr/local/nginx/nginx.conf',
#在子类继承时,可以使用和父类同名同类型的资源(两者的file),在子类中赋值了和父类属性相同但值却不同
#时,子类的这个值会覆盖父类的值,即source为/usr/local/nginx/nginx.conf而不是/tmp/nginx/nginx.conf
require +> Package['tomcat'],
#这里是追加属性;
}
service {'nginx':
ensure => true,
path => '/etc/rc.d/init.d/nginx',
}
}
include nginx_sub #调用子类
可参考文章:
三.模块
官方文档:
1.概述
到目前为止,所做的资源申报、定义类、声明类等所有的功能都只是在一个manifest文件中实现,但这并非是最有效的基于puppet管理IT基础架构的方式;
实践中,我们一般需要把manifest文件分解成易于理解的结构,例如将类文件、配置文件甚至包括后面将提到的模块文件等分类存放,并且通过某种机制在必要时将它们整合起来,这种机制就叫做"模块",它有助于以结构化,层次化的方式使用puppet,而puppet则基于"模块自动装载器"完成模块装载;
从另一个角度来说,模块实际上就是一个按约定的、预定义的结构,存放了很多个文件或子目录的目录结构,目录里的这些文件或子目录必须遵循其命名规范,puppet会按照此种规范在特定位置查找所需的模块文件,不过这些特定目录也可以通过puppet的配置参数modulepath定义;
一句话就是:
模块就是一个目录结构,目录名就是模块名;
2.使用模块
只要在某模块中定义了一个类,就可以在任何manifest文件中使用它,puppet会自动去查找并装载包含了这个类的定义的manifest文件。因此,可以在puppet上提供多个模块,并按需要在manifest文件任意使用它们。
例如:
site.pp为站点清单,使用node指明有多少个节点,每个节点是如何调用类的
这里用的是site.pp,可以看下面完整的示例来了解如何使用模块的;
# /etc/puppetlabs/code/environments/production/manifests/site.pp
node default {
include apache
class {'ntp':
enable => false;
}
apache::vhost {'personal_site':
port => 80,
docroot => '/var/www/personal',
options => 'Indexes MultiViews',
}
}
要确保模块可用,可以将其放到puppet的参数modulepath定义的路径下,而且要确保有正确的模块名;
而模块存放的位置为:
[root@bogon puppet]#
puppet agent --configprint modulepath
/etc/puppet/modules:/usr/share/puppet/modules
如果想使用额外的目录,在puppet apply时需使用
--modulepath指定模块位置;
3.模块目录结构布局
通常,模块只是一个特定的,可预见的目录结构:
manifests
init.pp
files
templates
lib
facts.d
examples
spec
其中:
MODULE_NAME:模块名称,也即模块目录名称;模块名称只能以小写字母开头,可以包含小写字母,数字和下划线;
manifests目录:清单存储目录,存放各种.pp清单文件,每个清单文件只包含一个类或一个定义的类,且建立的清单文件名与类名相同,如nginx::web对应web.pp清单文件,此中文件访问路径格式为:Module_Name::[SubDirectoryName::]ManifestFileName;
init.pp文件:包含一个一个单独的类定义,且类的名称必须与模块名相同,该文件必须存在;
files目录:文件存储目录,包含了一组静态文件,这些文件可被节点下载使用,每个文件的访问路径遵循puppet:///modules/MODULE_NAME/filename路径格式,如puppet:///modules/my_module/service.conf 会被映射到文件 my_module/files/service.conf;
templates目录:存储了清单文件用到的模板文件,其访问路径遵循template('ModuleName/TemplateName')格式;
lib目录:插件目录,常用于自定义fact及自定义资源类型等;
facts.d目录:包含额外的fact;
examples目录:当前模块的使用帮助或使用范例文件,类似如何声明当前模块中的类定义及定义的类型等;
spec目录:类似于examples目录的功能,只不过,其是为lib目录中定义的个插件提供使用范例和说明的;
完整示例如下:
使用时,就可以这样:
puppet apply -e 'include my_module' #应用init.pp清单
puppet apply -e 'include my_module::other_class' #应用子类
4.模块管理
puppet命令子命令module作用,具体使用方法可puppet module help:
module Creates, installs and searches for modules on the Puppet Forge.
4.1在线模块下载地址:
4.2显示本地已安装的模块:
[root@bogon ~]# puppet module list
/etc/puppet/modules (no modules installed)
/usr/share/puppet/modules (no modules installed)
4.3搜索模块
[root@bogon ~]# puppet module search module_name
Notice: Searching ...
NAME DESCRIPTION AUTHOR KEYWORDS
bobtfish-disable_caller_module_name Private classes are hateful for user... @bobtfish private
4.4安装模块
[root@bogon ~]# puppet module install module_name
5.具体示例
官方文档:
5.1列出可用的Nginx模块
[root@bogon nginx]# puppet module search nginx
Notice: Searching ...
NAME DESCRIPTION AUTHOR KEYWORDS
zooz-nginx Puppet module for nginx web server. @zooz nginx fedora
......
5.2下载Nginx模块(最好对应当前的puppet版本)
[root@bogon ~]# puppet module install zooz-nginx
Notice: Preparing to install into /etc/puppet/modules ...
Notice: Downloading from ...
Notice: Installing -- do not interrupt ...
/etc/puppet/modules
└── zooz-nginx (v0.0.3)
5.3查看安装的Nginx模块目录树
[root@bogon modules]# tree ./
./
└── nginx
├── files
├── lib
│ ├── facter
│ └── puppet
│ ├── parser
│ │ └── functions
│ ├── provider
│ └── type
├── manifests
│ ├── init.pp
│ ├── snippet_conf.pp
│ ├── snippet.pp
│ ├── upstream_conf.pp
│ ├── upstream.pp
│ ├── vhost_conf.pp
│ └── vhost.pp
├── metadata.json
├── Modulefile
├── README.md
├── templates
│ ├── nginx.conf.erb
│ ├── upstream_conf.erb
│ └── vhost_conf.erb
└── tests
5.4测试
[root@bogon modules]# rpm -q nginx
package nginx is not installed
[root@bogon modules]# service nginx status
nginx: 未被识别的服务
[root@bogon ~]# puppet apply -e 'include nginx'
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Notice: Compiled catalog for bogon in environment production in 2.78 seconds
Notice: /Stage[main]/Nginx/Package[nginx]/ensure: created
Notice: /Stage[main]/Nginx/File[/etc/nginx/nginx.conf]/content: content changed '{md5}d9dfc198c249bb4ac341198a752b9458' to '{md5}219bec7aa8c070fd26bd62945a629e27'
Notice: /Stage[main]/Nginx/File[/etc/nginx/vhost.d]/ensure: created
Notice: /Stage[main]/Nginx/File[/etc/nginx/snippet.d]/ensure: created
Notice: /Stage[main]/Nginx/File[/var/cache/nginx]/ensure: created
Notice: /Stage[main]/Nginx/File[/etc/nginx/conf.d/default.conf]/ensure: removed
Notice: /Stage[main]/Nginx/Service[nginx]/ensure: ensure changed 'stopped' to 'running'
Notice: Finished catalog run in 16.45 seconds
验证:
[root@bogon ~]# service nginx status
nginx (pid 5936) 正在运行...
接着调用nginx的upstream子类:
[root@bogon ~]# puppet apply -e 'include nginx::upstream'
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Error: create_resources(): second argument must be a hash at /etc/puppet/modules/nginx/manifests/upstream.pp:20 on node bogon
Error: create_resources(): second argument must be a hash at /etc/puppet/modules/nginx/manifests/upstream.pp:20 on node bogon
要求upstream.pp文件的第20行的第二个参数必须是hash,额,暂时还不知道如何修改,不过只要修改好就能用了;
贴出来upstream和upstream_conf清单文件内容:
[root@bogon manifests]# cat upstream.pp
class nginx::upstream inherits nginx {
if $::nginx::upstream != 'undef' { #20行
create_resources(nginx::upstream_conf, hiera_hash('nginx::upstream', undef))
}
}
[root@bogon manifests]# cat upstream_conf.pp
define nginx::upstream_conf(
$server = undef,
$ip_hash = false,
$keepalive = undef,
$least_conn = false,
$check = undef,
$check_http_send = undef,
$check_http_expect_alive = undef,) {
$conf_template = 'upstream_conf.erb'
if $server == undef {
fail('At least one backend server must be specified.')
}
file { "${nginx::vhost_dir}/${title}_upstream.conf":
ensure => 'file',
mode => '0644',
owner => 'root',
group => $nginx::user,
content => template("${module_name}/${conf_template}"),
notify => Service[$nginx::service_name],
}
}
参考文章:
Linux自动化运维之puppet的类和模块 | Linux–不是那么难