设为首页 收藏本站
查看: 4317|回复: 1

[经验分享] 学习puppet不得不掌握的基础知识

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-6-15 10:27:31 | 显示全部楼层 |阅读模式
目录
1、puppet简介
2、puppet工作原理
3、puppet的安装
4、puppet常用资源类型
5、puppet的表达式与条件判断语句
6、puppet类
7、puppet模块
8、总结
1、puppet简介
     puppet是一个为实现数据中心自动化管理而设计的配置管理软件,能够管理IT基础设施的整个生命周期:供应(provisioning)配置(configuration)、联动(orchestration)及报告(reporting)。puppet基于C/S架构,类似于zabbiz,有master与agent节点之分。它是一个开源的(谈不上真正的开源,因为有商业版与社区版之分)、新一代的、集中化的配置管理工具,由ruby语言研发,它拥有自己的配置语言(PCL,puppet configuration language)。
    puppet能够把IT日常的系统管理代码化,而代码可重用,这样可以减少运维人员的工作量,而且能快速、大规模部署服务器。在puppet的世界有其自己的哲学思想:在IT系统管理中,puppet只关注结果,不关心过程!这名话怎样理解,比如puppet的master端向各agent下达把nginx这个包安装上并启动服务,puppet的agent端面只向master端报告软件是否安装完成,服务是否已启动,puppet不关心软件是怎样安装上的,服务是怎样启动的,它只关心结果。
2、puppet工作原理
2.1、puppet两种工作方式介绍   
    puppet有两种工作方式,一种是独立工作方式(standalon),另一种是master-agent的方式 。以两张图片来说明这两种工作方式。
wKioL1V6pWuz2Sb9AAFI5bxlT_4074.jpg
(图一:puppet以standalone方式工作流程示意图,图片来自网络)
图片中各术语解释:
manifest:字面意思是清单,在这里指被puppet代码化的各种资源,是一种用PCL编写的代码;
catalog:表示把各种manifest编译后生成的可执行代码,也叫伪代码;
apply:生成catalog后puppet就可以把代码进行运用,在运用时也要先对伪代码进行检测,检测后才执行。
wKiom1V6o9_QsxE-AAGI7fvKL08166.jpg
(图二:puppet的master-agent工作流程图,图片来自网络)
简述:
a)、agent向主机请求catalog代码,在请求时要带上自己的主机名与facts,facts里包含了agent服务器自身的一些系统特征,比如操作系统是什么,是哪个版本,cpu是什么型号,内存有多大等信息;
b)、master接收到agent的请求后开始查询此节点包含的清单,把这些资源找出后编译成catalog,再发送给agent;
c)、agent收到catalog后就开始应用代码,并把执行的状态结果生成报告返还给master;
d)、master接收报告并记录日志。
2.2、puppet的认证机制简介
     puppet有其自己的证书管理机制,agent与master间的通信是需要得到master的认证,证书存放在/var/lib/puppet/ssl/。
在master/agent首次启用的过程:
a)、master启动时会为自己生成key,并签署证书,让自己成为一个ca;
b)、agent首次启动要为自己生成key,生成证书签署请求,并将证书请求发送给master请求签署;
c)、master收到agent的证书签署请求后,由管理员先验证请求是否合法,而后对证书签署请求作出签署或不签署。
3、puppet的安装

    puppet既然是C/S架构,那安装包就有master安装包与agent安装包之分。以下的安装及测试都是基于CentOS 6.4_x86_64的系统进行,在epel源也包含了puppet的软件包,所以我以yum安装为例。并且下边代码的测试都以standalone的工作方式运行。
1
[iyunv@nod2 ~]# yum -y install puppet-server puppet



#puppet-server是master端所需要安装包,而puppet是agent,在安装过程中会安装许多ruby包依赖的包,并且还会自动安装好facter相关包。
1
2
[iyunv@nod2 ~]# puppet -V  #epel源中是2.7.26的版本
2.7.26



puppet基础命令:
1
2
3
4
5
6
[iyunv@php ~]# puppet help  #获取puppet的帮助命令
[iyunv@php ~]# puppet  man parser  #表示获取parser子命令的帮助信息
[iyunv@php ~]# puppet parser validate init.pp #验证init.pp文件的语法是否正确
[iyunv@php ~]# puppet describe -l   #获取支持的资源类型命令,最后接上参数“-l”是L的小写
[iyunv@php ~]# puppet describe user   #查看特定资源类型的详细信息,这里查看user这个资源类型的详细信息。
[iyunv@php ~]# puppet apply *.pp   #表示对一个资源清单进行运用,“*.pp”表示一个具体的资源清单文件。



4、puppet常用资源类型

    在介绍资源类型前先来看下怎样定义一个资源,即定义一个资源的语法。

语法格式:
1
2
3
4
type {'title':
       attribute => value,
       .......
}



解释:type表示具体的一个资源类型,必须为小写,title可以单引号或双引号,双引号可实现变量替换,后边有一个冒号,这样由许多资源定义成的文件就是一个puppet的manifest,这些文件都是以“.pp”结尾。
定义资源时要注意:
a)、同一类型中,资源名称必须唯一,默认时就是“title”
b)、资源名称是否区分大小写是根据操作系统本身
4.1、puppet常用的资源类型介绍
notify:表示发送一个消息
例如:
1
2
3
4
5
6
7
8
[iyunv@nod2 puppet]# vim notify.pp
notify {'message':
    message => "hello.",
}
[iyunv@nod2 puppet]# puppet apply notify.pp
notice: hello.
notice: /Stage[main]//Notify[message]/message: defined 'message' as 'hello.'
notice: Finished catalog run in 0.08 seconds



package:这是一个关于软件包管理的类型
可以用“puppet describe package”查看详细的说明文档,常用的参数为:
ensure:常用值如下
        present(也叫installed),表示一定要安装指定的软件包;
        absent,表示一定不要安装指定的软件包
        latest,表示安装的软件包是最新版本
name:指定软件包名,但一般会省略,直接引用“title”作为软件包名
source:指定软件包的路径,可以是本地路径,也可以是网络路径,注:这些包是在agent上的,并且需要provider指定包的类型
provider:当安装指定的软件时需要指定其类型,比如rpm。
file:文件管理的资源类型

常用参数如下:
content:直接生成文件的内容
ensure:常用值如下:
        present:表示文件必须存在
        absent:表示文件一定不能存在
        file:表示存在的一定是一个文件
        directory:表示存在的一定是个目录
        link:表示创建的是一个链接文件,用link时需要用target参数来指定链接文件的源文件路径
source:指定URL下载文件至目标位置
target:当ensure指定为link时,指定符号链接的目标
owner:指定文件的属主
group:指定文件的属组
mode:指定文件权限
path:指定文件路径,如果在title里指定的全路径,那path省略
force:强制删除,与“ensure => absent”时使用
purge:修剪、清理,清除指定目录中存在但在puppet中未定义的文件
replace:是否替换已经存在的文件
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[iyunv@nod2 puppet]# vim file.pp
file {'file.text':
    ensure => present,
    content => "hello file.\n",
    path   =>  '/tmp/file.text',
    mode   => '0600',
    owner  => root,
    group  => root,
}
[iyunv@nod2 puppet]# puppet apply file.pp
notice: /Stage[main]//File[file.text]/ensure: created
notice: Finished catalog run in 0.05 seconds
[iyunv@nod2 puppet]# cat /tmp/file.text
hello file.
[iyunv@nod2 puppet]# ll /tmp/file.text
-rw-------. 1 root root 12 Jun 11 09:25 /tmp/file.text



service:用于管理系统服务的资源类型
ensure:指定service的状态,此参数的取值如下:
        true或running:指定服务的状态是启动的
        false或stopped:指定服务的状态是关闭的
enable:指定此服务开机是否自动启动,有如下值:
        true:表示此服务开机自动启动
        false:表示此服务开机不自动启动
name:指定服务名称,可省略,直接引用“title”
path:指定服务脚本路径,如果是在系统默认的路径可省略,如在centos系统上的/etc/rc.d/init.d/下的脚本
restart:指定restart此服务时,执行的指令,在生产环境一般是替换成reload操作
exec:可远程执行命令的资源类型
此属性用于在各agent节点执行系统命令,但只是限于不得不需要使用命令才能完成的工作时才这样使用,这不是puppet的强项,可以用absible来代替。
常用参数有:
command:指定要执行的命令的完全路径
path:指定命令搜索路径,多个路径用冒号隔开,类似于PATH环境
user:命令以哪个用户身份运行
group:命令以哪个组身份运行
refresh:默认为收到所依赖的资源的事件时会重新执行此命令,但refresh可以修改此默认执行此命令的动作,而去运行其他的命令或操作
refreshonly:指定此exec资源不会自动被执行,除非被依赖的资源发生改变
returns:指定状态返回值
tries:指定运行命令尝试的次数
例如:
1
2
3
4
5
6
7
8
9
10
11
[iyunv@nod2 puppet]# vim exec.pp
exec {'date':
    command => '/bin/date > /tmp/date.txt',
    user    => root,
    group   => root,
}
[iyunv@nod2 puppet]# puppet apply exec.pp
notice: /Stage[main]//Exec[date]/returns: executed successfully
notice: Finished catalog run in 0.11 seconds
[iyunv@nod2 puppet]# cat /tmp/date.txt
Thu Jun 11 10:00:39 CST 2015



group:组管理的资源类型

此类型用于管系统组,常用参数:
ensure:表示对组管理的目标状态,有两个值
     present:表示一定得有这个组
     absent:表示一定不能有这个组
name:表示指定的组名
gid:表示组的GID号
system:表示这个组是否为系统组,取值为
     true:表示为系统组
     false:表示为非系统组

user:用户管理的资源类型
此类型用于管理用户,常用参数:
ensure:表示对用户管理的目标状态,常用值
        present:表示一定得有这个用户
        absent:表示一定不能有这个用户
name:表示指定的用户名
gid:表示组的UID号
system:表示这个用户是否为系统用户,取值为
         true:表示为系统用户
         false:表示为非系统用户
gid:用户所属的基本组
groups:用户所属的附加组
home:用户的家目录路径,并不代表会被创建
managehome:当指定home后,需要此参数为控制是否真正创建家目录,有两个值
         true:表示创建家目录
         false:表示不创建家目录,这是默认值
password:指定用户的密码,是加密后的密码串
shell:指定用户的shell
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[iyunv@nod2 puppet]# vim user.pp
group {'testuser':
    ensure  => present,
    gid     => 555,
}
user {'testuser':
    ensure   => present,
    gid      => 555,
    uid      => 555,
    home     => '/home/testuser',
    managehome => true,
    shell    => '/bin/bash',
}
[iyunv@nod2 puppet]# puppet apply user.pp
notice: /Stage[main]//Group[testuser]/ensure: created
notice: /Stage[main]//User[testuser]/ensure: created
notice: Finished catalog run in 0.32 seconds
[iyunv@nod2 puppet]# id testuser
uid=555(testuser) gid=555(testuser) groups=555(testuser)
[iyunv@nod2 puppet]# ls /home/
testuser



cron:任务计划管理资源类型
ensure:表示cron是否得存在,值有两个
         present:表示有这个cron
         absent:表示不能有这个cron
command:周期性执行的命令
environment:设置环境变量
hour:小时
minute:分钟
month:月
monthday:一个月中的哪一天,取值为1-31
weekday:星期
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[iyunv@nod2 puppet]# vim cron.pp
cron {'ntpdate':
        ensure  => present,
        command => 'ntpdate time.nist.gov',
        environment => 'PATH=/bin:/usr/bin:/usr/sbin',
        minute  => '*/5',
        user    => root,
}
[iyunv@nod2 puppet]# puppet apply cron.pp
notice: Finished catalog run in 0.04 seconds
[iyunv@nod2 puppet]# crontab -l
# HEADER: This file was autogenerated at Fri Jun 12 16:19:29 +0800 2015 by puppet.
# HEADER: While it can still be managed manually, it is definitely not recommended.
# HEADER: Note particularly that the comments starting with 'Puppet Name' should
# HEADER: not be deleted, as doing so could cause duplicate cron jobs.
# Puppet Name: ntpdate
PATH=/bin:/usr/bin:/usr/sbin
*/5 * * * * ntpdate time.nist.gov



对资源类型的小结:
    puppet的资源类型有几十种,根据版本的不同数量可能不同,但常用的资源类型会涉及到对用户、组、文件、软件包、服务这些资源的管理,可以用“puppet describe resoure_type”来查看其支持的参数,通过上边对常用资源类型的介绍,发现每个资源类型里都会有一个“ensure”参数,而根据资源类型的不同其取值也不尽相同。
4.2、资源类型中特殊参数
    资源类型中有几个比较特殊的参数,叫元参数。元参数是用来定义资源间的相关性、依赖性,既然是参数,那元参数的也有值,它的值是其它资源或资源数组,这也称为资源引用。
资源引用有其固定的语法:“Type['title']”,资源类型的第一个字母必须大写,“title”表示资源的名称。
元参数有四个:before、require、notify和subscrible。
before  => Type['title']  :表示before所在资源必须执行完成后,Type['title']这个资源才能执行,即该资源先于Type['title']资源执行,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[iyunv@nod2 puppet]# vim user.pp
group {'testuser':
    ensure  => present,
    gid     => 555,
    before  => User['testuser'],
}
user {'testuser':
    ensure   => present,
    gid      => 555,
    uid      => 555,
    home     => '/home/testuser',
    managehome => true,
    shell    => '/bin/bash',
}



#这里就表示group这个资源必须执行完成后,“User['testuser']”这个资源才能执行。创建用户时是需要先创建组,再创建用户。
require  => Type['title'] :与before相对应,表示require所在的资源是依赖于"Type['title']"这个资源,必须等"Type['title']"这个资源执行完成后,require所在的资源才能执行,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[iyunv@nod2 puppet]# vim user.pp
group {'testuser':
    ensure  => present,
    gid     => 555,
}
user {'testuser':
    ensure   => present,
    gid      => 555,
    uid      => 555,
    home     => '/home/testuser',
    managehome => true,
    shell    => '/bin/bash',
    require => Group['testuser'],
}



notify  => Type['title']:表示notify所在的资源发生变化后,就会通知“Type['title']”资源进行相应的操作,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[iyunv@nod2 puppet]# vim nginx.pp
package {'nginx':
    ensure => present,
    before => Service['nginx'],
}
service {'nginx':
    ensure => running,
    enable => true,
    path   => '/etc/rc.d/init.d/nginx',
    restart => 'reload',
}
file {'/etc/nginx/nginx.conf':
    ensure => file,
    source => '/root/nginx.conf',
    owner  => root,
    group  => root,
    mode   => 644,
    notify => Service['nginx'],
}



#这个manifest是进行nginx软件包的安装,软件包安装好后,如果想修改nginx.conf这个配置文件,那我们去修改“/root/nginx.conf”这个配置模板,修改好后,puppet就会在一定时间后去通知把"/root/nginx.conf"这个配置文件拷贝到“/etc/nginx/nginx.conf”进行覆盖,然后再通知"Service['nginx']"去执行“/etc/rc.d/init.d/nginx reload”命令重新载入配置文件。
subscrible => Type['title']:与“notify => Type['title']”相对应,表示subscrible所在的资源依赖于“Type['title']”,它随时关注着“Type['title']”这个资源,一旦“Type['title']”有事件发生,subscrible所在的资源就发生相应的动作,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[iyunv@nod2 puppet]# vim nginx.pp
package {'nginx':
    ensure => present,
    before => Service['nginx'],
}
service {'nginx':
    ensure => running,
    enable => true,
    path   => '/etc/rc.d/init.d/nginx',
    restart => '/etc/rc.d/init.d/nginx reload' ,
    subscrible => File['/etc/nginx/nginx.conf'],
}
file {'/etc/nginx/nginx.conf':
    ensure => file,
    source => '/root/nginx.conf',
    owner  => root,
    group  => root,
    mode   => 644,
}



除了用上before、require、notify和subscrible四个元参数来定义资源间的依赖、通知关系外,还可以用次序链、通知链来定义。
次序链用“->”表示,通知链用“~>”。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[iyunv@nod2 puppet]# vim nginx.pp
package {'nginx':
    ensure => present,
    before => Service['nginx'],
}
service {'nginx':
    ensure => running,
    enable => true,
    path   => '/etc/rc.d/init.d/nginx',
    restart => '/etc/rc.d/init.d/nginx reload',
}
file {'/etc/nginx/nginx.conf':
    ensure => file,
    source => '/root/nginx.conf',
    owner  => root,
    group  => root,
    mode   => 644,
}
Package['nginx'] -> File['/etc/nginx/nginx.conf'] ~> Service['nginx']



#最后定义的次序和通知链表示nginx安装好后就去复制配置文件,配置文件准备好后就通知服务重新载入。
5、puppet的表达式与条件判断语句
5.1、变量及变量类型
在puppet中使用变量有其独特的要求:
a)、变量的赋值与引用都要在前加“$”号,赋值用“=”,支持追加赋值“+=”
b)、变量的引用格式:有简短名和FQN($scope::variable)

puppet有如下三种变量类型:
a)、自定义变量
b)、facter变量,这些变量在manifest中可直接调用
c)、内置变量,分master端内置变量和agent端内置变量

5.2、puppet支持的数据类型
字符型:即字符串,为了养成良好的编程习惯,使用单引号引起,也可不用;双引号可以完成变量替换物。
数值型:可以为整数或浮点数
数组型:格式为“[元素,元素,....]”,元素可以为任意可用数据类型,包括hash或其它数组,数组的引用索引从0开始,也可以使用负数索引引用。
布尔型:true和false,不能加引号
undef:从未被声明的变量的值类型为undef,即此变量值为空,不加引号
hash:键值对数据,格式为{key=>value,key=>value,.....},key为字符型数据,value可以为puppet支持的任意数据类型,引用是以key当索引使用
正则表达式:puppet的非标准数据类型,不能直接赋值给变量
注:在正则表达式中有三个选项,选项“i”表示忽略字符大小写,选项“m”表示把“.”点号当作换行符,选项“x”表示忽略模式中的空间字符和注释,而在puppet中正则有其特定的语法格式,以一个例子说明:
1
2
3
4
$package = $operatingsystem ? {
    /(?i-mx:ubuntu|debian)/   =>  'apache2',
    /(?i-mx:centos|fedora|redhat)/   => 'httpd',
}



#这个资源定义表示判断“$operatingsystem”的值是apahce2还是httpd。
5.3、puppet支持的操作符号
a)、比较操作符
==:等值判断
!=:不等值判断
<:小于
>:大于
<=:小于等于
>=:大于等于
=~:正则匹配判断
!~:正则不匹配判断
in:表示在某一个列表中
b)、布尔操作符
and:且
or   :或
!     :非
c)、算术操作符号
+  :加
-  :减
*   :乘
/   :除
<<  :左移位
>>  :右移位


5.4、puppet的条件判断语句
在puppet中有三种条件判断语句,if,case,selector,在puppet3.0后增加了一个unless。
a)、if判断语句
单分支
1
2
3
4
if  CONDITION {
    statement
     ...
}





双分支
1
2
3
4
5
6
7
8
if CONDITION {
    statement
    ...
}
else {
    statement
    ...
}



多分支
1
2
3
4
5
6
7
8
9
10
11
12
13
if CONDITION {
    statement
    ....
}
elsif CONDITION {
    statement
    ...
}
... ...
else {
    statement
    ...
}



举例:
if多分支举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[iyunv@nod2 puppet]# vim if.pp
if $operatingsystem == 'CentOS' {
    notice("hello CentOS.")
}
elsif $operatingsystem == 'RedHat' {
    notice("hello RedHat.")
}
elsif $operatingsystem == 'Fedora' {
    notice("hello Fedora.")
}
else {
    notice("who are you?")
}
[iyunv@nod2 puppet]# puppet apply if.pp
notice: Scope(Class[main]): hello CentOS.
notice: Finished catalog run in 0.07 seconds



if中配置正则表达式举例:
1
2
3
4
5
6
7
[iyunv@nod2 puppet]# vim reg.pp
if $operatingsystem =~ /^(?i-mx:(centos|redhat))/ {
    notice("hello $1")
}
[iyunv@nod2 puppet]# puppet apply reg.pp
notice: Scope(Class[main]): hello CentOS
notice: Finished catalog run in 0.07 seconds



b)、case判断语句
语法:
1
2
3
4
5
6
case CONTROL_EXPRESS {
    case1,...: {    statement...   }
    case2,...: {    statement...   }
    ... ...
    default:   {   statement...   }
}



CONTROL_EXPRESS表示一个控制表达式,可以为变量、表达式和一个有返回值的函数。
case可以为一个特定的字符串、一个变量、一个有返回值的函数、一个正则表达式。
default表示默认分支
例如:
1
2
3
4
5
6
7
8
9
[iyunv@nod2 puppet]# vim case.pp
case $operatingsystem {
    'CentOS','RedHat':  { notice("hello RedHAt OS Family") }
    /^(?i-mx:(Debian|Ubuntu))$/:{ notice("hello $1") }
    default:            { notice("who are you") }
}
[iyunv@nod2 puppet]# puppet apply case.pp
notice: Scope(Class[main]): hello RedHAt OS Family
notice: Finished catalog run in 0.08 seconds



c)、selector判断语句
只能用于期望出现直接值的地方,包括变量赋值、资源属性、函数参数、资源标题等。
语法:
1
2
3
4
5
6
CONTROL_VARIABLE  ?  {
    case1  => value1,
    case2  => value2,
    ...
    default  => valueN,
}



注意:default必须要有,不然在编译时会出错
举例:
1
2
3
4
5
6
7
8
9
10
11
12
[iyunv@nod2 puppet]# vim selector.pp
$webpackage = $operatingsystem ? {
    /^(?i-mx:(centos|redhat|fedora))$/  => httpd,
    /^(?i-mx:(debian|ubuntu))$/         => apache2,
    default                             => httpd,
}
package {"$webpackage":
    ensure => installed,
}
[iyunv@nod2 puppet]# puppet apply selector.pp
notice: /Stage[main]//Package[httpd]/ensure: created
notice: Finished catalog run in 8.99 seconds



6、puppet类
我给类下的一个定义:类就是把有相关性的,最直接的资源定义代码整合在一起,以实现以“类”为单位的管理,目的是实现代码重用
6.1、类定义的语法:
1
2
3
class   clall_name  {
    ...puppet code...
}



#类的名称只能由小写字母开头,可以包含小写字母、数字和下划线。
6.2、调用类的方法:
a)、include  class_name,class_name,常用此方法
b)、require,不常用
c)、class {'class_name':},像定义资源一样来调用类
6.3、带参数的类的定义:
语法:
1
2
3
4
class class_name ($para1='val1',$para2='val2',..) {
    puppet code
    ......
}



#($para1='val1',$para2='val2',..)中表示资源的默认值,即如果在调用类时没有向其传递参数,那就默认参数。
例如:
1
2
3
4
5
6
class mysql ($user = 'mysql',$port = 3306) {
    ....puppet code....
}
class {'mysql':
    user => mysqluser,
}



例如:
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
[iyunv@nod2 puppet]# vim class.pp
class createuser ($gpname=test,$uname=test) {
        group {"$gpname":
                ensure => present,
        }
        user {"$uname":
                ensure => present,
                gid    => $gpname,
                home   => “/home/$uname”,
                managehome => true,
                shell  => '/bin/bash',
        }
}
class {'createuser':
        gpname => zcj,
        uname  => zcj,
}
[iyunv@nod2 puppet]# puppet apply class.pp
notice: /Stage[main]/Createuser/Group[zcj]/ensure: created
notice: /Stage[main]/Createuser/User[zcj]/ensure: created
notice: Finished catalog run in 0.28 seconds
[iyunv@nod2 puppet]# id zcj
uid=556(zcj) gid=556(zcj) groups=556(zcj)
[iyunv@nod2 puppet]# ls /home/
testuser  zcj



6.4、类的继承
语法:
1
2
3
class BASENAME {
    ...puppet code...
}



#上边定义的这个类对下边的类来说是一个基本类
1
2
3
class BASENAME::CLASSNAME inherits BASENAME {
    ...puppet code....
}



#这个类在第一个基本类的前提下再增加了一个类,即第二个类是继承了第一个类的。第二个类中的“BASENAME”与第一个类中的“BASEDNAME”名称相同,“CLASSNAME”是第二个类的名称。
举例:
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
[iyunv@nod2 puppet]# vim nginx.pp
class nginx {
        package {'nginx':
                ensure => present,
                before => Service['nginx'],
        }
        service {'nginx':
                ensure => running,
                enable => true,
                path   => '/etc/rc.d/init.d/nginx',
                restart => '/etc/rc.d/init.d/nginx reload',
        }
}
class nginx::reloadnginx inherits nginx {
        file {'/etc/nginx/nginx.conf':
                ensure => file,
                source => '/root/nginx.conf',
                owner  => root,
                group  => root,
                mode   => 644,
        }
}
Package['nginx'] -> File['/etc/nginx/nginx.conf'] ~> Service['nginx']
#include nginx::reloadnginx
class {"nginx::reloadnginx":}



在类的继承中有两个问题要注意,如果在子类中定义了与父类相同的资源,那子类中定义的参数将会覆盖父类中定义的参数;如果子类想在父类中已定义的资源上追加一些额外的参数或资源,那用“+>”符号。
举例:
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
[iyunv@nod2 puppet]# vim nginx.pp
  1 class nginx {
  2         package {'nginx':
  3                 ensure => present,
  4                 before => Service['nginx'],
  5         }
  6         service {'nginx':
  7                 ensure => running,
  8                 enable => true,
  9                 path   => '/etc/rc.d/init.d/nginx',
10                 restart => '/etc/rc.d/init.d/nginx reload',
11         }
12 }
13 class nginx::reloadnginx inherits nginx {
14         file {'/etc/nginx/nginx.conf':
15                 ensure => file,
16                 source => '/root/nginx.conf',
17                 owner  => root,
18                 group  => root,
19                 mode   => 644,
20         }
21 }
22 file {'/etc/nginx/conf.d/virtual.conf':
23         ensure => file,
24         source => '/tmp/virtual.conf',
25 }
26
27 class nginx::reloadnginx::virtualhost inherits nginx::reloadnginx {
28         File['/etc/nginx/nginx.conf'] {
29                 require +> File['/etc/nginx/conf.d/virtual.conf'],
30         }
31 }
32 Package['nginx'] -> File['/etc/nginx/nginx.conf'] ~> Service['nginx']
33 #include nginx::reloadnginx
34 class {"nginx::reloadnginx":}
#这个例子中定义多级继承,仔细看27行,资源的追加请看29行。



7、puppet模块
7.1、模块的目录结构及应用举例
在puppet中模块就是一个目录名,此目录下各个规划好的子目录,各个目录存放的文件都有其规定。
模块的目录结构:
Module Name
        manifests
                init.pp
        files
        templates
        lib
        tests
        spec
manifests目录:用于存放清单文件,即以“.pp”结尾的文件,ini.pp文件必须存在,且此文件必须声明一个类,类名与模块名相同。在puppet中manifests下的清单文件的访问格式为:“modulename::[subdirectoryname::]manifestfilename”,这里的"subdirectoryname"是指在manifests目录下所创建的子目录名称,“manifestfilename”是指清单文件名称,但不要加上“.pp”后缀。
files目录:用于存放各种静态文件,访问格式为:puppet:///modules/MODULE_NAME/[SUBDIR_NAME/]FILE_NAME,这里的“SUBDIR_NAME”表示在files目录下自定义创建的目录名称。
templates目录:存放manifests的模板文件,以“.erb”结尾,调用方式为:template('ModuleName/TemplateName'),模板名一样不需要加“.erb”后缀。
lib目录:存放插件目录
tests目录:存放模块使用说明文档目录
spec:存放lib目录下插件的使用说明文档
举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[iyunv@nod2 ~]# mkdir modules
[iyunv@nod2 ~]# cd modules/
[iyunv@nod2 modules]# mkdir -pv nginx/{manifests,files,templates,lib,tests,spec}
[iyunv@nod2 modules]# vim nginx/manifests/init.pp
class nginx {
        package {'nginx':
                ensure => present,
        }
        file {'nginx.conf':
                ensure => file,
                path   => '/etc/nginx/nginx.conf',
                source => 'puppet:///modules/nginx/nginx.conf',
                owner  => root,
                group  => root,
                mode   => 644,
                require => Package['nginx'],
        }
        service {'nginx':
                ensure => running,
                enable => true,
                path   => '/etc/rc.d/init.d/nginx',
                subscribe => File['nginx.conf'],
        }
}



在files目录中要准备好nginx.conf这个配置文件,我这里从之前安装过的nginx的配置文件复制过来
1
[iyunv@nod2 modules]# cp /etc/nginx/nginx.conf nginx/files/



并把nginx.conf配置文件中的"worker_process = 1"修改为“worker_process = 3”。
卸载之前安装过的nginx:
1
2
3
4
[iyunv@nod2 modules]# rpm -e nginx
warning: /etc/nginx/conf.d/virtual.conf saved as /etc/nginx/conf.d/virtual.conf.rpmsave
[iyunv@nod2 modules]# rm -rf /etc/nginx/
[iyunv@nod2 modules]# puppet apply -dv --modulepath=/root/modules -e "include nginx"



#“--modulepath=/root/modules”只指定模块的上级目录,“-e "include nginx"”表示调用的是nginx这个类
运行此命令后出现“notice: Finished catalog run in 26.26 seconds”类似的字样表示运行成功
1
2
3
4
5
6
7
[iyunv@nod2 modules]# ps aux | grep nginx
root      5697  0.0  0.4  96432  2084 ?        Ss   23:35   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     5698  0.0  0.5  96780  2836 ?        S    23:35   0:00 nginx: worker process                  
nginx     5699  0.0  0.5  96780  2836 ?        S    23:35   0:00 nginx: worker process                  
nginx     5700  0.0  0.5  96780  2744 ?        S    23:35   0:00 nginx: worker process                  
root      5706  0.0  0.1 103236   860 pts/0    S+   23:35   0:00 grep nginx
#nginx启用了三个worker进程。



上边我们把模块放在了“/root/modules”下,其实puppet的模块有默认的存放位置,用以下命令可以查看:
1
2
[iyunv@nod2 modules]# puppet agent --genconfig | grep modulepath
    modulepath = /etc/puppet/modules:/usr/share/puppet/modules



所以可以把我们自己开发的模块放在此目录下,在执行时就不需要加“--modulepath=/root/modules”参数
1
[iyunv@nod2 modules]# mv /root/modules/nginx /etc/puppet/modules/



再去修改下files目录下的nginx.conf,把"worker_process = 3"修改成“worker_process = 1”后再执行一下nginx类:
1
2
3
4
5
6
[iyunv@nod2 modules]# puppet apply -dv -e "include nginx"
[iyunv@nod2 modules]# ps aux | grep nginx
root      5893  0.0  0.4  96432  2088 ?        Ss   23:41   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     5894  0.0  0.5  96780  2736 ?        S    23:41   0:00 nginx: worker process                  
root      5897  0.0  0.1 103236   856 pts/0    S+   23:41   0:00 grep nginx
#worker进程只有一个了。



再来做一个练习,编写一个自动安装mysql的模块:
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
[iyunv@nod2 modules]# pwd
/etc/puppet/modules
[iyunv@nod2 modules]# ls
nginx
[iyunv@nod2 modules]# mkdir -pv mysql{manifests,files,templates,lib,tests,spec}
[iyunv@nod2 modules]# vim mysql/manifests/init.pp
class mysql {
        package {'mysql':
                ensure => present,
                name   => 'mysql-server',
                before => Service['mysqld'],
        }
        service {'mysqld':
                ensure  => true,
                enable  => true,
                require => Package['mysql'],
        }
        file {'my.cnf':
                ensure  => file,
                source  => 'puppet:///modules/mysql/my.cnf',
                path    => '/etc/my.cnf',
                require => Package['mysql'],
                notify  => Service['mysqld'],
        }
}



再提供一个my.cnf文件:
1
2
3
4
5
6
7
8
9
10
11
12
[iyunv@nod2 modules]# cat  mysql/files/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
innodb_file_per_table = 1
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[iyunv@nod2 modules]# puppet parser validate mysql/manifests/init.pp #测试manifest文件,如果有语法错误会报告



1
[iyunv@nod2 modules]# puppet apply -dv -e "include mysql"  #安装测试



当出现“notice: Finished catalog run in 0.39 seconds”这样的类似字样表示执行成功。
1
2
3
[iyunv@nod2 modules]# ss -antl | grep 3306
LISTEN     0      50                        *:3306                     *:*   
#测试成功



7.2、站点清单的使用
在7.1中我们编写了两个模块,一个是nginx,一个是mysql,如下:
1
2
3
4
[iyunv@nod2 modules]# pwd
/etc/puppet/modules
[iyunv@nod2 modules]# ls
mysql  nginx



思考:如果一个主机需要安装mysql,又需要安装nginx,那要怎样操作?你会说执行两次apply,分别声明调用nginx类和mysql类就行了。不错,这样做是可以的,但如果主机需要安装的软件多达数十个,每个软件都写成了一个模块,那你不是要手动执行数十次apply。显然puppet不会让我这么做,这就是站点清单的作用。
默认时站点清单的路径是“/etc/puppet/manifests/site.pp”,这个site.pp文件名是不能更改的,现在我们来定义这样一个站点清单。
1
2
3
4
5
[iyunv@nod2 puppet]# vim /etc/puppet/manifests/site.pp
node 'nod2.test.com' {
        include nginx
        include mysql
}



#node是关键字,表示定义一个站点清单,“nod2.test.com”这是我本地主机的主机名,大括号里的内容就是我这个主机需要执行的类,注意后边没有“,”逗号。
1
[iyunv@nod2 puppet]# puppet parser validate /etc/puppet/manifests/site.pp  #语法测试



把之前安装的nginx,mysql统统卸载后,执行下站点清单看一下能否把nginx与mysql都安装上:
卸载软件过程略!
1
2
3
4
5
6
7
8
9
10
[iyunv@nod2 puppet]# puppet apply -dv /etc/puppet/manifests/site.pp
[iyunv@nod2 puppet]# ss -antl
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port
LISTEN     0      128                       *:80                       *:*   
LISTEN     0      128                      :::22                      :::*   
LISTEN     0      128                       *:22                       *:*   
LISTEN     0      100                     ::1:25                      :::*   
LISTEN     0      100               127.0.0.1:25                       *:*   
LISTEN     0      50                        *:3306                     *:*
#两个服务已启动



8、总结

     这是我在学习puppet时整理出的一些知识要点,通过对它的学习,也让我认识到大规格的环境下使用这样的自动化运维工具的必要性,它能让管理人员从繁重且重复性的工作中解放出来,让管理者有更多的精力关注技术。路漫漫其修远兮,我也在不断的学习与摸索,此文希望对想学习puppet的朋友有所帮助。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-77455-1-1.html 上篇帖子: puppet学习笔记之安装与配置 下篇帖子: puppet的master/aget环境部署及案例展示 基础知识
累计签到:189 天
连续签到:1 天
发表于 2017-9-17 14:11:30 | 显示全部楼层
写的还不错啊 很好很好

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表