Puppet —自动化部署工具详解

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/puppet
auth.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'],
            ...
    }

subscribe

B 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,
        ...
    }
  • 示例
#定义父类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

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
发布了56 篇原创文章 · 获赞 33 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章