puppet与ansible都是运维自动化工具,二者最大的区别在于,puppet重量级适用于较大规模运维场景,而ansible较轻量级在较大规模站点的功能显得不那么强。

puppet使用ruby语言研发,所以在使用中还要掌握一些ruby的语法;


本处使用epel仓库安装puppet,版本是3.6.2

yum -y install  puppet

puppet获取帮助信息

puppet help

puppet有两种工作模型

standalone模型  
master/agent模型

puppet的资源类型

puppet describe -l   #显示所有的puppet资源类型
puppet describe -ms group   #显示指定资源的简要信息,-s显示简要信息,-m显示元信息

定义资源的语法

resource {'title':
    attribute  => value
    ……
}
#resource必须使用小写,title在同一资源中必须唯一


puppet的八种常用资源类型:

1、group资源

创建组

cat group.pp
group{'mygrp':                #资源名称是group,title是mydb,以冒号标识
        ensure => present,    #ensure表示创建或删除组,此处present表示创建组,absent表示删除组
        name => mygrp,        #组名称,如果未定义则使用title指定的字符串,即此字段可以省略
        system => yes,        #此组是系统组
        gid => 1991,          #定义组id
}
#上述我们创建一个创建组的资源清单,每字段尾都要以逗号隔开,最后一行的逗号则可以写也可以不写

puppet apply -v --noop group.pp
#-v显示详细信息,--noop表示干跑,即模拟测试此资源清单,实际操作可以去掉--noop参数
#如果此组已经存在,多执行几次命令结果都是不变的,因为此资源是幂等的

2、user资源

创建用户

cat user.pp 
user{'user1':
        ensure => present,
        uid => 3000,         #指定用户id
        groups => puppet,      #用户所属辅助组
        home => '/app',        #指定用户家目录
        shell => '/bin/csh',      #在使用路径标识时一定要记得加引号,否则报错
}
#创建用户资源清单
#如果用户属于多个辅助组,可以使用groups => ['puppet','mygrp'],数组的表示方式
puppet apply -v  user.pp 
#应用此清单,即可创建资源
资源依赖/资源引用
user{'user1':
        ensure => present,
        uid => 3000,
        home => '/app',
        shell => '/bin/csh',
        groups => ['testgrp','mygrp'],
        require => [Group['testgrp'],Group['mygrp']],   #require引用资源,资源的首字母必须大写
}
group{'testgrp':
        ensure => present,
}
group{'mygrp':
        ensure => present,
}
#资源依赖,即要创建user1用户,必须存在testgrp和mygrp组,而且这两个组必须被引用
#除了require外,资源依赖还有一种表示方式:before,即某个资源被别的资源依赖,如下在testgrp组资源下定义
before => User['user1'],   #此组被user1用户资源所依赖,即此组要先存在才能创建user1

#总结,依赖关系用两种方式定义,一是被前资源依赖,一是被后资源依赖

3、package资源

安装软件包

cat package.pp  
package{'nginx':
        ensure => latest,
        name => nginx,
}
#就这些字段就可以将nginx安装了

4、service资源

启动服务

cat service.pp  
service{'nginx':
        ensure => running,   #是否开启服务
        enable => true,    #开机自启动
        hasrestart => true,  #是否有重启命令
        restart => "service nginx restart",    #设置重启命令
        require => Package['nginx'],         #开启服务依赖于package资源,只有先安装软件包才能启动服务
}
package{'nginx':
        ensure => latest,
}

5、file资源

管理文件,既能复制文件又能指定文件类型

类型一、文件
cat file.pp  
file{'/etc/nginx/nginx.conf':
        ensure => file,              #文件类型
        source => '/app/nginx.conf',     #要复制的原文件
        path => '/etc/nginx/nginx.conf',   #目标路径,与title重复,所以此处可以省略
        owner => root,
        group => root,
        mode => 0644,
}
#我们将nginx的配置文件监听端口修改为其他值如90,配置文件修改了,应该重启nginx服务,这部分后面会介绍
#以上实现复制文件的方法,下面进行目录的配置实现

类型二、目录
cat directory.pp  
file{'yum.repos.d':
        ensure => directory,
        path => '/tmp/yum.repos.d/',
        source => '/etc/yum.repos.d/',   #在/tmp下创建目录yum.repos.d,但是此目录下的文件是不会一并复制过来的
        recurse => true,          #所以需要使用递归参数recurse,将目录中的文件、子目录全复制到path指定路径下
}
#如果将文件复制到目录中,即source是文件而path是目录而且ensure也指定目录,最终复制是有问题的
#上述两个例子都是复制文件和目录,如果创建文件或目录则使用ensure指定present即可

类型三、符号链接

cat link.pp  
file{'/tmp/yum.d':            #本示例未使用path,则title充当目标路径,即在tmp目录下创建的文件为yum.d
        ensure => link,     #符号链接,创建的yum.d文件为软链接
        target => '/etc/nginx/nginx.conf',   #软链接文件指向的原始文件
}
#path或者title指定的是将要创建的对象,不论是文件还是目录
#符号链接文件的权限、属主、属组可以不用考虑


订阅和通知关系,下面通过综合示例说明订阅与通知关系

cat package.pp  
package{'nginx':
        ensure => latest,
        name => 'nginx',
}
#首先,安装软件包
file{'nginx.conf':
        ensure => file,
        path => '/etc/nginx/nginx.conf',
        source => '/app/nginx.conf',
        owner => 'root',
        group => 'root',
        mode => 0644,
        require => Package['nginx'],   #file资源依赖于package资源
        notify => Service['nginx'],    #当此配置文件修改时就会通知service资源,触发service的动作
}
#编辑配置文件,将修改后的文件通过file资源复制到目标
service{'nginx':
        ensure => running,
        name => 'nginx',
        hasrestart => true,
        restart => 'systemctl restart nginx',
        #subscribe => File['nginx.conf'],        #此资源订阅file资源,即file资源有改动此资源就会被通知并采取行动
}
#由于notify与subscribe都能感知变动并立即通知,所以二者的功能是重合的,只是放置的位置不同,因此只是用其中一个
#下述示例与本示例效果一样
package{'nginx':
        ensure => latest,
        name => 'nginx',
} ->    #此方法表示package资源先于file资源

file{'nginx.conf':
        ensure => file,
        path => '/etc/nginx/nginx.conf',
        source => '/app/nginx.conf',
        owner => 'root',
        group => 'root',
        mode => 0644,
} ~>    #此方法表示file资源通知service资源或者service资源订阅file资源

service{'nginx':
        ensure => running,
        name => 'nginx',
        hasrestart => true,
        restart => 'systemctl restart nginx',
}
#本例与上例效果都是一样的,此外还有第三种方法能够达到同样的效果
package{'nginx':
        ensure => latest,
        name => 'nginx',
} 

file{'nginx.conf':
        ensure => file,
        path => '/etc/nginx/nginx.conf',
        source => '/app/nginx.conf',
        owner => 'root',
        group => 'root',
        mode => 0644,
} 

service{'nginx':
        ensure => running,
        name => 'nginx',
        hasrestart => true,
        restart => 'systemctl restart nginx',
}

Package['nginx'] -> File['nginx.conf'] ~> Service['nginx']
#单独一处,定义依赖及通知关系

6、exec资源

类似于ansible中的shell

cat exec.pp  
exec{'mkdir':
        command => 'mkdir /tmp/test',          #执行的命令,创建目录
        path => '/bin:/sbin:/usr/bin:/usr/sbin',     #PATH变量的路径
        creates => '/tmp/test',              #如果此处的文件存在就不会执行command,否则执行
}
#本例中,creates只是在创建文件、目录时生效,如果是用户类命令则还需要其他参数

cat exec2.pp  
exec{'useradd':
        command => 'useradd user2',
        path => '/bin:/sbin:/usr/bin:/usr/sbin',
        unless => 'id user2',          #unless表示本命令执行失败才会执行command,即没有user2用户本命令才会执行失败
}
#unless表示除非,其为假才会执行command
#onlyif表示只有,其为真才会执行command

试想下,我们复制nginx的配置文件时,想将原文件做个备份,而不是向file复制那样直接覆盖,这样该怎么做
我们使用exec资源的refreshonly参数实现

cat exec3.pp  
file{'nginx.conf':
        ensure => file,
        source => '/app/nginx.conf',
        path => '/etc/nginx/nginx.conf'
}

exec{'backupfile':
        command => 'cp /etc/nginx/nginx.conf /tmp/nginx.conf.bak',
        path => ['/bin','/sbin','/usr/bin','/usr/sbin'],
        refreshonly => true,                #关键步骤,刷新功能启动
        subscribe => File['nginx.conf'],
}
#订阅参数指定依赖的资源,所以当file资源改变时触发exec资源
#此例实现配置文件修改,然后将原文件备份

7、cron资源

计划任务

cat cron.pp  
cron{'timesync':
        command => 'ntpdate 172.18.0.1 &> /dev/null',
        ensure => present,    #创建计划任务
        minute => '*/3',
        user => root,
}
#每3分钟以root的身份执行一次同步时间操作
crontab -l   #查看效果

8、notify资源

发送提示信息



结束