类是 puppet 中命名的代码模块,常用于定义一组通用目标的资源,可在 puppet 全局调用;
类可以被继承,也可以包含子类;
具体定义的语法如下:
- class NAME{
- ... puppet code ...
- }
其中,在我们定义的时候,需要注意的是:
下面,我们来看一个简单的例子:
- vim class1.pp class redis {#定义一个类package {
- 'redis': ensure = >installed,
- } - >
- file {
- '/etc/redis.conf': ensure = >file,
- source = >'/root/manifests/file/redis.conf',
- owner = >'redis',
- group = >'root',
- mode = >'0640',
- tag = >'redisconf'
- }~ >
- service {
- 'redis': ensure = >running,
- enable = >true,
- hasrestart = >true,
- hasstatus = >true
- }
- }
- include redis#调用类
注意:类只有被调用才会执行。include 后可以跟多个类,直接用 "," 隔开即可。
我们定义的类也可以进行参数设置,可以进行参数的传递。
具体语法如下所示:
- class NAME(parameter1, parameter2) { #注意,大括号前有一个空格
- ...puppet code...
- }
我们来看一个例子:
- vim class2.pp
- class instpkg($pkg) {
- package{"$pkg":
- ensure => installed,
- }
- }
- class{"instpkg": #给参数传入值
- pkg => 'memcached',
- }
注意:单个主机上不能被直接声明两次。
如果对应的参数未传值的话,执行会报错。
但是我们可以在定义形参的时候,设定一个默认值,这样的话,我们不传入值的话,就会自动调用默认值:
- vim class3.pp
- class instpkg($pkg='wget') {
- package{"$pkg":
- ensure => installed,
- }
- }
- include instpkg
这样的话,我们直接使用 include 调用即可,就不需要给参数传入值了。
由上,我们可以总结出,调用类的方式有两种:
- 1. include CLASS_NAME1, CLASS_NAME2, ...
- 2. class{'CLASS_NAME':
- attribute => value,
- }
我们来看一个比较全面的例子:
首先,判断我们系统的版本,是 6 还是 7,由此来确定,是安装 mysql 还是 mariadb,同时,使用调用参数的方式来实现如上需求。
具体实现的代码如下:
- vim dbserver.pp class dbserver($dbpkg = 'mariadb-server', $svc = 'mariadb') {#定义类并给参数赋值package {
- "$dbpkg": ensure = >installed,
- }
- service {
- "$svc": ensure = >running,
- enable = >true,
- hasrestart = >true,
- hasstatus = >true,
- }
- }
- if $operatingsystem == 'CentOS' {
- if $operatingsystemmajrelease == '7' {
- include dbserver#直接调用类
- } else {
- class {
- "dbserver": #调用类并对参数重新赋值dbpkg = >'mysql-server',
- svc = >'mysqld'
- }
- }
- }
类似于其它编程语言中的类的功能,puppet 的 Class 可以被继承,也可以包含子类。
其定义的语法如下:
- class SUB_CLASS_NAME inherits PARENT_CLASS_NAME {
- ...puppet code...
- }
下面我们来看一个例子:
- vim class4.pp
- class redis { #定义class类
- package{'redis':
- ensure => installed,
- }
- service{'redis':
- ensure => running,
- enable => true,
- }
- }
- class redis::master inherits redis { #调用父类
- file {'/etc/redis.conf':
- ensure => file,
- source => '/root/manifests/file/redis-master.conf',
- owner => 'redis',
- group => 'root',
- }
- Service['redis'] { #定义依赖关系
- subscribe => File['/etc/redis.conf']
- }
- }
- class redis::slave inherits redis { #调用父类
- file {'/etc/redis.conf':
- ensure => file,
- source => '/root/manifests/file/redis-slave.conf',
- owner => 'redis',
- group => 'root',
- }
- Service['redis'] { #定义依赖关系
- subscribe => File['/etc/redis.conf']
- }
- }
一样的,我们的类在调用的时候,可以实现修改原有值和额外新增属性的功能。
我们的继承父类的时候,可以定义一些父类原本没有的属性:
在继承的类中,我们可以在属性原有值的基础上,使用 +> 进行新增修改:
在继承的类中,我们可以直接把原有的值进行覆盖修改,使用 => 进行覆盖即可:
在继承的类中,我们还可以在整体调用的基础上,根据不同的需求,把父类中的部分值进行重写修改:
模板通常以 erb 结尾。模板均使用 erb 语法。
关于 puppet 兼容的 erb 语法,我们可以去官方文档查看,下面附上官方文档地址: https://docs.puppet.com/puppet/latest/reference/lang_template_erb.html
以下,附上部分重要内容:
- <%= EXPRESSION %> — 插入表达式的值,进行变量替换
- <% CODE %> — 执行代码,但不插入值
- <%# COMMENT %> — 插入注释
- <%% or %%> — 插入%
接着我们来看一个实例:
我们使用 puppet 模板来实现,将 redis 监听端口修改为本机的 ip 地址。
首先,我们先来定义一个 file.pp 文件,在该文件中调用我们的模板:
- vim file.pp
- file{'/tmp/redis.conf': #仅用于测试模板是否生效,所以放在tmp目录下
- ensure => file,
- content => template('/root/manifests/file/redis.conf.erb'), #调用模板文件
- owner => 'redis',
- group => 'root',
- mode => '0640',
- }
接着,我们去修改配置文件的源,也就是我们的模板文件:
- vim file/redis.conf.erb
- bind 127.0.0.1 <%= @ipaddress_eth0 %> #修改监听端口
修改完成以后,我们就可以执行查看结果了:
- puppet apply - v file.pp
然后,我们去查看一下 / tmp/redis.conf 文件:
- vim / tmp / redis.conf
可以看出,我们的变量替换已经成功。
实践中,一般需要把 manifest 文件分解成易于理解的结构,例如将类文件、配置文件甚至包括后面将提到的模块文件等分类存放,并且通过某种机制在必要时将它们整合起来。
这种机制即模块,它有助于以结构化、层次化的方式使用 puppet,而 puppet 则基于 "模块自动装载器"。
从另一个角度来说,模块实际上就是一个按约定的、预定义的结构存放了多个文件或子目录的目录,目录里的这些文件或子目录必须遵循其命名规范。
模块的目录格式如下:
其中,每个文件夹中存放的内容及其要求如下:
;
- puppet:///modules/MODULE_NAME/FILE_NAME
;
- tempate('MOD_NAME/TEMPLATE_FILE_NAME')
下面我们就来看一个实例来具体的了解应该如何定义一个模块:
1)我们先来创建对应的目录格式:
- [root@master ~]# mkdir modules
- [root@master ~]# cd modoules/
- [root@master modules]# ls
- [root@master modules]# mkdir -pv redis/{manifests,files,templates,tests,lib,spec}
- mkdir: created directory 'redis'
- mkdir: created directory 'redis/manifests'
- mkdir: created directory 'redis/files'
- mkdir: created directory 'redis/templates'
- mkdir: created directory 'redis/tests'
- mkdir: created directory 'redis/lib'
- mkdir: created directory 'redis/spec'
2)目录格式创建完成之后,我们就可以来创建对应的父类子类文件了。
首先,我们来创建父类文件:
- [root@master modules]# cd redis/
- [root@master redis]# vim manifests/init.pp
- class redis {
- package{'redis':
- ensure => installed,
- } ->
- service{'redis':
- ensure => running,
- enable => true,
- hasrestart => true,
- hasstatus => true,
- require => Package['redis'],
- }
- }
创建完成后,我们再来创建对应的子类文件:
- [root@master redis]# vim manifests/master.pp
- class redis::master inherits redis {
- file {'/etc/redis.conf':
- ensure => file,
- source => 'puppet:///modules/redis/redis-master.conf',
- owner => 'redis',
- group => 'root',
- mode => '0640',
- }
- Package['redis'] -> File['/etc/redis.conf'] ~> Service['redis']
- }
- [root@master redis]# vim manifests/slave.pp
- class redis::slave($master_ip,$master_port='6379') inherits redis {
- file {'/etc/redis.conf':
- ensure => file,
- content => template('redis/redis-slave.conf.erb'),
- owner => 'redis',
- group => 'root',
- mode => '0640',
- }
- Package['redis'] -> File['/etc/redis.conf'] ~> Service['redis']
- }
3)准备文件:
现在我们需要把模板文件准备好,放入我们的 templates 目录下:
- scp redis.conf.erb / root / modules / redis / templates / redis - slave.conf.erb
还有我们的静态文件,也要放入我们的 files 目录下:
- scp redis.conf / root / modules / redis / files / redis - master.conf
4)查看目录结构,确定我们是否都已准备完成:
- [root@master modules]# tree
- .
- └── redis
- ├── files
- │ └── redis-master.conf
- ├── lib
- ├── manifests
- │ ├── init.pp
- │ ├── master.pp
- │ └── slave.pp
- ├── spec
- ├── templates
- │ └── redis-slave.conf.erb
- └── tests
- 7 directories, 5 files
5)现在就可以把我们的准备好的模块放入系统的模块目录下:
- [root@master mdoules]#cp - rp redis / /etc/puppet / modules /
注意,模块是不能直接被调用的,只有放在 / etc/puppet/modules 下,或
目录下,使其生效才可以被调用。 我们可以来查看一下我们的模块到底有哪些:
- /usr/share/puppet/modules
- [root@master mdoules]# puppet module list
- /etc/puppet/modules
- └── redis (???)
- /usr/share/puppet/modules (no modules installed)
可以看出,我们的模块已经定义好了,现在我们就可以直接调用了。
6)调用模块
我们可以直接命令行传入参数来调用我们准备好的模块:
- [root@master modules]#puppet apply - v--noop - e "class{'redis::slave': master_ip => '192.168.37.100'}"#如果有多个参数,直接以逗号隔开即可
也可以把我们的调用的类赋值在. pp 文件中,然后运行该文件。
- [root@master ~]# cd manifests/
- [root@master manifests]# vim redis2.pp
- class{'redis::slave':
- master_ip => '192.168.37.100',
- }
- [root@master manifests]# puppet apply -e --noop redis2.pp
以上。实验完成。
注意,以上实验是我们在单机模式下进行的,如果是要在 master/agent 模式下进行,步骤还会略有不同。
master/agent 模型时通过主机名进行通信的,下面,就来看看 master-agent 模式的 puppet 运维自动化如何实现:
1)下载包
master 端:puppet.noarch,
- puppet-server.noarch
2)主机名解析
为了方便我们后期的操作,我们可以通过定义 / etc/hosts 文件实现主机名的解析。如果机器很多的话,可以使用 DNS 进行解析。
- [root@master ~]# vim /etc/hosts
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 192.168.37.111 master.keer.com
- 192.168.37.122 server1.keer.com
注意,该操作需要在每一台主机上进行。
修改完成以后,我们可以来测试一下是否已经成功:
- [root@master~]#ping server1.keer.com
3)时间同步
- [root@master~]#systemctl start chronyd.service
所有机器上都开启 chronyd.service 服务来进行时间同步
开启过后可以查看一下状态:
- [root@master~]#systemctl status chronyd.service
我们可以使用 chronyc sources 命令来查看时间源:
1)手动前台开启,观察服务开启过程:
- puppet master - v--no - daemonize#前台运行
2)直接 systemctl 开启服务,监听在 8140 端口。
1)在配置文件中指明 server 端的主机名:
- [root@server1 ~]# vim /etc/puppet/puppet.conf
- server = master.keer.com
接着,我们可以通过 puppet config print 命令来打印输出我们配置的参数:
- [root@server1 ~]# puppet config print 显示配置文件中的配置参数
- [root@server1 ~]# puppet config print --section=main 显示main 段的配置参数
- [root@server1 ~]# puppet config print --section=agent 显示agent 段的配置参数
- [root@server1 ~]# puppet config print server 显示server 的配置参数
2)开启 agent 服务
我们可以发现,他会一直卡在这里等待 CA 颁发证书。
3)在 master 端签署证书
- [root@master ~]# puppet cert list
- "server1.keer.com" (SHA256) B5:67:51:30:5C:FB:45:BA:7A:73:D5:C5:87:D4:E3:1C:D7:02:BE:DD:CC:7A:E2:F0:28:34:87:86:EF:E7:1D:E4
- [root@master ~]# puppet cert sign server1.keer.com #颁发证书
- Notice: Signed certificate request for server1.keer.com
- Notice: Removing file Puppet::SSL::CertificateRequest server1.keer.com at '/var/lib/puppet/ssl/ca/requests/server1.keer.com.pem'
master 端管理证书部署的命令语法如下:
puppet cert[–all|-a] [ ]
action:
list 列出证书请求
sign 签署证书
revoke 吊销证书
clean 吊销指定的客户端的证书,并删除与其相关的所有文件;
注意:某 agent 证书手工吊销后重新生成一次;
On master host:
puppet cert revoke NODE_NAME
puppet cert clean NODE_NAME
On agent host:
重新生成的主机系统,直接启动 agent;
变换私钥,建议先清理 / var/lib/puppet/ssl / 目录下的文件
4)终止服务开启,再次开启
- [root@server1~]#puppet agent - v--noop--no - daemonize
1)设置站点清单
① 查询站点清单应存放的目录,(可以修改,去配置文件修改)
- [root@master~]#puppet config print | grep manifest
- [root@master ~]# cd /etc/puppet/manifests/
- [root@master manifests]# vim site.pp
- node 'server1.along.com' {
- include redis::master
- }
分析:就是简单的调用模块,只有模块提前定义好就可以直接调用;我调用的是上边的 redis 模块
2)给 puppet 用户授权
因为 agent 端要来 master 端读取配置,身份是 puppet
- [root@master manifests]# chown -R puppet /etc/puppet/modules/redis/*
3)[root@server1 ~]# puppet agent -v --noop --no-daemonize 手动前台开启 agent 端服务
(4)直接开启服务,agent 会自动去 master 端获取配置
[root@server1 ~]# systemctl start puppetagent 包已下载,服务也开启了
机器名称 | IP 配置 | 服务角色 |
---|---|---|
puppet-master | 192.168.37.111 | puppet 的 master |
puppet-server1-master-redis | 192.168.37.122 | puppet 的 agent,redis 的 master |
puppet-server2-slave-redis | 192.168.37.133 | puppet 的 agent,redis 的 slave |
1)下载包
master 端:puppet.noarch,
agent 端:puppet.noarch
- puppet-server.noarch
2)主机名解析
为了方便我们后期的操作,我们可以通过定义 / etc/hosts 文件实现主机名的解析。如果机器很多的话,可以使用 DNS 进行解析。
- [root@master ~]# vim /etc/hosts
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 192.168.37.111 master.keer.com
- 192.168.37.122 server1.keer.com
- 192.168.37.133 server2.keer.com
注意,该操作需要在每一台主机上进行。
修改完成以后,我们可以来测试一下是否已经成功:
- [root@master~]#ping server1.keer.com
3)时间同步
- [root@master~]#systemctl start chronyd.service
三台机器上都开启 chronyd.service 服务来进行时间同步
开启过后可以查看一下状态:
- [root@master~]#systemctl status chronyd.service
我们可以使用 chronyc sources 命令来查看时间源:
(1)开启服务
- [root@master ~]# systemctl start puppetmaster
- [root@server1 ~]# systemctl start puppetagent
- [root@server2 ~]# systemctl start puppetagent
因为 server2 是第一次连接,需 master 端签署证书
(2)master 签署颁发证书
- [root@master manifests]# puppet cert list
- [root@master ~]# puppet cert sign server2.keer.com
- [root@master manifests]# cd /etc/puppet/manifests
- [root@master manifests]# vim site.pp 直接调上边完成的模块
- node 'server1.keer.com' {
- include redis::master
- }
- node 'server2.keer.com' {
- class{'redis::slave':
- master_ip => 'server1.keer.com'
- }
- }
- [root@server2~]#vim / etc / redis.conf
- [root@server2~]#redis - cli - a keerya info Replication
(1) 创建一个 chrony 模块,前准备
- [root@master ~]# cd modules/ 进入模块工作目录
- [root@master modules]# mkdir chrony 创建chrony 的模块
- [root@master modules]# mkdir chrony/{manifests,files} -pv 创建模块结构
(2)配置 chrony 模块
- [root@master modules]# cd chrony/
- [root@master chrony]# cp /etc/chrony.conf files/
- [root@master puppet]# vim files/chrony.conf
- # test #用于测试实验结果
- [root@master chrony]#vim manifests / init.pp class chrony {
- package {
- 'chrony': ensure = >installed
- } - >
- file {
- '/etc/chrony.conf': ensure = >file,
- source = >'puppet:///modules/chrony.conf',
- owner = >'root',
- group = >'root',
- mode = >'0644'
- }~ >
- service {
- 'chronyd': ensure = >running,
- enable = >true,
- hasrestart = >true,
- hasstatus = >true
- }
- }
(3)puppet 添加这个模块,并生效
- [root@master modules]# cp -rp chrony/ /etc/puppet/modules/
- [root@master modules]# puppet module list
- [root@master ~]# cd /etc/puppet/manifests/
- [root@master manifests]# vim site.pp
- node 'base' {
- include chrony
- }
- node 'server1.keer.com' inherits 'base' {
- include redis::master
- }
- node 'server2.keer.com' inherits 'base' {
- class{'redis::slave':
- master_ip => 'server1.keer.com'
- }
- }
- #node /cache[1-7]+\.keer\.com/ { #可以用正则匹配多个服务器使用模块
- # include varnish
- #}
我们现在直接去 server2 机器上,查看我们的配置文件是否已经生效,是否是我们添加过一行的内容:
- [root@server2~]#vim / etc / chrony.conf
发现我们的实验成功。
来源: http://www.cnblogs.com/keerya/p/8087675.html