puppet是一个IT基础设施自动化管理工具,它能够帮助系统管理员基础设施的整个生命周期,供应(provisioning)、配置(configuration)、联动(orchesrtation)及报告(reporting)
基于puppet,可实现自动化重复任务,快速部署关键性应用以及在本地或者云端完成主动管理变化和快速扩展架构规模等
遵循GPL协议(2.7.0-),基于ruby语言开发
2.7.0以后使用apache 2.0 license
对于系统管理员是抽象的,只依赖与ruby和facter
安装:
[root@node1 ~]# yum install puppet facter
常用资源介绍
puppet 从以下三个维度来对资源完成抽象:
1、相似的资源被抽象成同一种资源“类型” ,如程序包资源、用户资源及服务资源等;
2、将资源属性或状态的描述与其实现方式剥离开来,如仅说明安装一个程序包而不用关心其具体是通过yum、pkgadd、ports或是其它方式实现;
3、仅描述资源的目标状态,也即期望其实现的结果,而不是其具体过程,如“确定nginx 运行起来” 而不是具体描述为“运行nginx命令将其启动起来”;
group
获取帮助
[root@node1 manifests]# puppet describe group -s -m
常见属性
name:组名;
gid:GID;
system:是否为系统组,true OR false;
ensure:目标状态,present/absent;
members:成员用户;
demo:
group{'nginx':
name => 'nginx',
gid => 1003,
system => true,
ensure => 'present',
}
group{'marivn':
name => 'marvin',
gid => 1004,
system => true,
ensure => 'present',
}
user
获取帮助
[root@node1 manifests]# puppet describe user -s -m
常见属性
name:用户名;
uid: UID;
gid:基本组ID;
groups:附加组,不能包含基本组;
comment:注释;
expiry:过期时间 ;
home:家目录;
shell:默认shell类型;
system:是否为系统用户 ;
ensure:present/absent;
password:加密后的密码串;
demo:
user{'marvin':
name => 'marvin',
gid => 1002,
comment => 'puppet create',
ensure => 'present',
system => false
}
package
获取帮助
[root@node1 manifests]# puppet describe package -s -m
属性
ensure:installed, present, latest, absent, any version string (implies present)
name:包名,可以省略,如果省略,将继承title的值; 可以写版本号
source:程序包来源,仅对不会自动下载相关程序包的provider有用,例如rpm或dpkg;
provider:指明安装方式
demo
package{'redis':
name => 'redis',
ensure => present,
}
service
获取帮助
[root@node1 manifests]# puppet describe service -s -m
常见属性
ensure:服务的目标状态,值有true(running)和false(stopped)
enable:是否开机自动启动,值有true和false
name:服务名称,可以省略,如果省略,将继承title的值
path:服务脚本路径,默认为/etc/init.d/下
start:定制启动命令
stop:定制关闭命令
restart:定制重启命令
status:定制状态
demo
service{'redis':
name => 'redis',
ensure => running,
enable => true,
}
file
获取帮助
[root@node1 manifests]# puppet describe file -s -m
常见属性
ensure:目标状态,值有absent,present,file,directory和link
file:类型为普通文件,其内容由content属性生成或复制由source属性指向的文件路径来创建;
link:类型为符号链接文件,必须由target属性指明其链接的目标文件;
directory:类型为目录,可通过source指向的路径复制生成,recurse属性指明是否递归复制;
path:文件路径;
source:源文件;
content:文件内容;
target:符号链接的目标文件;
owner:定义文件的属主;
group:定义文件的属组;
mode:定义文件的权限;
atime/ctime/mtime:时间戳;
demo:
file{'redis.conf':
ensure => file,
source => '/root/redis.conf', #源文件
path => '/etc/redis.conf', #目标文件
owner => 'redis',
group => 'redis',
mode => '0644'
}
exec
获取帮助
[root@node1 manifests]# puppet describe exec -s -m
常见属性
command (namevar):要运行的命令;
cwd:The directory from which to run the command.
creates:文件路径,仅此路径表示的文件不存在时,command方才执行;
user/group:运行命令的用户身份;
path:The search path used for command execution. Commands must be fully qualified if no path is specified.
onlyif:此属性指定一个命令,此命令正常(退出码为0)运行时,当前command才会运行;
unless:此属性指定一个命令,此命令非正常(退出码为非0)运行时,当前command才会运行;
refresh:重新执行当前command的替代命令;
refreshonly:仅接收到订阅的资源的通知时方才运行;
demo
exec{'mkdir':
command => 'mkdir /tmp/testdir',
path => '/bin:/sbin:/usr/bin:/usr/sbin',
creates => '/tmp/testdir'
}
cron
获取帮助
[root@node1 manifests]# puppet describe cron -s -m
常见属性
command:要执行的任务;
ensure:present/absent;
hour:
minute:
monthday:
month:
weekday:
user:以哪个用户的身份运行命令
target:添加为哪个用户的任务
name:cron job的名称;
demo
cron{'timesync':
command => '/usr/sbin/ntpdate 192.168.1.200 &> /dev/null',
ensure => present,
minute => '*/3',
user => 'root',
}
notify
获取帮助
[root@node2 ~]# puppet decribe notify -s -m
demo
notify{'sayhi':
message => 'how old are you?',
name => 'sayhi'
}
依赖通知介绍
before:表示需要在某个资源运行前运行 定义在先运行资源中
require:表示先运行require包含的资源 定义在后运行资源中
notify:A notify B:B依赖于A,且A发生改变后会通知B; 定义在A notify => Type['B']
subscribe:B subscribe A:B依赖于A,且B监控A资源的变化产生的事件;定义在B subscribe => Type['A']
demo:
package{'redis':
allow_virtual => false,
name => 'redis',
ensure => present,
}
file{'redis.conf':
ensure => file,
source => '/root/redis.conf',
path => '/etc/redis.conf',
owner => 'redis',
group => 'redis',
mode => '0644',
require => Package['redis'],
notify => Service['redis'],
}
service{'redis':
name => 'redis',
ensure => running,
enable => true,
require => Package['redis'],
#subscribe => File['redis.conf']
}
变量
字符型:引号可有可无;但单引号为强引用,双引号为弱引用;
数值型:默认均识别为字符串,仅在数值上下文才以数值对待;
数组:[]中以逗号分隔元素列表;
布尔型值:true, false;
hash:{}中以逗号分隔k/v数据列表; 键为字符型,值为任意puppet支持的类型;{ 'mon' => 'Monday', 'tue' => 'Tuesday', };
undef:未定义 ;
流程语句
puppet支持if,case,selector等常见流程语句
if demo
if $operatingsystemmajrelease == '7' {
$db_pkg='mariadb-server'
}else{
$db_pkg='mysql-server'
}
case demo
case $osfamily {
"RedHat": { $webserver='httpd' }
/(?i-mx:debian)/: { $webserver='apache2' }
default: { $webserver='httpd' }
}
selector demo
$pkgname = $operatingsystem ? {
/(?i-mx:(ubuntu|debian))/ => 'apache2',
/(?i-mx:(redhat|fedora|centos))/ => 'httpd',
default => 'httpd',
}
模块
1、创建模块结构
[root@node2 modules]# pwd
/etc/puppet/modules
[root@node2 modules]# mkdir chrony/{manifests,files,templates,lib,spec,tests} -pv
2、创建初始化文件
[root@node2 modules]# cd chrony/manifests/
[root@node2 manifests]# vim init.pp
class chrony{
package{'chrony':
allow_virtual => true,
name => 'chrony',
ensure => latest,
} ->
file{'chrony.conf':
path => '/etc/chrony.conf',
source => 'puppet:///modules/chrony/chrony.conf',
} ~>
service{'chronyd':
ensure => running,
enable => true,
}
}
模块列表
[root@node2 files]# puppet module list
/etc/puppet/modules
└── chrony (???)
/usr/share/puppet/modules (no modules installed)
继承
资源配置
class chrony::cron inherits chrony{
cron{'timesync':
command => '/usr/sbin/ntpdate 192.168.1.200 &> /dev/null',
ensure => present,
minute => '*/3',
user => 'root',
}
}
master 跟 agent模式
实验环境:
主节点: node2.zander.com
agent节点: node3.zander.com,node4.zander.com
节点必须要用完全名称解析,这里用hosts文件做设置,最好用dns解析
1、安装master节点服务
[root@node2 modules]# yum -y install facter puppet puppet-server
2、master节点手动前台开启,观察服务开启过程:(初始化证书,生产私钥,完成自签)
#观察模式启动
[root@node2 modules]# puppet master -v --no-daemonize
[root@node2 manifests]# ss -lntup|grep puppet
tcp LISTEN 0 128 *:8140 *:* users:(("puppet",pid=33424,fd=8))
#生产模式启动
[root@node2 modules]# systemctl start puppetmaster
#删除所有证书,慎用
[root@node3 ~]# rm -fr /var/lib/puppet/ssl
3、node3 node4 安装puppet 跟 facter
[root@node3 ~]# yum -y install facter puppet
观察模式启动:
[root@node3 ~]# puppet agent --no-daemonize -v --server node2.zander.com
生产模式启动:
[root@node3 ~]# vim /etc/puppet/puppet.conf
server = node2
[root@node4 ~]# systemctl start puppetagent
#如果需要重新生产证书
[root@node3 ~]# rm -fr /var/lib/puppet/ssl
5、master签证
master节点查看待签证证书
[root@node2 manifests]# puppet cert list
"node3.zander.com" (SHA256) 18:7D:91:54:A0:61:3A:C0:30:2F:83:97:7B:41:7B:5C:52:A3:B6:8F:28:CF:2D:AE:37:39:C0:F1:84:B0:62:91
#所有证书查看
[root@node2 manifests]# puppet cert list --all
"node3.zander.com" (SHA256) A6:E7:74:16:E4:BA:5F:51:8F:49:2B:0C:63:21:2D:78:ED:0D:08:51:1C:8C:54:A1:1D:94:8B:4A:45:F4:8D:5A
"node4.zander.com" (SHA256) B8:FD:E1:24:AA:6E:6A:A5:DA:31:7A:CB:EC:92:B2:30:BE:F6:45:FE:79:21:EB:72:A6:C6:16:51:9E:70:29:64
+ "node2.zander.com" (SHA256) 4B:F6:93:5C:1B:79:63:73:42:66:2D:25:12:7E:9E:A8:1F:59:FF:B7:99:38:52:DF:D7:C8:1E:ED:14:24:D5:20 (alt names: "DNS:node2.zander.com", "DNS:puppet", "DNS:puppet.zander.com")
#签证单个
[root@node2 manifests]# puppet cert sign node3.zander.com
Notice: Signed certificate request for node3.zander.com
Notice: Removing file Puppet::SSL::CertificateRequest node3.zander.com at '/var/lib/puppet/ssl/ca/requests/node3.zander.com.pem'
#签证所有
[root@node2 manifests]# puppet cert sign --all
Notice: Signed certificate request for node4.zander.com
Notice: Removing file Puppet::SSL::CertificateRequest node4.zander.com at '/var/lib/puppet/ssl/ca/requests/node4.zander.com.pem'
6、master节点添加清单
[root@node2 modules]# vim /etc/puppet/manifests/site.pp
node 'node3.zander.com' {
include redis
}