Puppet —自动化部署工具详解

来源:互联网 发布:华为无线优化工程师 编辑:程序博客网 时间:2024/06/05 16:06

Puppet —自动化部署工具详解

一个集群的自动化部署过程可以分为三个阶段:供应阶段(操作系统部署阶段)、初始化配置阶段、命令和管控阶段。

操作系统部署阶段常用的工具有: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 的执行效率更高。

这里写图片描述

puppet 的两种工作模型

  1. Standalone (单机)模型:手动应用清单

  2. Master/Agent (主从)模型:由agent周期性地向Master请求清单并自动应用于本地

puppet 程序介绍

Master端主机需要安装的程序包:facter,puppet,puppet-server

Agent端主机需要安装的程序包:facter,puppet

  1. 程序配置文件路径 :/etc/puppet
  2. puppet主程序路径 :/usr/bin/puppet

puppet 程序的工作架构分级

查看puppet的程序目录,其中的每个文件或目录都有其重要功用

ls /etc/puppetauth.conf  environments  fileserver.conf  manifests  modules  puppet.conf

配置类文件

  1. puppet.conf :puppet程序的通用主配置文件,其中定义了 “[main]” , “[agent]” 两个配置段,定义了部分 puppet 程序的初始化默认配置,可使用 “puppet config print” 命令查看 puppet 程序的所有配置项的默认值

  2. auth.conf :认证信息文件,其中定义了主节点和各个从节点主机的各类权限,可在此处设置主从间通信的访问权限

  3. fileserver.conf :文件系统配置文件,可在此文件中定义新的挂载点,供主从间通信使用

Master/Agent 模型

  1. environments :环境,指将要部署的环境

    • 在实际应用中,一般有 development , testing , production 等几种常见部署环境
  2. manifests :主机清单,此目录下应存在一个 site.pp 文件,该文件定义了集群中的每台主机的主机名和每台主机要执行的动作(引用的模块名、类名),每台主机连接

Standalone 模型

  1. manifests :主机清单存放目录,用于本地编辑 site.pp 文件,将所有附属的Agent的主机信息都放在主机清单中

  2. modules :模块存放目录,可以在此处开发modules,开发完成后放置于environments的对应环境下

Puppet中的 modules 开发

1.resource (资源)

  • 资源的格式示例:
type{'title':    attribute_1 =>  'value_1',    attribute_2 =>  'value_2',    ...}
  • 资源引用:Type[‘title’]

注意:资源中的 “type” 必须要小写,在被引用时,资源中的 “Type” 首字母大写,其余字母小写;title是一个字符串,在同一类型中必须惟一。

2.资源类型:

常用的资源有8个 :group, user, package, service, file , exec, cron, notify,每个资源中都含有不同的属性

资源有三个的特殊属性
- Namevar, 可简称为name;name可省略,此时将由title表示
- ensure:资源的目标状态;
- Provider:指明资源的管理接口

资源间关系的元参数metaparameters:

  • 前置/依赖关系:before/require
A before B: B依赖于A,定义在A资源中;    {        ...        before  => Type['B'],        ...    }B require A: B依赖于A,定义在B资源中;    {        ...        require => Type['A'],        ...    }
  • 通知/订阅关系:notify/subscribe
notify A notify B:B依赖于A,且A发生改变后会通知B;    {        ...        notify => Type['B'],            ...    }subscribeB subscribe A:B依赖于A,且B监控A资源的变化产生的事件;    {        ...        subscribe => Type['A'],        ...    }
  • 关系元参数也可以用符号表示 :->, ~>
Package['httpd'] -> File['httpd.conf'] -> Service['httpd']
  1. user:Manage users.
属性:    name:用户名    uid: UID    gid:基本组ID    groups:附加组,不能包含基本组    comment:注释    expiry:过期时间     home:家目录    shell:默认shell类型    system:是否为系统用户     ensure:present/absent    password:加密后的密码串
  1. group:Manage groups.
属性:    name:组名    gid:GID    system:是否为系统组,true OR false    ensure:目标状态,present/absent    members:成员用户
  1. package:Manage packages.
属性:    ensure:installed, present, latest, absent    name:包名    source:程序包来源,仅对不会自动下载相关程序包的provider有用,例如rpm或dpkg
  1. service:Manage running services.
属性:    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操作
  1. file:Manages files, including their content, ownership, and permissions.
属性:                     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

  1. exec:Executes external commands. Any command in an 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:仅接收到订阅的资源的通知时方才运行
  1. cron:Installs and manages cron jobs. Every cron resource created by Puppet requires a command and at least one periodic attribute (hour, minute, month, monthday, weekday, or special).
属性:             command:要执行的任务    ensure:present/absent    hourminute:    monthday:    month:    weekday:    user:以哪个用户的身份运行命令    target:添加为哪个用户的任务    name:cron job的名称
  1. notify:Sends an arbitrary message to the agent run-time log.
属性:    message:信息内容    name:信息名称

3.puppet 的 variable (变量)

FQN: $::scope1::scope2::variable

$variable_name=value

数据类型:字符串、数值、布尔型、数组、hash、undef

  • 字符型:引号可有可无;但单引号为强引用,双引号为弱引用;
  • 数值型:默认均识别为字符串,仅在数值上下文才以数值对待;
  • 数组:[]中以逗号分隔元素列表;
  • 布尔型值:true, false;
  • hash:{}中以逗号分隔k/v数据列表; 键为字符型,值为任意puppet支持的类型;{ ‘mon’ => ‘Monday’, ‘tue’ => ‘Tuesday’, };
  • undef:未定义 ;

  • 正则表达式:

(?<ENABLED OPTION>:<PATTERN>)(?-<DISABLED OPTION>:<PATTERN>)    OPTIONS:        i:忽略字符大小写;        m:把.当换行符;        x:忽略<PATTERN>中的空白字符    示例:(?i-mx:PATTERN

4.变量类型

facts:    由facter提供;top scope;    内建变量:        master端变量         agent端变量         parser变量    用户自定义变量:变量有作用域,称为Scope;    top scope:     如 $::var_name    node scope    class scope

5.puppet流程控制语句

if , case , selector , unless

  1. if 语句
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'],}
  1. case 语句

    • 语法及格式
case CONTROL_EXPRESSION {case1: { ... }    case2: { ... }    case3: { ... }    ...    default: { ... }}    CONTROL_EXPRESSION:        (1) 变量        (2) 表达式         (3) 有返回值的函数    各case的给定方式:        (1) 直接字串;        (2) 变量         (3) 有返回值的函数        (4) 正则表达式模式;        (5) default
  • case 语句示例:
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'],}
  1. 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'],}

6.puppet的类

类: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,        ...    }
  • 示例
#定义父类nginxclass nginx {    package{'nginx':    ensure  => installed,    }    service{'nginx':        ensure  => running,        enable  => true,        restart => '/usr/sbin/nginx -s reload',    }}#定义nginx的子类nginx::webclass 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::proxyclass 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::proxyinclude nginx::proxy

7.puppet模板

erb:模板语言,embedded ruby;

  • 在资源中使用模板的格式
file{'title':    ensure  => file,    content => template('MOD_NAME/ERB_FILE'),}
  • 文本文件中内嵌变量替换机制:
<%= @VARIABLE_NAME %>

8.puppet模块

模块就是一个按约定的、预定义的结构存放了多个文件或子目录的目录,目录里的这些文件或子目录必须遵循一定格式的命名规范

  • puppet模块的目录结构
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目录下可存在多个清单文件,每个清单文件包含一个类,其文件名同类名

9.模块执行测试

  1. standalone模式:测试命令如下
    puppet apply  [-d|--debug] [-v|--verbose] [-e|--execute] [--noop] <CLASS_NAME.pp>
  1. master/agent模式 :通过master节点的主机资源清单实现执行过程,agent每隔30分钟到master端请求与自己相关的catalog
    master: site manifest        node 'node_name' {            ...puppet code...        }

10.puppet的帮助文档

程序包下载路径:        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