puppet是一种开源的、新一代的集中化的配置管理工具。可管理的平台有windows,Linux,Unix等。有自己的配置语言(资源申报语言),可管理文件、软件包、系统服务、用户等。这些统称为puppet的资源。puppet是采用ruby语言研发的。
如下图:
单机模型:实现定义多个manifests --> complier --> catalog --> apply
master/agent模型:集中式管理
架构:
工作原理:
资源:是puppet的核心,通过资源申报,定义在资源清单中。
类:一组资源清单。
模块:包含多个类。
站点清单:以主机为核心,应用哪些模块。
puppet的安装可以使用源码安装,也可以使用rpm(官方提供)、epel源、官方提供的yum仓库来安装(通过下载官方提供的rpm包可以指定官方的yum仓库)。
这里使用的是2.7系列的,使用epel仓库
|
1
|
yum install puppet -y |
puppet从以下三个维度来都资源完成抽象:
|
1
2
3
4
5
|
1、相似的资源被抽象成同一种资源“类型,”如程序包资源、用户资源及服务资源等2、将资源属性或状态的描述与其实现方式剥离开来,如仅说明安装一个程序包而不用关系其具体 是yum、pkgadd、prots或其他方式实现3、仅描述资源的目标状态,也即期望其实现的结果,而不是其具体过程,如“确定nginx运行起来” 而不是具体描述为“运行nginx命令将启动起来” |
这三个也被称为puppet的资源抽象层(RAL)。RAL由type(类型)和provide(提供者,即不同的OS上的特定实现)组成。
资源是puppet用于模型化系统配置的基础单元,每个资源都从某个角度描述了系统属性,如某程序包必须安装或某用户必须移除等,在puppet,用于完成此类功能的代码也即“资源申报”
|
1
2
3
|
type { ‘title’: atttibue => value, } |
资源的文件统一以.pp结尾。在定义时,资源类型必须使用小写字母,而资源名称仅是一个字符串,但要求在同一类型中期必须唯一。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
## 帮助查看:puppet describe [-s] packagepuppet支持使用的软件包管理器:yum,rpm,apt,prots,gem,msi,dpkg,pkg常用的参数:ensure:程序包的目标状态,值有present(installed)、absent(不存在)、purged、held、 latestname:资源的名称,即软件包的名字,可以省略,如果省略,将继承title的值provide:软件包管理器,会自动识别source:指定程序包文件路径install_options:安装选项,最常用的是通过INATALLDIR来制定安装目录 |
|
1
2
3
4
5
6
7
8
9
10
11
12
|
## 帮助查看:puppet describe [-s] service常用的参数: ensure:服务的额目标状态,值有true(running)和false(stopped) enable:是否开机自动启动,值有true和false name:服务名称,可以省略,如果省略,将继承title的值 path:服务脚本路径,默认为/etc/init.d/下 start:定制启动命令 stop:定制关闭命令 restart:定制重启命令 status:定制状态 |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
## 帮助查看: puppet describe [-s] file ensuce:目标状态,值有*absent*, *present*, *file*, 和*directory*.backup:通过filebacket资源来备份文件,值通常为filebucket资源的名称content:文件内容,生成方式有三种(content,source,target),三者彼此互斥source:通过制定的url下载文件至本地,获取文件格式为: puppet:///modules/MODULE_NAME/file_names,使用模块时会用到target:为符号链接指定目标links:文件为符号连接,值为“follow”,“manage”path:文件路径,必须使用双引号mode:定义权限,通常为8进制数字owner: 定义文件的属主group:定义文件的属组force:强制执行删除文件、链接或目录、仅用于ensure为absent时purge:清除指定目录中存在的,但未在资源中定义的文件resurce:目录递归,值为true,false,inf,remotereplace:替换,本地存在的文件与资源中指定的文件内容不同时是否执行替换,默认为否 |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package { ["httpd",‘mysql-server‘,‘php‘]: ensure => present} service { ["httpd",‘mysqld‘]: ensure => true, enable => false}file{‘my.cnf‘: ensure => file, source => ‘/root/my.cnf‘, path => ‘/etc/my.cnf‘,} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
## 帮助查看: puppet describe [-s] exec常用的参数:command:要执行的命令,通过为命令文件的完整路径path:命令搜索路径group:执行命令的组user:执行命令的用户onlyif:0,表示仅在命令的状态返回值为0时才执行此命令refresh:定义接受的其他资源的通知时,则要重新执行此命令refreshonly:仅被当被依赖的资源发生改变时才被触发tries:尝试次数,默认为1try_sleep:多次尝试之间的时间间隔 |
|
1
2
3
4
5
6
7
8
|
## 帮助查看: puppet describe [-s] group常用参数: ensure:目标状态,present,absent name:组名 gid:GID system:系统组 |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
## 帮助查看: puppet describe [-s] user常用参数:ensure:目标状态,present,absentname:用户名uid:用户uidsystem:系统用户home:用户家目录shell:用户默认shellgid:用户的gidpassword:密码,使用加密后密码managehome: 是否创建家目录,默认为false |
|
1
2
3
4
5
6
7
8
9
10
11
|
常见属性ensure:目标状态,present,absentcommand:命令或脚本environment:运行时的环境变量hour:小时mouth:月monthday:日weekday:周minute:分name:名称user: 默认为root |
|
1
2
3
|
常用参数:message:信息name:信息名称 |
常见的资源就是这些。更详细的可以使用puppet describe命令查看。
使用Type[‘title‘],首字母必须大写
puppet提供了before、require、notify、subscribe四个元参数来定义资源之间的相关性。
|
1
2
3
4
|
require:表示需要依赖于某个资源before:表示应该先执行本资源,在执行别的资源notify: 表示将当前资源的变动信息通知给别的资源,为通知的发出者subscribe:表示定义某资源的变动信息,为通知的接收者 |
依赖关系还可以使用->和~>来表示
|
1
2
|
-> 表示后资源需要依赖前资源~> 表示前资源变动通知后资源调用 |
例如:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package{‘nginx‘: ensure => installed,}file{‘nginx.conf‘: ensure => file, source => ‘/root/nginx.conf‘, require => Package[‘nginx‘], path => ‘/etc/nginx/nginx.conf‘,} service{‘nginx‘: ensure => true, enable => true, require => Package[‘nginx‘], subscribe => File[‘nginx.conf‘],} |
6、puppet变量
puppet的变量名称以“$”开头,赋值操作符为“=”
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
puppet的变量类型:布尔型:true和false,不能加引号,if语句的测试条件和比较表达式都会返回布尔型值, 另外,其他数据类型也可以自动转换为布尔型,如空字符串为false等undef:从未声明的变量的值类型即为undef,也可以手动为某变量赋予undef值, 即直接使用不加引号的undef字符串字符型:非结构化的文本字符串,可以使用引号,也可以不用。单引号中的变量不会替换, 而双引号中的能够进行变量替换;字符型也支持使用转移符数值型:可为整数或浮点数,不过,puppe只有在数值上下文才把数值当数值对待, 其他清理下一律以字符型处理数组:数组值为中括号“[]”中的以逗号分隔的项目列表,最后一个项目后面可以有逗号; 数组中的袁术可以为任何可用数据类型,包括hash或其他数组,属组索引为从0开始的整数, 也可以使用负数索引hash:即为外键值数据类型,键和值之间使用“=>”分隔,键值对定义在“{ }”中, 彼此间以逗号分隔;其键位字符型数据,而值可以为puppet支持的任意数据类型, 访hash类型的数据元素要使用“键”当作索引进行。实际上和关联数组应属于同一数据类型正则表达式:属于puppet的非标准数据类型,不能赋值给变量,仅能用于有限的几个接收正则 表达式的地方,即接受使用“=~”及“!~”匹配操作符的位置,通常包括case语句中的 selector,已经节点名称匹配的位置,他们不能传递给函数或用于资源属性的定义facter变量:可以通过facter查看内置变量: 例如:agent端:$environment,$clientcert,$clentbversion server端:$servername,$serverip,$serverversion |
puppet中的正则表达式支持使用(?<ENABLED OPTION>:<SUNPATTERN>)和(?-<DISABLED OPTION>:<SUNPATTERN>)两个特殊的符号,如下面的示例,表示做正则表达式匹配时启用选项“i(忽略字符大小写)”,但不支持使用“m(把.当作换行符)”和启用“x(忽略模式中的空白字符和注释)”
|
1
2
3
4
|
$packages = $operatingsystem ? { /(?i-mx:ubuntu|debian)/ => ‘apache2‘, /(?i-mx:centos|fedora|redhat)/ => ‘httpd‘,} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
puppet的判断语句主要有三种分别为if,case,selectorpuppet的操作符有:比较操作符,布尔操作符,算术操作符if语句分为单分支,双分支和多分支 单分支: if CONDITION { statement ... }双分支: if CONDITION { statement ... } else { statement ... }多分支: if CONDITION { statement ... } elsif CONDITION { statement ... } else { statement ... }case语句的语法 case CONTROL_EXPRESS { case1,...: { statement... } case2,...:{ statement... } ... ... default:{ statement... } }selector语句的用法 CONTROL_VARIABLE ? { case1 => value1 case2 => value2 ... default => valueN } |
例如:判断一个系统的OS的类型,并输出“welcome to OS”的信息
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
if $operatingsystem == /^(?i-mx:centos|fedora|redhat)/ { notice "welcome to redhat OS Family"}elsif $operatingsystem == ubuntu { notice "welcome to ubuntu server"}else { notice "unkown server"} ################################################################# case $operatingsystem { ‘Solaris‘: { notice("Welcome to Solaris") } ‘RedHat‘, ‘CentOS‘: { notice("Welcome to RedHat OSFamily") } /^(Debian|Ubuntu)$/:{ notice("Welcome to $1 linux") } default: { notice("Welcome, alien *_*") } } #################################################################$welcome =$operatingsystem ? { /^(?i-mx:centos|fedora|redhat)/ => ‘redhat OS Family‘, /^(?i-mx:ubuntu)/ => ‘ubuntu‘, /^(?i-mx:debian)/ => ‘debebian‘, }notify { "$welcome": message => "welcome to $welcome",} |
|
1
2
3
|
class my_class { ...puppet code ...} |
|
1
2
3
4
5
6
7
8
9
10
|
class nginx { package { ‘nginx‘: ensure => installed, name => nginx, } service { ‘nginx‘: ensure => true, enable => true, subscribe => Package[‘nginx‘], }} |
以上是类的定义,类似于函数。需要使用的话,要调用。调用时,使用关键在include即可。
类可以基于父类调用,在调用时,应该指定通过inherits关键字调用父类。例如:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class nginx { package { ‘nginx‘: ensure => installed, name => nginx, }}class nignx::web inherits nginx { service { ‘nginx‘: ensure => true, enable => true, }}include nignx::web |
也支持类的覆盖和重写:
|
1
2
|
=>:在子类中覆盖父类中的资源+>:在子类中为父类中的资源新增额外的属性 |
puppet模块:为了实现某种完备功能而组织成的一个独立的、自我包含的目录结构
模块名:目录名
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
目录结构:Module_name: manifests init.pp: 必须声明一个类,类名与模块名相同; *.pp: MODULE_NAME::[SUBDIR_NAME]::MANIFESTS_FILE_NAME files:静态文件 puppet url:puppet:///modules/MODULE_NAME/[SUBDIR_NAME]/FILE_NAME file{‘nginx.conf‘: source => puppet:///modules/nginx/nginx.conf } templates: 模板文件:*.erb template(‘MODULE_NAME/TEMPLATE_FILE_NAME‘); file{‘nginx.conf‘: content => template(‘模板文件‘), } lib: 插件 tests: 模块使用说明文档 spec: lib目录下的插件使用说明文档 |
三、使用maste/agent模式,部署LAMP平台
Master/Agent模型之间通信是靠主机名通信的,大致步骤是:
|
1
2
3
|
1、master启动时会为自己的key,自签2、agent启动前要生成自己的key,生成签署请求3、master收到请求书,验证合法性,签署证书 |
实验环境:
|
1
2
3
|
Master端:172.16.10.9 server.magedu.comAgent端:172.16.10.77 basic.example.com 172.16.10.122 node2.example.com |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
### 安装软件在172.16.10.9:yum install puppet puppet-server -y在172.16.10.77,172.16.10.122:yum install puppet -y### 提供主机名解析名文件# 172.16.10.9 172.16.10.77 172.16.10.122# /etc/hosts127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4::1 localhost localhost.localdomain localhost6 localhost6.localdomain6172.16.10.77 basic.example.com172.16.10.9 server.magedu.com172.16.10.122 node2.example.com### 配置3台机器时间同步 |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
## Master端 目录文件,如下:[root@server modules]# pwd/etc/puppet/modules[root@server modules]# tree .├── mysql│ ├── file│ │ └── my.cnf│ └── manifests│ └── init.pp└── nginx ├── files │ └── nginx.conf └── manifests └── init.pp6 directories, 4 files[root@server modules]# cat mysql/manifests/init.pp class mysql { package{‘mysql-server‘: ensure => installed, } file{‘my.cnf‘: ensure => file, source => ‘puppet:///modules/mysql/my.cnf‘, path => ‘/etc/my.cnf‘, require => Package[‘mysql-server‘], } service{‘mysqld‘: ensure => true, enable => true, require => Package[‘mysql-server‘], subscribe => File[‘my.cnf‘], }}[root@server modules]# cat nginx/manifests/init.pp class nginx { package{‘nginx‘: ensure => installed, } file{‘nginx.conf‘: ensure => file, source => ‘puppet:///modules/nginx/nginx.conf‘, require => Package[‘nginx‘], path => ‘/etc/nginx/nginx.conf‘, } service{‘nginx‘: ensure => true, enable => true, require => Package[‘nginx‘], subscribe => File[‘nginx.conf‘], } }## 说明:my.cnf nginx.cnf是配置文件[root@server manifests]# pwd/etc/puppet/manifests[root@server manifests]# tree .├── server│ ├── basic.pp│ └── node2.pp└── site.pp1 directory, 3 files[root@server manifests]# cat server/node2.pp node ‘node2.example.com‘ { include nginx,mysql}[root@server manifests]# cat server/basic.pp node ‘basic.example.com‘ { include nginx,}[root@server manifests]# cat site.pp import "server/*.pp" |
创建好目录清单后,此时需要启动服务。第一次启动时,可手动启动。
Master端启动:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
[root@server ~]# puppet master -v -d --no-daemonizedebug: Failed to load library ‘rubygems‘ for feature ‘rubygems‘debug: Puppet::Type::User::ProviderUser_role_add: file roleadd does not existdebug: Puppet::Type::User::ProviderPw: file pw does not existdebug: Puppet::Type::User::ProviderDirectoryservice: file /usr/bin/dscl does not existdebug: Puppet::Type::User::ProviderLdap: true value when expecting falsedebug: /File[/var/lib/puppet/yaml]: Autorequiring File[/var/lib/puppet]debug: /File[/var/lib/puppet/ssl/private]: Autorequiring File[/var/lib/puppet/ssl]debug: /File[/etc/puppet/auth.conf]: Autorequiring File[/etc/puppet]debug: /File[/var/lib/puppet/lib]: Autorequiring File[/var/lib/puppet]debug: /File[/var/lib/puppet/facts]: Autorequiring File[/var/lib/puppet]debug: /File[/var/lib/puppet/ssl/certificate_requests]: Autorequiring File[/var/lib/puppet/ssl]debug: /File[/etc/puppet/manifests/site.pp]: Autorequiring File[/etc/puppet/manifests]debug: /File[/var/lib/puppet/rrd]: Autorequiring File[/var/lib/puppet]debug: /File[/var/log/puppet/masterhttp.log]: Autorequiring File[/var/log/puppet]debug: /File[/var/lib/puppet/ssl/private_keys]: Autorequiring File[/var/lib/puppet/ssl]debug: /File[/var/lib/puppet/reports]: Autorequiring File[/var/lib/puppet]debug: /File[/etc/puppet/puppet.conf]: Autorequiring File[/etc/puppet]debug: /File[/var/lib/puppet/state]: Autorequiring File[/var/lib/puppet]debug: /File[/etc/puppet/fileserver.conf]: Autorequiring File[/etc/puppet]debug: /File[/var/lib/puppet/server_data]: Autorequiring File[/var/lib/puppet]debug: /File[/etc/puppet/manifests]: Autorequiring File[/etc/puppet]debug: /File[/var/lib/puppet/bucket]: Autorequiring File[/var/lib/puppet]debug: /File[/var/lib/puppet/ssl/public_keys]: Autorequiring File[/var/lib/puppet/ssl]debug: /File[/var/lib/puppet/ssl]: Autorequiring File[/var/lib/puppet]debug: /File[/var/lib/puppet/ssl/certs]: Autorequiring File[/var/lib/puppet/ssl]debug: /File[/var/lib/puppet/yaml]/ensure: createddebug: /File[/var/lib/puppet/rrd]/ensure: createddebug: /File[/var/lib/puppet/reports]/ensure: createddebug: /File[/var/lib/puppet/facts]/ensure: createddebug: /File[/var/lib/puppet/ssl]/ensure: createddebug: /File[/var/lib/puppet/ssl/private_keys]/ensure: createddebug: /File[/var/lib/puppet/ssl/public_keys]/ensure: createddebug: /File[/var/lib/puppet/ssl/certs]/ensure: createddebug: /File[/var/lib/puppet/state]/ensure: createddebug: /File[/var/lib/puppet/ssl/private]/ensure: createddebug: /File[/var/lib/puppet/lib]/ensure: createddebug: /File[/var/lib/puppet/bucket]/ensure: createddebug: /File[/var/lib/puppet/ssl/certificate_requests]/ensure: createddebug: /File[/var/lib/puppet/server_data]/ensure: createddebug: Finishing transaction 70003525843560debug: /File[/var/lib/puppet/ssl/ca/signed]: Autorequiring File[/var/lib/puppet/ssl/ca]debug: /File[/var/lib/puppet/ssl/ca/requests]: Autorequiring File[/var/lib/puppet/ssl/ca]debug: /File[/var/lib/puppet/ssl/ca/private]: Autorequiring File[/var/lib/puppet/ssl/ca]debug: /File[/var/lib/puppet/ssl/ca]/ensure: createddebug: /File[/var/lib/puppet/ssl/ca/signed]/ensure: createddebug: /File[/var/lib/puppet/ssl/ca/private]/ensure: createddebug: /File[/var/lib/puppet/ssl/ca/requests]/ensure: createddebug: Finishing transaction 70003525749380info: Creating a new SSL key for cainfo: Creating a new SSL certificate request for cainfo: Certificate Request fingerprint (md5): E4:F9:A5:7C:CD:DC:D5:F4:30:C5:97:D4:4B:75:E2:1Anotice: Signed certificate request for canotice: Rebuilding inventory filedebug: Using cached certificate for cainfo: Creating a new certificate revocation listinfo: Creating a new SSL key for server.magedu.comdebug: Using cached certificate for cainfo: Creating a new SSL certificate request for server.magedu.cominfo: Certificate Request fingerprint (md5): EC:52:9E:3B:8A:92:A3:E2:82:FB:D6:EF:7B:36:50:1Fnotice: server.magedu.com has a waiting certificate requestdebug: Using cached certificate for cadebug: Using cached certificate_request for server.magedu.comnotice: Signed certificate request for server.magedu.comnotice: Removing file Puppet::SSL::CertificateRequest server.magedu.com at ‘/var/lib/puppet/ssl/ca/requests/server.magedu.com.pem‘notice: Removing file Puppet::SSL::CertificateRequest server.magedu.com at ‘/var/lib/puppet/ssl/certificate_requests/server.magedu.com.pem‘notice: Starting Puppet master version 2.7.25debug: Finishing transaction 70003524197780debug: No modules mount given; autocreating with default permissionsdebug: No plugins mount given; autocreating with default permissions |
出现以上信息时,证明测试没有问题,此时可以使用:
|
1
|
service puppetmaster start |
以172.16.10.122为例:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
[root@node2 ~]# puppet agent --server=server.magedu.com --no-daemonize -d### 会出现以下信息:info: Creating a new SSL key for node2.example.cominfo: Caching certificate for cainfo: Creating a new SSL certificate request for node2.example.cominfo: Certificate Request fingerprint (md5): 1B:D4:E5:D9:15:A8:87:5B:67:C0:4B:C2:72:\ 15:45:BA###############################################################此时在Master端:[root@server ~]# puppet cert --list "node2.example.com" (1B:D4:E5:D9:15:A8:87:5B:67:C0:4B:C2:72:15:45:BA)签名:[root@server ~]# puppet cert --sign node2.example.comnotice: Signed certificate request for node2.example.comnotice: Removing file Puppet::SSL::CertificateRequest node2.example.com at \‘/var/lib/puppet/ssl/ca/requests/node2.example.com.pem‘#####################################################################此时Agent端出现:debug: Using cached certificate for node2.example.comnotice: Starting Puppet client version 2.7.25表明签署成功。####################################################################确保上述agent相关操作不存在问题后,便可以将--server选项指定的信息存储与agent的配置文件中,并以服务的方式启动puppet agent了。其配置文件为/etc/puppet/puppet.confecho "server=server.magedu.com" >> /etc/puppet/puppet.conf####################################################################service puppet start |
172.16.10.77同样的配置。
puppet客户端默认每30分钟很服务器通讯一次,但是有时,我们希望服务器能够给客户端紧急推送一些任务,于是就有了puppet kick(puppet 2.6以前叫puppetrun)。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
1)编辑客户端配置文件/etc/puppet/puppet.conf在[agent]端中添加如下listen=true2)在客户端编辑或创建新文件/etc/puppet/namespaceauth.conf,包含下面内容[puppetrunner]allow *.magedu.com3)在客户端编辑文件auth.conf,添加如下内容path /run method save auth any allow server.magedu.com## 注意,这一项放到 path /前面4)推送方法,在服务器端运行命令[root@server puppet]# puppet kick -p 1 --host node2.example.comTriggering node2.example.comGetting statusstatus is successnode2.example.com finished with exit code 0Finished |
配置基本完成。
本文出自 “逆水寒” 博客,请务必保留此出处http://guoting.blog.51cto.com/8886857/1568590
原文:http://www.cnblogs.com/puremans/p/6431226.html