Jusene's Blog

Puppet 配置语言学习(二)

字数统计: 3.2k阅读时长: 16 min
2017/09/11 Share

Puppet

puppt的配置语言将资源抽象化,所以我们不必担心底层如何实现,而资源与资源必然是会存在依赖先后关系的,并且puppet更加有oop(面向对象的编程)的设计,存在类,模版,模块,变量等多种概念。

Metaparameters

这个属性属于资源的特殊属性,可以通过这个属性的定义资源间的依赖的关系,或者资源间的通知关系。

before && require && -> 依赖关系

example:

1
~]# cat test.pp
2
package {'nginx':
3
		name => 'nginx',
4
		ensure => latest,
5
} ->
6
file {'config':
7
		source => "/root/manifest/conf/nginx.conf",
8
		path => "/etc/nginx/nginx.conf",
9
		backup => ".puppet.bak",
10
		ensure => file,
11
		before => Service['nginx']
12
}
13
service {'nginx':
14
		name => 'nginx',
15
		ensure => running,
16
		hasstatus => true,
17
		hasrestart => true,
18
		restart => "systemctl reload nginx",
19
		path => ["/usr/sbin","/usr/bin"],
20
		require => [Package['nginx'],File['config']]
21
}
22
~]# puppet apply -v test.pp
23
Notice: Compiled catalog for init.localdomain in environment production in 0.61 seconds
24
Info: Applying configuration version '1505126957'
25
Notice: /Stage[main]/Main/Package[nginx]/ensure: created
26
Notice: /Stage[main]/Main/File[config]/content: content changed '{md5}93bc8e01bfd45e7e18b23acc178ae25b' to '{md5}f73950c032695ad66a259bca4039afba'
27
Notice: /Stage[main]/Main/Service[nginx]/ensure: ensure changed 'stopped' to 'running'
28
Info: /Stage[main]/Main/Service[nginx]: Unscheduling refresh on Service[nginx]
29
Notice: Finished catalog run in 140.62 seconds

注意:资源引用必须type的首字母大写,Type['title']。

以上例子共用了三种资源依赖关系的表示方法:

  • 被依赖的资源中使用:before
  • 依赖其他资源中使用:require
  • 脸是依赖:->

notify && subscribe && ~> 通知关系

example:

1
~]# cat test1.pp
2
package {'nginx':
3
	name => 'nginx',
4
	ensure => latest
5
} ~>
6
exec {'log':
7
	command => "echo 'package nginx install ok' > /tmp/test.log",
8
	path => ['/usr/bin','/usr/sbin'],
9
	refreshonly => true
10
}
11
file {'config':
12
		source => "/root/manifest/conf/nginx.conf",
13
		path => "/etc/nginx/nginx.conf",
14
		backup => ".puppet.bak",
15
		ensure => file,
16
		notify => Service['nginx']
17
} ~>
18
exec {'log1':
19
	command => "echo 'nginx conf replace ok' >> /tmp/test.log",
20
	refreshonly => true,
21
	path => ['/usr/bin','/usr/sbin']
22
}
23
service {'nginx':
24
		name => 'nginx',
25
		ensure => running,
26
		hasstatus => true,
27
		hasrestart => true,
28
		restart => "systemctl reload nginx",
29
		path => ["/usr/sbin","/usr/bin"],
30
		require => [Package['nginx'],File['config']],
31
		subscribe => File['config']
32
}
33
~]# puppet apply -v test1.pp
34
Notice: Compiled catalog for init.localdomain in environment production in 0.66 seconds
35
Info: Applying configuration version '1505128794'
36
Notice: /Stage[main]/Main/Package[nginx]/ensure: created
37
Info: /Stage[main]/Main/Package[nginx]: Scheduling refresh of Exec[log]
38
Notice: /Stage[main]/Main/Exec[log]: Triggered 'refresh' from 1 events
39
Info: /Stage[main]/Main/File[config]: Removing old backup of type file
40
Notice: /Stage[main]/Main/File[config]/content: content changed '{md5}93bc8e01bfd45e7e18b23acc178ae25b' to '{md5}f73950c032695ad66a259bca4039afba'
41
Info: /Stage[main]/Main/File[config]: Scheduling refresh of Service[nginx]
42
Info: /Stage[main]/Main/File[config]: Scheduling refresh of Service[nginx]
43
Info: /Stage[main]/Main/File[config]: Scheduling refresh of Exec[log1]
44
Notice: /Stage[main]/Main/Exec[log1]: Triggered 'refresh' from 1 events
45
Notice: /Stage[main]/Main/Service[nginx]/ensure: ensure changed 'stopped' to 'running'
46
Info: /Stage[main]/Main/Service[nginx]: Unscheduling refresh on Service[nginx]
47
Notice: Finished catalog run in 17.30 seconds
48
~]# cat /tmp/test.log 
49
package nginx install ok 
50
nginx conf replace ok

通知信息,就是向你想要的通知的资源发送refresh信号,常用的就是在更改配置信息后重新启动服务等之类的通知。

以上例子共用了三种资源通知资源的表示方法:

  • 被依赖的资源主动使用:notify
  • 监听其他资源的资源:subscribe
  • 链式通知: ~>

变量,数据类型,正则表达式

变量

变量是以$开头,赋值符号=;任何非正则表达式类型的数据均可赋值的变量。

作用域:定义代码的生效范围,以实现代码间隔离

  • 仅能隔离:变量,资源的默认属性
  • 不能隔离:资源的名称及引用

每个变量两种引用路径:

  • 相对路径
  • 绝对路径:$::scope::scopr::variable

变量的赋值符号:

  • =
  • +=:追加赋值

puppet中的变量种类:

  • 自定义变量
  • facter变量,可以通过facter -p 查看
  • 内置变量

数据类型

  • 布尔型:true|false
  • undef:未申明
  • 字符型:可以不用引号,支持单引号(强引号),双引号(弱引用)
  • 数值型:整数和浮点型
  • 数组: [item1,item2,item3,…]元素可为任意可用的数据类型,包括数组和hash;索引从0开始,还可以使用负数
  • hash:{key => value,key => value,…},键为字符串,而值可以是任意数据类型

正则表达式

非标准的数据类型,不能赋值给变量。
语法结构:

  • (?<ENABLED OPTION>:<SUBPATTERN>)
  • (?-<DISABLED OPTION>:<SUBPATTERN>)

OPTION:

  • i:忽略大小写
  • m:把.当换行符
  • x:忽略模式中的空白的注释

条件判断

if语句

语法格式:

1
if CONDITION {
2
	...
3
} elseif {
4
	...
5
} else {
6
	...
7
}

COMDITION的用法:

  1. 比较表达式
  2. 变量引用
  3. 有返回值的函数调用

example:

1
~]# cat if.pp
2
if $operatingsystem =~ /^(?i-mx:(centos|redhat))/ {
3
	notice ("welcome to $1 linux server!")
4
}
5
~]# puppet  apply -v if.pp 
6
Notice: Scope(Class[main]): welcome to CentOS linux server!
7
Notice: Compiled catalog for init.localdomain in environment production in 0.01 seconds
8
Info: Applying configuration version '1505130702'
9
Notice: Finished catalog run in 0.01 seconds

case语句

语法格式:

1
case CONTROL_EXPRESS {
2
	case1,case2,...:{statement...}
3
	case3,case4,...:{statement...}
4
	....
5
	default:{statemnet...}
6
}

case:字符串,变量,有返回值函数,模式,default

example:

1
~]# cat case.pp
2
case $operatingsystem {
3
	/^(?i-mx:(centos|redhat))/:{notice("welcome to $1 linux server")}
4
	ubuntu:{notice("welcome to ubuntu server")}
5
	default:{notice("welcome to jusene server")}
6
}
7
~]# puppet  apply -v case.pp 
8
Notice: Scope(Class[main]): welcome to CentOS linux server
9
Notice: Compiled catalog for init.localdomain in environment production in 0.01 seconds
10
Info: Applying configuration version '1505131147'
11
Notice: Finished catalog run in 0.01 seconds

case语句中,statement是可执行的代码块。

selector语句

只能用于期望出现直接值(plain value)的地方,这包括变量赋值、资源属性、函数参数、资源标题、其他selector的值及其表达式,直接返回一个值,而不执行代码块。

语法格式:

1
CONTROL_VARIABLE ? {
2
	case1 => value1,
3
	case2 => value2,
4
		...
5
	default => valueN
6
}

example:

1
~]# cat selector.pp
2
$webserver = $operatingsystem ? {
3
	/^(?i-mx:centos|redhat|fedore)/ => 'httpd',
4
	/^(?i-mx:debian|ubuntu)/ => 'apache2',
5
	default => 'webserver'
6
}
7
if $webserver {
8
	notice("webserver is $webserver!")
9
}
10
~]# puppet  apply -v selector.pp 
11
Notice: Scope(Class[main]): webserver is httpd!
12
Notice: Compiled catalog for init.localdomain in environment production in 0.01 seconds
13
Info: Applying configuration version '1505131896'
14
Notice: Finished catalog run in 0.02 seconds

类

类(class)用于公共目的的一组资源,是命名代码块:创建后可在puppet全局调用,类可被继承。

语法格式:

1
class class_name {
2
	...puppet code...
3
}

注意:类名只能包含小写字母、数字和下划线,且必须以小写字母开头

example:

1
~]# cat class.pp
2
class nginx {
3
	package {'nginx':
4
		name => 'nginx',
5
		ensure => latest,
6
} ->
7
file {'config':
8
		source => "/root/manifest/conf/nginx.conf",
9
		path => "/etc/nginx/nginx.conf",
10
		backup => ".puppet.bak",
11
		ensure => file,
12
		before => Service['nginx']
13
}
14
service {'nginx':
15
		name => 'nginx',
16
		ensure => running,
17
		hasstatus => true,
18
		hasrestart => true,
19
		restart => "systemctl reload nginx",
20
		path => ["/usr/sbin","/usr/bin"],
21
		require => [Package['nginx'],File['config']]
22
}
23
}
24
25
include nginx    声明类,相当于类的实例化
26
~]# puppet apply -v class.pp
27
Notice: Compiled catalog for init.localdomain in environment production in 0.76 seconds
28
Info: Applying configuration version '1505132362'
29
Notice: /Stage[main]/Nginx/Package[nginx]/ensure: created
30
Info: /Stage[main]/Nginx/File[config]: Removing old backup of type file
31
Notice: /Stage[main]/Nginx/File[config]/content: content changed '{md5}93bc8e01bfd45e7e18b23acc178ae25b' to '{md5}f73950c032695ad66a259bca4039afba'
32
Notice: /Stage[main]/Nginx/Service[nginx]/ensure: ensure changed 'stopped' to 'running'
33
Info: /Stage[main]/Nginx/Service[nginx]: Unscheduling refresh on Service[nginx]
34
Notice: Finished catalog run in 17.51 seconds
  • 定义能接受参数的类:

example:

1
~]# cat class1.pp
2
class webserver($server='nginx') {
3
	package {'webserver':
4
				name => $server,
5
				ensure => latest,
6
	} ->
7
	service {'webserver':
8
				name => $server,
9
				ensure => running,
10
				hasstatus => true,
11
				hasrestart => true,
12
				restart => "systemctl reload $server",
13
				path => ["/usr/sbin","/usr/bin"],
14
	}
15
}
16
17
class {'webserver':
18
		server => httpd,
19
}
20
~]# puppet apply -v class1.pp
21
Notice: Compiled catalog for init.localdomain in environment production in 0.61 seconds
22
Info: Applying configuration version '1505132897'
23
Notice: /Stage[main]/Webserver/Package[webserver]/ensure: created
24
Notice: /Stage[main]/Webserver/Service[webserver]/ensure: ensure changed 'stopped' to 'running'
25
Info: /Stage[main]/Webserver/Service[webserver]: Unscheduling refresh on Service[webserver]
26
Notice: Finished catalog run in 4.11 seconds
27
~}# ps aux | grep httpd
28
root      8279  0.1  0.2 226212  5140 ?        Ss   08:28   0:00 /usr/sbin/httpd -DFOREGROUND
29
apache    8280  0.0  0.1 226212  3004 ?        S    08:28   0:00 /usr/sbin/httpd -DFOREGROUND
30
apache    8281  0.0  0.1 226212  3004 ?        S    08:28   0:00 /usr/sbin/httpd -DFOREGROUND
31
apache    8282  0.0  0.1 226212  3004 ?        S    08:28   0:00 /usr/sbin/httpd -DFOREGROUND
32
apache    8283  0.0  0.1 226212  3004 ?        S    08:28   0:00 /usr/sbin/httpd -DFOREGROUND
33
apache    8284  0.0  0.1 226212  3004 ?        S    08:28   0:00 /usr/sbin/httpd -DFOREGROUND
34
root      8286  0.0  0.0 112644   952 pts/0    S+   08:28   0:00 grep --color=auto httpd
  • 类继承

定义方式:

1
class base_class {
2
	...puppet_class...
3
}
4
5
class base_class::class_name inherits base_class {
6
	...puppet code...
7
}

example:

1
~]# cat base.pp
2
class webserver($server='nginx') {
3
		package {'webserver':
4
			name => $server,
5
			ensure => latest
6
		}
7
}
8
9
class webserver::httpd inherits webserver {
10
		Package['webserver'] {
11
			name => httpd,
12
		} 
13
		file {"config":
14
			source => "/root/manifest/conf/httpd.conf",
15
			path => "/etc/httpd/conf/httpd.conf",
16
			backup => ".puppet.bak",
17
			ensure => file,
18
			before => Service['httpd']
19
		}
20
		service {"httpd":
21
				name => httpd,
22
				ensure => running,
23
				hasstatus => true,
24
				hasrestart => true,
25
				restart => "systemctl reload httpd",
26
				path => ["/usr/sbin","/usr/bin"],
27
		}
28
}
29
30
include webserver::httpd
31
~]# puppet  apply -v class.pp 
32
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
33
Notice: Compiled catalog for init.localdomain in environment production in 0.74 seconds
34
Info: Applying configuration version '1505133760'
35
Notice: /Stage[main]/Webserver/Package[webserver]/ensure: created
36
Notice: /Stage[main]/Webserver::Httpd/File[config]/content: content changed '{md5}f5e7449c0f17bc856e86011cb5d152ba' to '{md5}f8a8d510316c2d584a407f0aa2139a2d'
37
Notice: /Stage[main]/Webserver::Httpd/Service[httpd]/ensure: ensure changed 'stopped' to 'running'
38
Info: /Stage[main]/Webserver::Httpd/Service[httpd]: Unscheduling refresh on Service[httpd]
39
Notice: Finished catalog run in 3.31 seconds
40
41
~]# ps aux | grep httpd
42
root      8765  0.0  0.2 226212  5140 ?        Ss   08:42   0:00 /usr/sbin/httpd -DFOREGROUND
43
apache    8766  0.0  0.1 226212  3004 ?        S    08:42   0:00 /usr/sbin/httpd -DFOREGROUND
44
apache    8767  0.0  0.1 226212  3004 ?        S    08:42   0:00 /usr/sbin/httpd -DFOREGROUND
45
apache    8768  0.0  0.1 226212  3004 ?        S    08:42   0:00 /usr/sbin/httpd -DFOREGROUND
46
apache    8769  0.0  0.1 226212  3004 ?        S    08:42   0:00 /usr/sbin/httpd -DFOREGROUND
47
apache    8770  0.0  0.1 226212  3004 ?        S    08:42   0:00 /usr/sbin/httpd -DFOREGROUND
48
root      8777  0.0  0.0 112644   952 pts/0    S+   08:43   0:00 grep --color=auto httpd

类的继承时:

  • 声明子类时,其基类会被自动首先声明
  • 基类成为子类的父类,基类的变量的属性默认值会被子类复制一份
  • 子类可以覆盖父类中同一资源的相同属性的值
  • 继承一个已有的类,并实现覆盖资源的属性,或向资源属性追加额外值:=>,+>

模版

基于ERB模版语言,在静态文件中使用变量等编程元素生成适合与多种不同的环境的文本文件(配置文件):Embedded Ruby,用于实现在文本文件中嵌入ruby代码,原来的文本信息不会被改变,但ruby代码会被执行,执行的结果将直接替换原来的代码。

  • <%= Ruby Expression %>: 替换为表达式的值
  • <% Ruby code %>: 仅执行代码,而不替换
  • <%# comment %>: 注释
  • <%% or %%>等同于<% or %>:分别进行
  • <%- 等同于<%: 闭合标签,控制代码前输出大量空格
  • -%> 等同于%>: 闭合标签,控制代码后大量输出空格
  • <%= @Ruby var %> 也可以写成<%= Ruby var %>

变量引用:当前范围内的变量都可以作为ruby的变量,用@符号引用

1
~]# cat conf/test.erb
2
cpuconut = <%= @processorcount %>
3
~]# cat temp.pp
4
file {'test':
5
        content => template('/root/manifest/conf/test.erb'),
6
        path => '/tmp/test.conf',
7
        owner => 'jusene',
8
        group => 'jusene'
9
}
10
~]# puppet apply -v temp.pp               
11
Notice: Compiled catalog for init.localdomain in environment production in 0.14 seconds
12
Info: Applying configuration version '1505136413'
13
Notice: /Stage[main]/Main/File[test]/ensure: defined content as '{md5}0f30fa861c205656ebb195564c77c3e6'
14
Notice: Finished catalog run in 0.04 seconds
15
~]# cat /tmp/test.conf 
16
cpucount = 2
  • 测试变量:

    1
    ~]# cat conf/test.erb
    2
    <% if @webserver %>
    3
    webserver = <%= @webserver %>
    4
    <% else %>
    5
    webserver = httpd
    6
    <% end %>
    7
    ~]# cat temp.conf
    8
    $webserver='nginx'
    9
    file {'test':
    10
            content => template('/root/manifest/conf/test.erb'),
    11
            path => '/tmp/test.conf',
    12
            owner => 'jusene',
    13
            group => 'jusene'
    14
    }
    15
    ~]# cat /tmp/test.conf 
    16
    webserver = nginx
  • 获取当前作用域的所有变量名

    1
    ~]# cat conf/test.erb
    2
    <%scope.to_hash.keys.each do | k | -%>
    3
    <%= k %>
    4
    <% end -%>
  • 模版结合

    1
    多个模版,可以使用逗号结合。
    2
    content => template(’mumodule/template1.erb‘, ’mumodule/template2.erb‘)
  • 数组迭代

    1
    $values = [var1,var2,var3]
    2
    <% values.each do | val |-%>
    3
    value = <%= val %>
    4
    <% end %>

模版语法检查:

1
~]# erb -P -x -T '-' mytemplate.erb | ruby -c

模块

1
/etc/puppet/modules/
2
		modules_name/
3
			manifests/
4
					init.pp: 至少应该包含一个与当前模块名称同命令
5
			files: 静态文件:puppet://modules/module_name/file_name
6
			templates: 模版文件目录:template("module_name/template_file_name"):
7
			lib: 插件目录
8
			tests: 当前模块的使用帮助文件及示例文件
9
			spec: 类事与tests目录,存储lib目录下定义的插件的使用帮助及示例文件

模块管理命令:
puppet module <action> [--environment production ] [--modulepath $basemodulepath ]

  • build Build a module release package.
  • changes Show modified files of an installed module.
  • generate Generate boilerplate for a new module.
  • install Install a module from the Puppet Forge or a release archive.
  • list List installed modules
  • search Search the Puppet Forge for a module.
  • uninstall Uninstall a puppet module.
  • upgrade Upgrade a puppet module.

mkdir -pv /etc/puppet/modules/nginx/{manifests,files,templates,tests,lib,spec}

模块是按照一定的目录结构组合,可以理解这个与ansible的roles的相似。

CATALOG
  1. 1. Puppet
  2. 2. Metaparameters
    1. 2.1. before && require && -> 依赖关系
    2. 2.2. notify && subscribe && ~> 通知关系
  3. 3. 变量,数据类型,正则表达式
    1. 3.1. 变量
    2. 3.2. 数据类型
    3. 3.3. 正则表达式
  4. 4. 条件判断
    1. 4.1. if语句
    2. 4.2. case语句
    3. 4.3. selector语句
  5. 5. 类
  6. 6. 模版
  7. 7. 模块