一个集群的自动化部署过程可以分为三个阶段:供应阶段(操作系统部署阶段)、初始化配置阶段、命令和管控阶段。
操作系统部署阶段常用的工具有:pxe , cobbler 等
初始化配置阶段工具 :ansible(agentless) , puppet(master/agent) (ruby), saltstack (python) 等
命令和管控阶段工具 :ansible(playbook) , fabric(fab) , func 等
Puppet 是一款应用非常广泛的高性能环境自动化部署工具,本文以 puppet-3.8.7-1.el7.noarch 版本为例来了解下这款程序的工作机制和应用方法。
与 Ansible 程序利用 ssh 远程协议与从节点主机通信不同的是,Puppet 中的 Master 和 Agent 间采用 https 协议通信,Puppet 的执行效率更高。
Standalone (单机)模型:手动应用清单
Master/Agent (主从)模型:由agent周期性地向Master请求清单并自动应用于本地
Master端主机需要安装的程序包:facter,puppet,puppet-server
Agent端主机需要安装的程序包:facter,puppet
查看puppet的程序目录,其中的每个文件或目录都有其重要功用
ls /etc/puppet
auth.conf environments fileserver.conf manifests modules puppet.conf
puppet.conf :puppet程序的通用主配置文件,其中定义了 “[main]” , “[agent]” 两个配置段,定义了部分 puppet 程序的初始化默认配置,可使用 “puppet config print” 命令查看 puppet 程序的所有配置项的默认值
auth.conf :认证信息文件,其中定义了主节点和各个从节点主机的各类权限,可在此处设置主从间通信的访问权限
fileserver.conf :文件系统配置文件,可在此文件中定义新的挂载点,供主从间通信使用
environments :环境,指将要部署的环境
manifests :主机清单,此目录下应存在一个 site.pp 文件,该文件定义了集群中的每台主机的主机名和每台主机要执行的动作(引用的模块名、类名),每台主机连接
manifests :主机清单存放目录,用于本地编辑 site.pp 文件,将所有附属的Agent的主机信息都放在主机清单中
modules :模块存放目录,可以在此处开发modules,开发完成后放置于environments的对应环境下
type{'title':
attribute_1 => 'value_1',
attribute_2 => 'value_2',
...
}
注意:资源中的 “type” 必须要小写,在被引用时,资源中的 “Type” 首字母大写,其余字母小写;title是一个字符串,在同一类型中必须惟一。
常用的资源有8个 :group, user, package, service, file , exec, cron, notify,每个资源中都含有不同的属性
资源有三个的特殊属性
- Namevar, 可简称为name;name可省略,此时将由title表示
- ensure:资源的目标状态;
- Provider:指明资源的管理接口资源间关系的元参数metaparameters:
A before B: B依赖于A,定义在A资源中;
{
...
before => Type['B'],
...
}
B require A: B依赖于A,定义在B资源中;
{
...
require => Type['A'],
...
}
notify
A notify B:B依赖于A,且A发生改变后会通知B;
{
...
notify => Type['B'],
...
}
subscribe
B subscribe A:B依赖于A,且B监控A资源的变化产生的事件;
{
...
subscribe => Type['A'],
...
}
Package['httpd'] -> File['httpd.conf'] -> Service['httpd']
属性:
name:用户名
uid: UID
gid:基本组ID
groups:附加组,不能包含基本组
comment:注释
expiry:过期时间
home:家目录
shell:默认shell类型
system:是否为系统用户
ensure:present/absent
password:加密后的密码串
属性:
name:组名
gid:GID
system:是否为系统组,true OR false
ensure:目标状态,present/absent
members:成员用户
属性:
ensure:installed, present, latest, absent
name:包名
source:程序包来源,仅对不会自动下载相关程序包的provider有用,例如rpm或dpkg
属性:
ensure:Whether a service should be running. Valid values are `stopped` (also called `false`), `running` (also called `true`).
enable:Whether a service should be enabled to start at boot. Valid values are `true`, `false`, `manual`.
name:
path:The search path for finding init scripts. Multiple values should be separated by colons or provided as an array. 脚本的搜索路径,默认为/etc/init.d/
hasrestart:
hasstatus:
start:手动定义启动命令
stop:
status:
restart:Specify a *restart* command manually. If left unspecified, the service will be stopped and then started. 通常用于定义reload操作
属性:
ensure:Whether the file should exist, and if so what kind of file it should be. Possible values are `present`, `absent`, `file`, `directory`, and `link`.
file:类型为普通文件,其内容由content属性生成或复制由source属性指向的文件路径来创建;
link:类型为符号链接文件,必须由target属性指明其链接的目标文件;
directory:类型为目录,可通过source指向的路径复制生成,recurse属性指明是否递归复制
path:文件路径;
source:源文件;
content:文件内容;
target:符号链接的目标文件;
owner:属主
group:属组
mode:权限;
atime/ctime/mtime:时间戳
可使用puppet URL :puppet:///modules/MODULE_NAME/FILE_NAME
exec
resource must be able to run multiple times without causing harm — that is, it must be idempotent.属性:
command (namevar):要运行的命令
cwd:The directory from which to run the command
creates:文件路径,仅此路径表示的文件不存在时,command方才执行
user/group:运行命令的用户身份
path:The search path used for command execution. Commands must be fully qualified if no path is specified
onlyif:此属性指定一个命令,此命令正常(退出码为0)运行时,当前command才会运行
unless:此属性指定一个命令,此命令非正常(退出码为非0)运行时,当前command才会运行
refresh:重新执行当前command的替代命令
refreshonly:仅接收到订阅的资源的通知时方才运行
属性:
command:要执行的任务
ensure:present/absent
hour:
minute:
monthday:
month:
weekday:
user:以哪个用户的身份运行命令
target:添加为哪个用户的任务
name:cron job的名称
属性:
message:信息内容
name:信息名称
FQN: $::scope1::scope2::variable
$variable_name=value
数据类型:字符串、数值、布尔型、数组、hash、undef
undef:未定义 ;
正则表达式:
(?<ENABLED OPTION>: )
(?-<DISABLED OPTION>: )
OPTIONS:
i:忽略字符大小写;
m:把.当换行符;
x:忽略<PATTERN>中的空白字符
示例:(?i-mx:PATTERN)
facts:
由facter提供;top scope;
内建变量:
master端变量
agent端变量
parser变量
用户自定义变量:
变量有作用域,称为Scope;
top scope: 如 $::var_name
node scope
class scope
if , case , selector , unless
if CONDITION {
...
} else {
...
}
CONDITION的给定方式:
(1) 变量
(2) 比较表达式
(3) 有返回值的函数
vim /etc/puppet/modules/webserver.pp
#内容如下:
if $osfamily =~ /(?i-mx:debian)/ {
$webserver = 'apache2'
} else {
$webserver = 'httpd'
}
package{"$webserver":
ensure => installed,
before => [ File['httpd.conf'], Service['httpd'] ],
}
file{'httpd.conf':
path => '/etc/httpd/conf/httpd.conf',
source => '/root/manifests/httpd.conf',
ensure => file,
}
service{'httpd':
ensure => running,
enable => true,
restart => 'systemctl restart httpd.service',
subscribe => File['httpd.conf'],
}
case 语句
case CONTROL_EXPRESSION {
case1: { ... }
case2: { ... }
case3: { ... }
...
default: { ... }
}
CONTROL_EXPRESSION:
(1) 变量
(2) 表达式
(3) 有返回值的函数
各case的给定方式:
(1) 直接字串;
(2) 变量
(3) 有返回值的函数
(4) 正则表达式模式;
(5) default
case $osfamily {
"RedHat": { $webserver='httpd' }
/(?i-mx:debian)/: { $webserver='apache2' }
default: { $webserver='httpd' }
}
package{"$webserver":
ensure => installed,
before => [ File['httpd.conf'], Service['httpd'] ],
}
file{'httpd.conf':
path => '/etc/httpd/conf/httpd.conf',
source => '/root/manifests/httpd.conf',
ensure => file,
}
service{'httpd':
ensure => running,
enable => true,
restart => 'systemctl restart httpd.service',
subscribe => File['httpd.conf'],
}
selector 语句
CONTROL_VARIABLE ? {
case1 => value1,
case2 => value2,
...
default => valueN,
}
CONTROL_VARIABLE的给定方法:
(1) 变量
(2) 有返回值的函数
各case的给定方式:
(1) 直接字串;
(2) 变量
(3) 有返回值的函数
(4) 正则表达式模式;
(5) default
注意:不能使用列表格式;但可以是其它的selecor
$webserver = $osfamily ? {
"Redhat" => 'httpd',
/(?i-mx:debian)/ => 'apache2',
default => 'httpd',
}
package{"$webserver":
ensure => installed,
before => [ File['httpd.conf'], Service['httpd'] ],
}
file{'httpd.conf':
path => '/etc/httpd/conf/httpd.conf',
source => '/root/manifests/httpd.conf',
ensure => file,
}
service{'httpd':
ensure => running,
enable => true,
restart => 'systemctl restart httpd.service',
subscribe => File['httpd.conf'],
}
类:puppet中命名的代码模块,常用于定义一组通用目标的资源,可在puppet全局调用;类可以被继承,也可以包含子类;
class NAME {
...puppet code...
}
class NAME(parameter1, parameter2) {
...puppet code...
}
(1) include CLASS_NAME1, CLASS_NAME2, ...
(2) class{'CLASS_NAME':
attribute => value,
}
子类
sub_class_name:
base_class::sub_class_name
子类中引用父类的资源:
Type['title'] {
attribute => value,
atrribute +> value,
}
在子类中为父类的资源新增属性或覆盖指定的属性的值:
Type['title'] {
attribute1 => value,
...
}
在子类中为父类的资源的某属性增加新值:
Type['title'] {
attribute1 +> value,
...
}
#定义父类nginx
class nginx {
package{'nginx':
ensure => installed,
}
service{'nginx':
ensure => running,
enable => true,
restart => '/usr/sbin/nginx -s reload',
}
}
#定义nginx的子类nginx::web
class nginx::web inherits nginx {
Service['nginx'] {
subscribe => File['ngx-web.conf'],
}
file{'ngx-web.conf':
path => '/etc/nginx/conf.d/ngx-web.conf',
ensure => file,
source => '/root/manifests/ngx-web.conf',
}
}
#定义nginx的子类nginx::proxy
class nginx::proxy inherits nginx {
Service['nginx'] {
subscribe => File['ngx-proxy.conf'],
}
file{'ngx-proxy.conf':
path => '/etc/nginx/conf.d/ngx-proxy.conf',
ensure => file,
source => '/root/manifests/ngx-proxy.conf',
}
}
#调用(声明)nging的子类nginx::proxy
include nginx::proxy
erb:模板语言,embedded ruby;
file{'title':
ensure => file,
content => template('MOD_NAME/ERB_FILE'),
}
<%= @VARIABLE_NAME %>
模块就是一个按约定的、预定义的结构存放了多个文件或子目录的目录,目录里的这些文件或子目录必须遵循一定格式的命名规范
MODULES_NAME:
manifests/
init.pp:必须一个类定义,类名称必须与模块名称相同
files/:静态文件
templates/:
lib/:插件目录,常用于存储自定义的facts以及自定义类型
spec/:类似于tests目录,存储lib/目录下插件的使用帮助和范例
tests/:当前模块的使用帮助或使用范例文件
模块名只能以小写字母开头,可以包含小写字母、数字和下划线;但不能使用 “main” 和 “settings”
注意:
- puppet 3.8及以后的版本中,资源清单文件的文件名要与文件听类名保持一致,例如某子类名为“base_class::child_class”,其文件名应该为child_class.pp
- 无需再资源清单文件中使用import语句
- manifests目录下可存在多个清单文件,每个清单文件包含一个类,其文件名同类名
puppet apply [-d|--debug] [-v|--verbose] [-e|--execute] [--noop] <CLASS_NAME.pp>
master: site manifest
node 'node_name' {
...puppet code...
}
程序包下载路径:
https://yum.puppetlabs.com/
官方文档:
https://docs.puppet.com/puppet/3/reference/
内建函数:
https://docs.puppet.com/puppet/3/reference/function.html
配置参数列表:
https://docs.puppet.com/puppet/3/reference/configuration.html
puppet兼容的erb语法:
https://docs.puppet.com/puppet/latest/reference/lang_template_erb.html