Jusene's Blog

Puppet 配置语言学习(一)

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

Puppet

puppet是一种linux,unix,windows平台的集中配置管理系统,尽管puppet采用ruby开发,但是puppet的配置语言却自成一套编程语言体系(puppet描述语言),puppet可以自行维护一个相对稳定的IT系统,采用c/s星状的结构,也就是master/agent框架,每个puppet-agent会周期(默认半个小时)向服务器发送请求,获取最新的配置信息,保障每个puppet-agent系统都可以根据puppet-master的配置维护系统稳定和配置的一致性,配置完成后puppet-agent可以反馈给服务端一个消息。

puppet的配置语言是基于声明性的编程语言进行配置,在puppet的工作模式中分为:

  • 定义:使用pupet配置语言定义资源的状态
  • 模拟:根据资源关系图,puppet可以模拟部署(无损运行测试代码)
  • 强制:比对客户端主机状态和定义的资源状态是否一致,自动强制执行
  • 报告:通过puppet api,可以将日志送到第三方监控工具,如:dashboard,forman

puppet将底层的资源进行抽象化,这些资源通过puppet的配置语言来进行事务处理这些抽象化的资源层,所以如果按照按照单一配置语言处理的过程来进行分层的话,我们还可以分为三层:

  • 配置语言
  • 事务层
  • 资源抽象层:
    • 资源类型:相似的资源被抽象为同一资源的类型,如程序包资源、用户资源及服务资源等,具体来说就是用户、组、文件、程序、服务等。
    • 属性及状态与实现方式分离:仅说明安装一个程序包而不关心具体通过什么方式来实现。
    • 期望状态:期望达到的结果,不必说明具体过程

puppet的核心就是资源,其具体的实现过程puppet都通过抽象层来完成,所以在配置puppet的过程中,我们的核心就是编写资源清单:manifest,及通过资源清单中资源定义的所依赖的文件、模版等数据按特定结构组织起即为的‘模块’。

puppet属于c/s架构,所以在agent与master的架构中我们需要安装不同的数据包:
agent:puppet,facter
master:puppet-server
需要获取的puppet包,我们可以通过这个url获取,http://yum.puppetlabs.com/

结下来我们可以展示下puppet的工作模型,一下是在agent下的工作模型:

而这个就是master-agent的工作模型:

Puppet的配置语言

我们为了探究puppet的配置语言,所以我们可以在agent的模式下测试自己的配置语言:

puppet的语法格式:
Usage: puppet <subcommand> [options] <action> [options]

获取所支持的所有的资源类型:

1
~]# puppet describe -l              #列出所有的资源类型
2
~]# puppet describe RESOURCE_TYPE   #获取单个资源类型的属性

每个资源都应该有type、title、attributes,如:

1
type {'title':
2
	attribute1 => value1,
3
	attribute2 => value2,
4
}

注意:title必须在同一type中唯一,并且必须小写。

在资源的属性(attributes)中,除了资源本身的属性中,我们还可以为它定义以下属性:

  • namevar: 大多数type都有在目标系统上标识资源的一个属性,这个常常被称为namevar,namevar的值在配的资源type中必须是唯一的,除了少数例外(exec)。
  • ensure: 用于大多数资源中,用于控制资源的存在性
  • metaparameters: 用于资源引用,资源的依赖关系,通知关系等。

常用的资源类型:
user,group,file,package,service,exec,cron,notify

group

  • name: namevar 组名
  • gid: GID
  • system: true|false
  • ensure: present|absent
  • members: 组内成员

example:

1
~]# cat group.pp
2
group { "jusene":
3
		name => "jusene",
4
		gid => 3000,
5
		ensure => present,
6
}
7
~]# puppet apply -v group.pp
8
Notice: Compiled catalog for init.localdomain in environment production in 0.11 seconds
9
Info: Applying configuration version '1505049462'
10
Notice: /Stage[main]/Main/Group[jusene]/ensure: created
11
Notice: Finished catalog run in 0.03 seconds
12
~]# grep jusene /etc/group
13
jusene:x:3000:

user

  • comment: 注释信息
  • ensure: true|false
  • expiry: 过期期限
  • gid: 基本组
  • groups: 附加组
  • home: 家目录
  • shell: 默认shell
  • name: namevar 用户名
  • system: true|false
  • uid: UID
  • password: 这里需要的是加密后的密码

生成密码的方式
md5加密

1
~]# openssl passwd -1 -salt 'pass'  
2
Password: 
3
$1$pass$fPYxo9a/Tb6JgVP.kg1kV.

sha512加密

1
~]# pip install -U passlib
2
~]# python
3
Python 2.7.5 (default, Nov 20 2015, 02:00:19) 
4
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
5
Type "help", "copyright", "credits" or "license" for more information.
6
>>> from passlib.hash import sha512_crypt
7
>>> import getpass
8
>>> print(sha512_crypt.encrypt(getpass.getpass()))
9
Password: 
10
$6$rounds=656000$oQwcJxo9Leu63FFN$oqS901AxOw6kdE1b/tHuI6J5fhuYG42Xo9P6UmdMrqfkMM3Yx4iN1c07tpbzZP54H0R7Ey3AbDuq95/pievGX0

example:

1
~]# cat user.pp
2
user {'jusene':
3
		name => 'jusene',
4
		uid => 3000,
5
		gid => 3000,
6
		home => '/home/jusene',
7
		shell => '/bin/bash',
8
		comment => 'puppet create user',
9
		ensure => present,
10
		password => '$6$rounds=656000$oQwcJxo9Leu63FFN$oqS901AxOw6kdE1b/tHuI6J5fhuYG42Xo9P6UmdMrqfkMM3Yx4iN1c07tpbzZP54H0R7Ey3AbDuq95/pievGX0',
11
}
12
~]# puppet apply -v user.pp
13
Notice: Compiled catalog for init.localdomain in environment production in 0.15 seconds
14
Info: Applying configuration version '1505050550'
15
Notice: /Stage[main]/Main/User[jusene]/ensure: created
16
Notice: Finished catalog run in 0.04 seconds
17
~]# grep jusene /etc/passwd
18
jusene:x:3000:3000:puppet create user:/home/jusene:/bin/bash
19
~]# grep jusene /etc/shadow
20
jusene:$6$rounds=656000$oQwcJxo9Leu63FFN$oqS901AxOw6kdE1b/tHuI6J5fhuYG42Xo9P6UmdMrqfkMM3Yx4iN1c07tpbzZP54H0R7Ey3AbDuq95/pievGX0:17419:0:99999:7:::

file

管理文件的内容、从属关系以及权限,内容可以通过content属性直接给出,也可以通过source属性根据远程服务器路径下载生成:

  • backup: .puppet.bak 覆盖前备份
  • content: 直接给出文件内容,支持\n,\t
  • source: 从指定位置下载文件,可以是本地文件路径(单机模式),也可以是puppet:///modules/module_name/file_name
  • ensure: file,directory,link,present,absent
  • force: 强制创建,可用值yes,no,true,false
  • group: 属组
  • owner: 属主
  • mode: 权限,支持八进制格式权限,以及u,g,o的赋值方式
  • path: namevar,绝对路径
  • target: 当ensure为link时,target表示path指向的文件是一个符号文件,其目标为此target属性指向的路径

example:

1
~]# cat file.pp
2
file {'test':
3
	path => '/tmp/fstab',
4
	backup => '.puppet.bak',
5
	source => '/etc/fstab',
6
	owner => 'jusene',
7
	group => 'jusene',
8
	mode => '0666',
9
	ensure => file,
10
}
11
~]# puppet apply -v file.pp
12
Notice: Compiled catalog for init.localdomain in environment production in 0.11 seconds
13
Info: Applying configuration version '1505051798'
14
Notice: /Stage[main]/Main/File[test]/ensure: defined content as '{md5}c33fef818e0af833709ef902db780705'
15
Notice: Finished catalog run in 0.04 seconds
16
~]# ll /tmp/fstab 
17
-rw-rw-rw-. 1 jusene jusene 541 Sep 10 09:56 /tmp/fstab
18
~]# echo '#' >> /etc/fstab
19
~]# puppet apply -v file.pp 
20
Notice: Compiled catalog for init.localdomain in environment production in 0.12 seconds
21
Info: Applying configuration version '1505051898'
22
Notice: /Stage[main]/Main/File[test]/content: content changed '{md5}c33fef818e0af833709ef902db780705' to '{md5}e26781ee354d18ad64e84427a765672c'
23
Notice: Finished catalog run in 0.04 seconds
24
~]# ll /tmp/fstab
25
fstab             fstab.puppet.bak

example2:

1
~]# cat file1.pp
2
file {'test':
3
	path => '/opt/fstab',
4
	target => '/etc/fstab',
5
	ensure => link,
6
}
7
~]# puppet apply -v file2.pp          
8
Notice: Compiled catalog for init.localdomain in environment production in 0.11 seconds
9
Info: Applying configuration version '1505052170'
10
Notice: /Stage[main]/Main/File[test]/ensure: created
11
Notice: Finished catalog run in 0.02 seconds
12
~]# ll /opt/fstab 
13
lrwxrwxrwx. 1 root root 10 Sep 10 10:02 /opt/fstab -> /etc/fstab

exec

运行一个外部命令:命令应该具备“幂等性”:
幂等性:
– 命令本身具备幂等性,运行多少遍都无影响
– 资源有onlyif,unless,create等属性以实现命令的条件运行
– 资源有refreshonly的属性,以实现只有订阅的资源发生时才执行

  • command:运行的命令 namevar
  • creates:此属性指定的文件不存在时才运行
  • cwd:此属性指定的路径下运行命令
  • user:以指定的用户身份运行命令
  • group:以指定的用户组身份运行命令
  • onlyif:给定测定命令,仅在此命令返回true
  • unless:给定测试命令,仅在此命令放回false
  • refresh:接受其他资源发来的refresh通知时,默认时重新执行exec定义的command,refresh属性可改变这种行为,即可指定仅在refresh时运行的命令
  • refreshonly:仅在收到refresh通知,才运行此资源
  • returns:期望返回的返回值
  • path:命令查找的路径
  • tries:尝试执行的次数
  • timeout:超时的时长

example:

1
~]# cat exec.pp
2
exec {"test":
3
        command => "touch /tmp/test.file",
4
        creates => '/tmp/test.file',
5
        path => ['/usr/bin','/usr/sbin'],
6
        user => 'jusene',
7
        group => 'jusene',
8
        tries => 2,
9
        timeout => 5
10
}
11
~]# puppet apply -v exec.pp 
12
Notice: Compiled catalog for init.localdomain in environment production in 0.05 seconds
13
Info: Applying configuration version '1505053485'
14
Notice: /Stage[main]/Main/Exec[test]/returns: executed successfully
15
Notice: Finished catalog run in 0.05 seconds
16
~]# ll /tmp/test.file    
17
-rw-r--r--. 1 jusene jusene 0 Sep 10 10:24 /tmp/test.file

example2:

1
~]# cat exec1.pp
2
exec {"test":
3
	command => "echo 'ok' > /tmp/test.file",
4
	onlyif => "test -e /tmp/test.file",
5
	path => ['/usr/bin','/usr/sbin']	
6
}
7
~]# puppet apply -v exec1.pp 
8
Notice: Compiled catalog for init.localdomain in environment production in 0.04 seconds
9
Info: Applying configuration version '1505054015'
10
Notice: /Stage[main]/Main/Exec[test]/returns: executed successfully
11
Notice: Finished catalog run in 0.06 seconds
12
~]# cat /tmp/test.file 
13
ok
14
~]# > /tmp/test.file
15
~]# cat exec2.pp
16
exec {"test":
17
	command => "echo 'ok' > /tmp/test.file",
18
	unless => "test -e /tmp/test.file",
19
	path => ['/usr/bin','/usr/sbin']	
20
}
21
~]# puppet apply -v exec2.pp 
22
Notice: Compiled catalog for init.localdomain in environment production in 0.05 seconds
23
Info: Applying configuration version '1505054121'
24
Notice: Finished catalog run in 0.05 seconds
25
~]# cat /tmp/test.file

example3:

1
~]# cat exec3.pp
2
file {'test':
3
	path => "/tmp/issue",
4
	source => "/etc/issue",
5
	ensure => file,
6
	notify => Exec['test']
7
}
8
9
exec {'test':
10
	command => "echo '1' > /tmp/test.file",
11
	refresh => "echo '2' > /tmp/test.file",
12
	path => ['/usr/bin','/usr/sbin']
13
}
14
~]# puppet apply -v exec3.pp
15
Notice: Compiled catalog for init.localdomain in environment production in 0.17 seconds
16
Info: Applying configuration version '1505054544'
17
Notice: /Stage[main]/Main/File[test]/ensure: defined content as '{md5}f078fe086dfc22f64b5dca2e1b95de2c'
18
Info: /Stage[main]/Main/File[test]: Scheduling refresh of Exec[test]
19
Notice: /Stage[main]/Main/Exec[test]/returns: executed successfully
20
Notice: /Stage[main]/Main/Exec[test]: Triggered 'refresh' from 1 events
21
Notice: Finished catalog run in 0.08 seconds
22
~]# cat /tmp/test.file 
23
2
24
~]# puppet apply -v exec3.pp
25
Notice: Compiled catalog for init.localdomain in environment production in 0.19 seconds
26
Info: Applying configuration version '1505054582'
27
Notice: /Stage[main]/Main/Exec[test]/returns: executed successfully
28
Notice: Finished catalog run in 0.07 seconds
29
~]# cat /tmp/test.file      
30
1
31
~]# cat exec4.pp
32
file {'test':
33
	path => "/tmp/issue",
34
	source => "/etc/issue",
35
	ensure => file,
36
	notify => Exec['test']
37
}
38
39
exec {'test':
40
	command => "echo '1' > /tmp/test.file",
41
	refreshonly => true,
42
	path => ['/usr/bin','/usr/sbin']
43
}
44
~]# puppet apply -v exec3.pp     
45
Notice: Compiled catalog for init.localdomain in environment production in 0.18 seconds
46
Info: Applying configuration version '1505054793'
47
Notice: /Stage[main]/Main/File[test]/ensure: defined content as '{md5}f078fe086dfc22f64b5dca2e1b95de2c'
48
Info: /Stage[main]/Main/File[test]: Scheduling refresh of Exec[test]
49
Notice: /Stage[main]/Main/Exec[test]: Triggered 'refresh' from 1 events
50
Notice: Finished catalog run in 0.08 seconds
51
~]# cat /tmp/test.file 
52
1
53
~]# puppet apply -v exec3.pp
54
Notice: Compiled catalog for init.localdomain in environment production in 0.16 seconds     #command的指令并没有没执行
55
Info: Applying configuration version '1505054820'
56
Notice: Finished catalog run in 0.05 seconds
57
~]# cat /tmp/test.file 
58
1

notify

打印信息

  • message:要发送的消息的内容,namevar

example:

1
~]# cat notify.pp
2
notify {'test':
3
		message => 'hello puppet'
4
5
}
6
~]# puppet apply -v notify.pp 
7
Notice: Compiled catalog for init.localdomain in environment production in 0.01 seconds
8
Info: Applying configuration version '1505055101'
9
Notice: hello puppet
10
Notice: /Stage[main]/Main/Notify[test]/message: defined 'message' as 'hello puppet'
11
Notice: Finished catalog run in 0.03 seconds

cron

管理cron任务

  • ensure:present,absent
  • command:要运行的job
  • hour:
  • minute:
  • month:
  • monthday:
  • weekday:
  • name:namevar
  • user:运行的用户
  • environment:运行时的环境变量

example:

1
~]# cat cron.pp
2
cron {'test':
3
	name => "sync time",
4
	command => "ntpdate 10.0.0.1 &> /dev/null",
5
	ensure => present 
6
}
7
~]# puppet apply -v cron.pp 
8
Notice: Compiled catalog for init.localdomain in environment production in 0.07 seconds
9
Info: Applying configuration version '1505055436'
10
Notice: /Stage[main]/Main/Cron[test]/ensure: created
11
Notice: Finished catalog run in 0.04 seconds
12
~]# crontab -l
13
# HEADER: This file was autogenerated at 2017-09-10 10:57:16 -0400 by puppet.
14
# HEADER: While it can still be managed manually, it is definitely not recommended.
15
# HEADER: Note particularly that the comments starting with 'Puppet Name' should
16
# HEADER: not be deleted, as doing so could cause duplicate cron jobs.
17
# Puppet Name: sync time
18
* * * * * ntpdate 10.0.0.1 &> /dev/null

package

管理安装包

  • ensure: installed,latest,VERSION(2.3-1.l7),present,absent
  • name: 程序包名称
  • source:包来源,可以本地文件或者url
1
~]# cat package.pp
2
package {'test':
3
		name => 'nginx',
4
		ensure => present
5
}
6
~]# puppet apply -v package.pp 
7
Notice: Compiled catalog for init.localdomain in environment production in 0.44 seconds
8
Info: Applying configuration version '1505055747'
9
Notice: /Stage[main]/Main/Package[test]/ensure: created
10
Notice: Finished catalog run in 36.14 seconds
11
~]# rpm -qa nginx
12
nginx-1.10.2-1.el7.x86_64

service

管理服务

  • enable:是否开机自动启动,true|false
  • ensure:启动(running),停止(stopped)
  • hasrestart: 是否支持restart参数
  • hasstatus: 是否支持status参数
  • name: 服务名称,NameVar
  • path: 服务查找路径
  • pattern:用于搜索此服务相关的进程的模式;当脚本不支持restart/status时,用于确定服务是否支持处于运行状态
  • restart:自定义脚本
  • status:自定义脚本
  • stop:自定义脚本

example:

1
~]# service.pp
2
service {'test':
3
		name => "nginx",
4
		ensure => running,
5
		hasstatus => true,
6
		hasrestart => true,
7
		restart => "systemctl reload nginx",
8
		path => ['/usr/bin','/usr/sbin']
9
}
10
~]# puppet apply -v service.pp 
11
Notice: Compiled catalog for init.localdomain in environment production in 0.19 seconds
12
Info: Applying configuration version '1505056135'
13
Notice: /Stage[main]/Main/Service[test]/ensure: ensure changed 'stopped' to 'running'
14
Info: /Stage[main]/Main/Service[test]: Unscheduling refresh on Service[test]
15
Notice: Finished catalog run in 0.12 seconds
16
~]# ps aux | grep nginx
17
root     31446  0.0  0.1 122240  2228 ?        Ss   11:08   0:00 nginx: master process /usr/sbin/nginx
18
nginx    31447  0.0  0.1 122672  3296 ?        S    11:08   0:00 nginx: worker process
19
nginx    31448  0.0  0.1 122672  3088 ?        S    11:08   0:00 nginx: worker process
20
root     31460  0.0  0.0 112644   952 pts/0    S+   11:09   0:00 grep --color=auto nginx
CATALOG
  1. 1. Puppet
  2. 2. Puppet的配置语言
    1. 2.1. group
    2. 2.2. user
    3. 2.3. file
    4. 2.4. exec
    5. 2.5. notify
    6. 2.6. cron
    7. 2.7. package
    8. 2.8. service