Puppet资源使用
一、什么是puppet
Puppet是一个IT基础设施自动化管理工具,它能够帮助系统管理员管理基础设施的整个生命周期:供应(provisioning)、配置(configuration)、联动(orchestration)及报告(reporting)
puttet的工作模型
puppet通过声明性、基于模型的方法进行IT自动化管理
定义:通过puppet的声明性配置语言 定义基础设置的目标状态
模拟:强制应用改变配置之前先进行模拟性应用;dry-run
强制:自动、强制部署达成目标状态,纠正任何偏离的配置
报告:报告当下状态及目标状态的不同,以及达成目标状态所进行的任何强制性改变
基于puppet,可以实现自动化重复任务,快速部署关键性应用以及在本地或云端完成主动管理变更和快速扩展架构规模等
对于系统管理员是抽象的,只依赖于ruby与facter
能管理多大40多种资源、例如;file、user、group、host、package、service、cron、exec、yum、repo等,适合整个软件生命周期管理
Puppet使用两种模型
1、 单机使用
Puppet apply
2、 master/agent(即C/S方式)
master:puppet,puppet-server
agent:puppet
二、介绍puppet
Puppet的C/S的工作原理
1、 agent向主机请求catalog代码,在请求时要带上自己的主机名与facts,facts里 包含了agent服务器自身的一些系统特征,比如操作系统是什么、是哪个版本、cpu是什么型号,内存有多大信息等
2、 master接受到agent的请求后开始查询此节点包含的清单,把这些资源找出后编译成calalog,再发送给agent
3、 agent接收到calalog后就开始应用代码,并把执行的状态结构生成报告返回给master
4、 master接收报告并记录日志
puppet的认证方式
1、 puppet有其自己的证书管理机制,agent和master间的通信是需要得到master的认证,证书存放在/var/llib/puppet/ssl/
在master/agent首次启用过程:
1、 master启动时会为自己生成key,并签署证书,让自己成为一个ca
2、 agent首次启动为自己生成key,生成证书签署请求,并将证书请求发送给master请求签署
3、 master收到agent的证书签署请求后,由管理员先验证请求是否合法,而后对认证书签署请求作出签署或不签署
puppet的三层模型
Configuration Language #配置语言
Transactional Layer #事务层
Resources Abstraction Layer #资源抽象层
三、Manifest清单
Puppet的程序文件称作“manifest(清单)”,以.pp作为文件明名后缀
如前所述,puppet语言的核心是:资源定义,而定义一个资源的核心就在于描述其目标状态
而manifest却还实现了常见的程序逻辑,如条件语句、资源集合及打印文件信息等功能
简言之,也即resource定义在manifest文件中,或使用manifest文件定义resource
Puppet apply 子命令能够将一个manifest中描述的目标状态强制实现,因此,它通常以manifest文件为参数
四、catlog文件
Puppet通过manifest同步资源时,不会直接应用manifest文件,而是要经过预先的编译过程,这是因为manifest文件中可能会包含条件判断、变量、函数及其他的程序逻辑
实际执行中,有可能会基于层次及包含关系存在多个manifest文件,这些文件会被编译进同一个称作“catalog”的文件
编译完成后的catalog文件仅包含各个资源以及它们同步时的次序
puppet资源抽象
puppet从以下三个维度来对资源完成抽象
1、相似的资源被抽象成同一种资源“类型”,如程序包资源、用户资源及服务资源等;
2、将资源属性或状态的描述与其实现方式剥离开来,如仅说明安装一个程序包而不用关心其具体是通过yum、pkgadd、ports或是其他方式实现
3、仅描述资源的目标状态,也即期望其实现的结果,而不是其具体过程,如“确定nginx运行起来”而不是描述为“运行nginx命令将其启动起来”;
这三个也被称为puppet的资源抽象层(RAL)
1、RAL由type(类型)和peovier(提供者,既不同OS上的特定实现)组成
五、资源使用
Puppet的八种常用类型
user group package file service exec cron notify
puppet的十二中次常用类型
router stage schedule computer host augeas mount yumrepo interface
tidy sshkey resources
1、 定义组的资源
puppet describe group #可查看group的用法
vim group.pp
group { 'mygrp':
name => 'group',
ensure => 'present',
gid => 2000,
}
2、 定义(创建)用户资源
puppet describe user #查看user的用法
vim use.pp
user {'zy':
ensure => present,
system => false,
comment => 'test user',
shell => '/bin/bash',
home => '/home/zy',
groups => 'group',
managehome => true,
}
[root@node2 ~]# puppet apply -v use.pp #执行该命令
3、 定义before和require
group {'group':
ensure => present,
gid =>600,
before => user['zy'],
}
user{'zy':
ensure => present,
gid => 600,
shell => '/bin/bash',
home => '/home/zy',
}
#因为有上面的实验,所以报了个小错,不过不要紧,资源编写是没问题的
4、定义package
puppet describe package #查看语法
vim package.pp
package {'redis':
ensure => 'latest',
provider => 'yum',
}
puppet apply -v --noop package.pp #--noop参数 可进行检查语法
4、 定义service
path #定义脚本时的路径
ensure running /stopped
enable
hasstatus: start / stop / status /restart
vim service.pp
service {'redis':
ensure => running,
enable => true,
}
定义程序包的依赖关系,
package {'memcached':
ensure => installed,
}
service{'memcached':
ensure => running,
enable => false,
require => package['memcached']
}
5、 定义file文件资源
简单的文件复制:
file {'/tmp/redis.conf':
ensure => file,
source => /etc/puppet/manifests/files.conf #文件的来源
}
创建文件
reurse => true #递归复制
file {'/tmp/text.txt':
ensure => file,|director
content => 'how are you ', #文件内容
owner => 'zy', #文件属主
group => 'group', #文件属组
mode => '0400',
}
链接文件
file {'/tmp/test.txt.link':
ensure => link,
target => '/tmp/test.txt',
}
(2)定义file、service、和package资源的结合
service {'httpd':
ensure => running,
enable => true,
restart => 'systemctl restart httpd.service',
}
package {'httpd':
ensure => installed,
}
file {'httpd.conf':
path => '/etc/httpd/httpd.conf',
source => '/root/httpd.conf',
ensure => file
notify => Service['httpd'],
}
Package['httpd'] -> File['httpd.conf'] -> Service['httpd']
2、 例子
#1|#2|#3 代表一种表示方法
package{'redis':
ensure => installed,
} #2 ->
file{'/etc/redis.conf':
source => '/etc/manifests/files/redis.conf',
ensure => file,
owner => redis,
group => root,
mode => '0640',
notify => Service['redis'], #依赖于Service
} #2 ->
# ~> #表示notify之意
service{'redis':
ensure => running,
enable => true,
subscribe => File['/etc/redis.conf'], #依赖于File
#1 require => ['Package["redis"]','File["/etc/redis.conf"]'],
}
#3 Package['redis'] -> File['/etc/redis.conf'] -> Service['redis']
Package['redis'] -> File['/etc/redis.conf'] ~> Service['redis']
资源特殊属性(前后资源)
notify:
A notify B #即B依赖于A,且A发生改变后会通知B
subscribe:
B subscribe A #即B依赖于A,且B监控A资源的变化产生的事件
6、 定义exec资源
puppet describe exec #查看用法
vim exec.pp
exec {'cmd':
command => '[ -e /tmp/testdir ] || mkdir /tmp/testdir', #-e 判断
path => ['/bin/','/sbin/','/usr/bin/','/usr/sbin'],
#creates => '/tmp/testdir' #目录不存在才执行command
}
puppet apply exec.pp
创建用户
exec {'user':
command => 'useradd zy',
path => '/bin:/sbin:/usr/bin:/usr/sbin',
unless => 'id zy', #当执行失败时,才会执行command
}
redis的重启设置
7、定义cron
vim cron.pp
#同步时间
cron{'timesync':
command => '/usr/sbin/ntpdate 172.17.0.1 &> /dev/null ',
ensure => present,
minute => "*/5",
target => 'root',
}
puppet apply cron.pp
8、定义notify资源
send an arbitrary to the agent run-time log
#向代理运行时日志发送任意
notify{'sayhi':
message => 'hello word'
}
9、定义tag格式
vim service.pp
package{'redis':
ensure => latest,
}
file{'redis.conf':
path => '/etc/redis.conf',
source => '/root/redis.conf',
ensure => file,
mode => '0644',
owner => redis,
group => root,
notify => Service['redis'],
tag => 'cpfile',
}
service{'redis':
ensure => running,
enable => true,
hasrestart => true,
restart => 'systemctl restart redis',
# subscribe => File['redis.conf'],
tag => "onlyrestart",
}
Package['redis'] -> File['redis.conf'] ~> Service['redis']
执行:
puppet apply --tags onlyrestart service.pp
puppet apply --tags cpfile service.pp
10、定义变量
#自定义变量
方法1:
$pkgname = 'tree'
package{'installpkg':
name => "$pkgname",
ensure => latest,
}
方法2:
$pkgname = 'tree'
package{"$pkgname":
ensure => latest,
}
内建变量:
master端变量:$servername $serverip $serverversion
agent端变量:$clientcert $clientversion $environment
parser变量:$module_name 内建的子系统
facter -p #查看所有内建变量
#测试内建变量,可直接调用
notify{'os':
message => "$operatingsystem $operatingsystemrelease",
}
六、Scope区域的使用
Scope是一个特定的代码区域,用于同程序中的其他代码隔离开来
在puppet中,scope可用于限定变量及资源默认属性的作用范围,但不能用于限定资源名称及资源引用的生效范围
何给定的scope都可以访问它自己的内容,以及接收来自于其父scope、节点scope及top scope的内容
top scope仅能访问自己变量和属性默认值;
节点scope能访问自己的及top scope的变量和属性默认值
example::parent,example::other和example::four能访问自己的以及节点scope和top scope的变量和默认值
七、if statement:的使用
单分支
if condition{
statement
...
}
双分支:
if condition {
statement
...
}
else{
statement
...
}
多分支:
if condition {
statement
...
}
elsif condition{
statement
...
}
else{
statement
...
}
例子:
if $operatingsystemmajrelease == '7' {
$db_pkg='mariadb-server'
}else{
$db_pkg='myslq-server'
}
package{"$db_pkg":
ensure => installed,
}
八、case statement的使用
case给定的方式:
(1)直接字串
(2)变量
(3)有返回值的函数
(4)正则表达式模式
(5)default
类似于if语句,case语句会从多个代码快中选择一个分支执行,这跟其他编程语言中的case语句功能一致
case语句会接受一个控制表达式和一组case代码块,并执行第一个匹配到控制表达式的块
格式:
case control_express{
case1, ... {statement ...}
case2,...{statement...}
default : {statement...}
}
例子:
case $operatingsystem{
'Solaris': {notice("welcome to Solaris")}
'Redhat','CentOS' : {notice("welcome to Rehat OSFamily")}
/^(Debian|Ubunto)$/:{notice("say hello")}
default: {notice("you are good")}
}
2、例子
if $osfamily == 'RedHat'{
$webPkg='httpd'
}elsif $osfamily =="Debian"{
$webPkg='apache2'
}else{
$webPkg='apache'
}
case $osfamily{
'Redhat':{ $webPkg='httpd'}
/(?i-mx:debian)/:{$webPkg='apache2'} #忽略大小写匹配
default: {$webPkg='apache'}
}
package{"$webPkg":
ensure => installed
}