1、认识puppet
1.1 引入
puppet是什么,咱们先不用专业的名词解释它,咱们先描述一些工作场景,看明白这些工作场景,自然会知道puppet是什么。
(1)场景一:
管理员想要在100台服务器上同时创建一个名叫"along"的用户,怎么办,当然,我们可以"手动解决",登录每一台服务器,然后一台一台的创建用户,如果你真的这样干,那么我只能说,算你狠!!!但是,既然我们这篇文章是介绍puppet的,我们肯定会推荐你使用puppet解决这个问题。
(2)场景二:
公司新买了一堆云服务器,这些服务器最终可能要提供相同的服务,现在需要管理员在这一堆服务器上安装一些相同的应用,而且安装完成后,还需要这些服务器上的应用自动启动,怎么办,当然,手动解决算你狠,兄弟我服了,你说你写脚本解决,嗯,这是个办法,在我没有认识puppet之前我可能也会写个脚本,但是我们是介绍puppet的,我们会推荐你使用puppet解决这个问题。
(3)场景三:
在一些服务器中,执行大批量的重复操作,我们可以使用puppet。
看完上述三个场景,你应该已经大概猜出puppet是干吗的了,没错,说的糙一点,你可以把它理解成批量处理工具,但是你又不能完全把它理解成批量处理工具,因为除了批量处理,他还有一些别的功能和特性,我们暂且先这么认为,以便我们入门。
1.2 介绍
(1)我自己对puppet的了解
像puppet这种工具有几个专业的名词可以用来称呼它们:"配置管理工具"、"自动化运维管理工具"。
Linux中,常见的配置管理工具有puppet、saltstack、ansible(博主之前讲解过)、chef等,它们的功能类似,puppet算是这个领域里面的老大哥,时间久(我说的是创始时间久,不要想歪了····),成熟,被广泛的应用,google、twitter、redhat,cisco等大公司都用到了它,功能强大,puppet是使用ruby研发的,saltstack和ansible都属于python系的, ansible和saltstack与puppet相比,属于后起之秀,我们以后也可能会对它们进行总结,但是现在,我们只聊puppet。
(2)专业术语介绍
① puppet是一种Linux/Unix平台下的集中配置管理系统,使用自有的puppet描述语言,可管理配置文件、用户、cron任务、软件包、系统服务等。puppet把这些系统实体称之为资源,puppet的设计目标是简化对这些资源的管理以及妥善处理资源间的依赖关系。
② Puppet是开源的基于Ruby的系统配置管理工具,puppet是一个C/S结构。所有的puppet客户端同一个服务器端的puppet通讯,每个puppet客户端每半小时(可以设置)连接一次服务器端,下载最新的配置文件,并且严格按照配置文件来配置服务器。 配置完成以后,puppet客户端可以反馈给服务器端一个消息, 如果出错,也会给服务器端反馈一个消息。
③ Puppet是用于大规模集群管理的神器。其本身使用Ruby语言开发,基于C/S架构。在每台机器上部署的客户端每隔一个指定的时间会连接到Master检查资源变化情况,若资源发生变化,将按配置动作进行相应的操作。
④ Puppet将所有可操作对象抽象为资源,目前涵盖了40多种,如:File、User、Group、Host、Package、Service、Cron、Exec等,下面我会一一讲述。
⑤ Puppet 通过抽象资源的方式,使得每台机器能够“清楚”其本身“应该”是什么“状态”,而客户端根据当前是否达到这个状态决定采取指定的动作。这使得Puppet 不仅可用于传统的应用部署,而且通过合理的手段,也能够将比应用部署更频繁的配置管理一并解决。甚至可以在Master端外接自己开发的平台,通过集中配 置方式管理各项“资源”,实现高度灵活的自动化管理体系。
1.3 puppet 名词解释
资源:是puppet的核心,通过资源申报,定义在资源清单中。相当于ansible中的模块,只是抽象的更加彻底。
类:一组资源清单。
模块:包含多个类。相当于ansible中的角色。
站点清单:以主机为核心,应用哪些模块。
本篇文章主要讲解资源;类、模块、站点清单都在下篇进行详解。
1.4 puppet常用资源类型
group 组
user 用户
packge 程序包
service 服务
file 文件
exec 执行自定义命令
cron 周期性任务计划
notify 通知
yumrepo 源
host /etc/hosts中主机解析
1.5 puppet命令使用
(1)查询资源类型和帮助信息
1
puppet describe [-h|--help] [-s|--short] [-p|--providers] [-l|--list] [-m|--meta] [type]
-l:列出所有资源类型;
-s:显示指定类型的简要帮助信息;也就是基本选项
-m:显示指定类型的元参数,一般与-s 一同使用;这些选项只是来描述这个类型的
(2)执行资源清单命令
1
puppet apply [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose] [-e|--execute] [--detailed-exitcodes] [-l|--logdest ] [--noop] [--catalog ] [--write-catalog-summary]
-d:打开调试信息,会显示很多信息
-v:显示详细信息
-e:直接执行给定的命令
-l:执行结果保存到指定日志的文件中,否则执行结果会输出到标准输出
--noop:dry run 干跑,只是测试的跑一边,不真正的执行
--catalog:应用JSON目录
1.6 puppet的优缺点
这类垂直管理系统的使用及活跃,极大减轻了运维人员在重复性、批量化操作方面的负担,能够非常有效地在各自领域完成既定的运维子目标。但其缺陷在于只能针对某一垂直领域的特定问题进行高效处理,对于它们之间的关联性很难应对。因为运维的本质是保证服务的可用性,而自动化运维则是在完全保证这一前提下,尽可能将需要人干涉的部分处理掉,所以判断其优劣的标准则是——与人工处理比,对服务的保证有没有提高。如果仅是解决报警、部署这些单一动作,后续仍然需要人去处理、去关注、去判断的话,就离这个目标还有距离,谈不上真正的自动化,只能算是工具化。
puppet是一个开源的软件自动化配置和部署工具,它使用简单且功能强大,正得到了越来越多地关注,现在很多大型IT公司均在使用puppet对集群中的软件进行管理和部署,如google利用puppet管理超过6000台地mac桌面电脑(2007年数据)。
puppet设计架构是基于c/s架构的。服务器端保存着所有对客户端服务器的配置代码,在puppet里面叫做manifest. 客户端下载manifest之后,可以根据manifest对服务器进行配置,例如软件包管理,用户管理和文件管理等等。
2、puppet的使用模型及工作流程
puppet的使用模型分为 单机使用模型 和 master/agent模型;本文主要讲解单机使用模型,便于入门。
2.1 master/agent模型
从上述专业的解释中,我们可以得知puppet是C/S架构的,也就是说,它有服务端,也有客户端,管理员可以通过puppet服务端(master),管理每一台被管理的服务器,但是需要puppet客户端作为中介,也就是说,puppet客户端作为代理(agent),接收来自puppet服务端的配置信息,按照服务端(master)发送过来的配置信息,对被管理服务器进行配置,真正执行配置操作的是puppet客户端,puppet服务端只负责将配置信息准备好,发送给puppet客户端,以便客户端执行具体操作,puppet客户端还有另一个作用,就是向puppet服务端发送报告,当客户端按照配置信息执行完成相关配置以后,会将执行信息发送到服务端,比如执行成功与否,执行结果等,默认情况下,每30分钟,puppet客户端会向puppet服务端发起一次请求,请求受管理服务器的配置信息, puppet服务端将配置信息发送给客户端,客户端根据反回的信息进行判断,判断被管理服务器是否符合管理员定义的配置,puppet的这种工作模式就是C/S架构的,也可以理解为master/agent的工作模式,用文字描述显得太无力,我们画个图来看看。
那么,我们把上图中的两台服务器拿出来,详细说说它们之间的具体工作流程,但是此处我们需要说明,在master/agent模型下工作的puppet的工作流程比我们总结的要复杂一点,但是为了入门方便,我们只取出其中的一部分核心的流程进行总结,在后面的实际应用中,我们会不断的丰富这些流程,此处先给出一个简化过的流程图,如下图所示。
过程分析:
① 客户端puppet agent请求catalog,我们已经说过,catalog其实就是被管理服务器对应的配置文件(经过处理过的配置文件),服务端master收到agent的请求,然后找到对应被管理服务器的"站点清单",或者被称为"主机清单",因为一台"被管理服务器"可能同时担任多个"角色",每个角色可能都会对应一个"manifest"(也就是清单),所以,我们可以为每一台被管理服务器配置一个"站点清单",站点清单也可以理解成为一种"清单",只是它是针对一台服务器而存在的一种清单。
② 服务端master找到被管理服务器的站点清单后,根据站点清单,找到对应服务器需要哪些"清单",因为一台服务器可能会需要多张"清单",上图中为了示例,只画出了一个清单,但是这不代表必定只有一个。
③ master将找到的所有"清单"进行处理,处理为catalog。
④ master将处理过的catalog发送到agent端。
⑤ agent收到master发送过来的catalog,然后,agent会查询"被管理服务器的当前状态",看看服务器的当前状态是否符合catalog中定义的目标状态。
⑥ 如果"被管理服务器的当前状态"与"catalog中定义的目标状态"一致,那么资源对应的操作将不会执行,如果"被管理服务器的当前状态"与"catalog中定义的目标状态"不一致,那么资源对应的操作将会执行,以便让"被管理服务器"达到管理员指定的"目标状态"。
⑦ 经过上一步的"状态判断",执行对应操作,不管执行是否成功,都会生成对应的报告信息。
⑧ agent将生成的报告信息发送给master端。
上述过程,就是puppet在master/agent模式下的工作流程,我们说过,默认情况下,客户端每隔30分钟向服务端请求一次配置信息,然后根据服务端返回的配置信息,判断当前服务器是否处于管理员定义的目标状态,如果被管理的服务器不处于管理员定义的目标状态,则需要执行对应的操作,使得被管理主机最终处于管理员定义的目标状态,我们也可以不必每次都等待30分钟,我们可以从master端推送catalog到agent端,主动告诉agent端,配置已经发生了改变,请执行对应的操作。这是后话,我们以后再聊。
2.2 单机使用模型
当然,puppet也可以不在master/agent模式下工作,我们可以在受管理服务器上只安装puppet客户端,使用客户端手动执行对应配置文件,相当于配置文件中的信息并不是通过puppet服务端发送过来,而是通过本地的配置文件获取,也是可以的,我们暂且称这种不需要puppet服务端的工作模式为单机模式,我们在学习puppet时,可以使用单机的模式进行练习,但是在生产环境中,一般都使用master/agent的方式使用puppet。
实现定义多个manifests --> complier --> catalog --> apply
3、puppet资源详解
3.1 puppet资源介绍
3.1.1 程序安装及环境
首先,我们还是来安装一下puppet,puppet的安装可以使用源码安装,也可以使用rpm(官方提供)、epel源、官方提供的yum仓库来安装(通过下载官方提供的rpm包可以指定官方的yum仓库)。
在这里,我们就是用 yum 安装的方式。
1
[root@along ~]# yum -y install puppet
3.1.2 puppet资源简介
(1)资源抽象
puppet 从以下三个维度来对资源完成抽象:
相似的资源被抽象成同一种资源“类型”,如程序包资源、用户资源及服务资源等;
将资源属性或状态的描述与其实现方式剥离开来,如仅说明安装一个程序包而不用关心其具体是通过yum、pkgadd、ports或是其它方式实现;
仅描述资源的目标状态,也即期望其实现的结果,而不是其具体过程,如“确定nginx 运行起来” 而不是具体描述为“运行nginx命令将其启动起来”;
这三个也被称作puppet 的资源抽象层(RAL)
RAL 由type( 类型) 和provider( 提供者,即不同OS 上的特定实现)组成。
(2)资源定义
① 资源定义通过向资源类型的属性赋值来实现,可称为资源类型实例化;
② 定义了资源实例的文件即清单,manifest;
③ 定义资源的语法如下:
1
2
3
4
5
type {'title':
attribute1 => value1,
atrribute2 => value2,
……
}
注意:type必须使用小写字符;title是一个字符串,在同一类型中必须惟一;每一个属性之间需要用“,”隔开,最后一个“,”可省略。
例如,可以同时有名为nginx 的“service”资源和“package”资源,但在“package” 类型的资源中只能有一个名为“nginx”的资源。
(3)资源属性中的三个特殊属性:
Namevar:可简称为name;
ensure:资源的目标状态;
Provider:指明资源的管理接口;
3.2 group:Manage groups
3.2.1 类型属性选项
(1)属性 Parameters:
name:组名;
gid:GID;
system:是否为系统组,true OR false;
ensure:目标状态,present(创建)/absent(删除);
members:成员用户;
(2)puppet describe group -s -m 使用之前,可以查询这个类型的选项
3.2.2 演示
① 编辑manifest( 清单)
1
2
3
4
5
6
[root@along manifest]# vim group.pp
group{'mygrp':
name => 'mygrp',
ensure => present,
gid => 2000,
}
② 执行并验证 manifest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---先预执行一次,检查是否有语法错误
[root@along manifest]# puppet apply -v --noop group.pp
Notice: Compiled catalog for along in environment production in 0.18 seconds
Info: Applying configuration version '1550042227'
Notice: /Stage[main]/Main/Group[mygrp]/ensure: current_value absent, should be present (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Info: Creating state file /var/lib/puppet/state/state.yaml
Notice: Finished catalog run in 0.03 seconds
---真正执行,执行成功
[root@along manifest]# puppet apply -v group.pp
Notice: Compiled catalog for along in environment production in 0.06 seconds
Info: Applying configuration version '1550042298'
Notice: /Stage[main]/Main/Group[mygrp]/ensure: created
Notice: Finished catalog run in 0.09 seconds
---查询验证
[root@along manifest]# cat /etc/group |grep mygrp
mygrp:x:2000:
3.3 user:Manage users
3.3.1 类型属性选项
(1)属性 Parameters:
name:用户名;
uid: UID;
gid:基本组ID;
groups:附加组,不能包含基本组;
comment:注释;
expiry:过期时间 ;
home:家目录;
shell:默认shell类型;
system:是否为系统用户 ;
ensure:present/absent 存在/不存在;
password:加密后的密码串;
(2)puppet describe user -s -m 使用之前,可以查询这个类型的选项
3.3.2 演示
① 编辑manifest( 清单)
1
2
3
4
5
6
7
8
9
10
11
[root@along manifest]# vim user1.pp
user{'along1':
ensure => present,
system => false,
comment => 'Test user',
shell => '/usr/sbin/nologin',
home => '/app/along',
managehome => true,
groups => 'mygrp',
uid => 3000,
}
② 执行manifest
1
2
3
4
5
6
7
8
[root@along manifest]# puppet apply -v --noop user1.pp
[root@along manifest]# puppet apply -v user1.pp
Notice: Compiled catalog for along in environment production in 0.08 seconds
Info: Applying configuration version '1550042932'
Notice: /Stage[main]/Main/User[along1]/ensure: created
Notice: Finished catalog run in 0.12 seconds
[root@along manifest]# cat /etc/passwd |grep along1
along1:x:3000:3000:Test user:/mnt/along:/usr/sbin/nologin
3.4 package:Manage packages
3.4.1 类型属性选项
① 属性:
ensure:installed, present, latest, absent, any version string (implies present)
name:包名;
ource:程序包来源,仅对不会自动下载相关程序包的provider有用,例如rpm或dpkg;
provider:指明安装方式;rpm/yum/...
② puppet describe package -s -m 可以查询这个类型的选项
3.4.2 演示
① 创建manifest
1
2
3
4
5
[root@along manifest]# vim pkg.pp
package{'redis':
ensure => installed,
provider => yum
}
② 执行manifest
1
2
3
4
5
6
7
8
9
[root@along manifest]# puppet apply --noop -v pkg.pp
[root@along manifest]# puppet apply -v pkg.pp
Notice: Compiled catalog for along in environment production in 0.26 seconds
Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false.
(at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default')
Info: Applying configuration version '1550044027'
Notice: /Stage[main]/Main/Package[redis]/ensure: created
Notice: Finished catalog run in 6.09 seconds
[root@along manifest]# rpm -ql redis
3.5 service:Manage running services
3.5.1 类型属性选项
① 属性:
ensure:running\true(开启) 或 stopped/false(停止)
enable:是否开机自启:true(开机自启)、false(不自启)、manual(手动)
name:服务名
binary:若服务不是systemctl/service 启动,则需规定启动命令;如nginx -s start
path:如果不是systemctl/service 这样启动服务,而是通过脚本启动,指明path路径。多个值应该由冒号分隔,或者作为数组提供。脚本的搜索路径,默认为/etc/init.d/;
hasrestart:是否支持restart 这个参数重启;true/fault ;true 表示支持
hasstatus:是否支持status 这个参数查看状态;true/false
start:手动定义启动命令;
stop:手动定义关闭命令;
status:若hasstatus 为fals 手动定义查看信息命令;
restart:若hasrestart 为false 手动定义reload操作
② puppet describe service -s -m 可以查询这个类型的选项
3.5.2 演示1:开启redis 服务
① 编写manifest 资源清单
1
2
3
4
5
[root@along manifest]# vim srv1.pp
service{'redis':
ensure => running,
enable => true,
}
② 执行
1
2
3
4
5
6
7
8
9
[root@along manifest]# puppet apply -v --noop srv1.pp
[root@along manifest]# puppet apply -v srv1.pp
Notice: Compiled catalog for along in environment production in 0.08 seconds
Info: Applying configuration version '1550044320'
Notice: /Stage[main]/Main/Service[redis]/ensure: ensure changed 'stopped' to 'running'
Info: /Stage[main]/Main/Service[redis]: Unscheduling refresh on Service[redis]
Notice: Finished catalog run in 0.11 seconds
[root@along manifest]# ss -nutl |grep 6379
tcp LISTEN 0 128 127.0.0.1:6379 *:*
3.5.2 演示1:下载memcached 包,且开启服务
① 编写manifest 资源清单
[root@along manifest]# vim srv2.pp
package {'memcached':
ensure => installed,
}
service{'memcached':
ensure => running,
enable => false,
require => Package['memcached']
}
② 执行
1
2
3
4
5
6
7
8
9
10
11
12
[root@along manifest]# puppet apply -v --noop srv2.pp
[root@along manifest]# puppet apply -v srv2.pp
Notice: Compiled catalog for along in environment production in 0.35 seconds
Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false.
(at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default')
Info: Applying configuration version '1550044434'
Notice: /Stage[main]/Main/Package[memcached]/ensure: created
Notice: /Stage[main]/Main/Service[memcached]/ensure: ensure changed 'stopped' to 'running'
Info: /Stage[main]/Main/Service[memcached]: Unscheduling refresh on Service[memcached]
Notice: Finished catalog run in 3.28 seconds
[root@along manifest]# ss -nutlp |grep memcached
udp UNCONN 0 0 *:11211 *:* users:(("memcached",pid=8573,fd=28))
3.6 file:管理文件,包括它们的内容、所有权和权限
3.6.1 类型属性选项
(1)类型的属性、选项
① 属性
ensure:`present`创建, `absent`删除, `file`创建普通文件, `directory`创建目录, link`创建软链接.
file:类型为普通文件,其内容由content属性生成或复制由source属性指向的文件路径来创建;
link:类型为符号链接文件,必须由target属性指明其链接的目标文件;
directory:类型为目录,可通过source指向的路径复制生成,recurse属性指明是否递归复制;
path:文件路径;
source:源文件;当复制文件内容时需要指定
content:文件内容;直接编写文件内容
target:符号链接的目标文件;
owner:属主
group:属组
mode:权限;
atime/ctime/mtime:时间戳;
access time:访问时间,atime,读取文件内容
modify time: 修改时间, mtime,改变文件内容(数据)
change time: 改变时间, ctime,元数据发生改变
② puppet describe file -s -m |tail -20
3.6.2 演示1:创建test.txt,且直接写内容
创建test.txt,且直接写内容
① 编写manifest 清单
[root@along manifest]# vim file1.pp
file{'/mnt/test.txt':
ensure => file,
content => "How are you?\nHow old are you?\n",
owner => 'along1',
group => 'mygrp',
mode => '0400'
}
② 执行
1
2
3
4
5
6
7
8
9
10
11
[root@along manifest]# puppet apply -v --noop file1.pp
[root@along manifest]# puppet apply -v file1.pp
Notice: Compiled catalog for along in environment production in 0.07 seconds
Info: Applying configuration version '1550044597'
Notice: /Stage[main]/Main/File[/mnt/test.txt]/ensure: defined content as '{md5}93c12