2017 11-24 puppet应用

作者: 楠人帮 | 来源:发表于2017-11-26 22:16 被阅读45次

    一.puppet介绍

    • (1)什么是puppet
      puppet是一种重量级自动化运维工具,实现自动化运维以及能够帮助系统管理员管理基础设施的整个生命周期。因此基于puppet可以实现自动化重复任务、快速部署关键性应用以及本地或云端完成主动管理变更和快速扩展架构规模等
      适用系统:Linux ,Unix,Windows
      和ansible的区别:ansible属于轻量级自动化运维系统,在一般的小型企业中应用广泛,而puppet属于重量级运维工具
    • (2)puppet开发语言
      puppet有自己的开发语言,遵循GPL协议(2.7.0-),基于ruby语言开发
      2.7.0以后使用(Apache 2.0 license)
      (3)puppet作用
      可以实现配置文件,设置用户,制定cron计划任务,安装软件包,管理软件系统等功能。puppet把这些系统实体称之为资源,puppet的设计目标是简化对这些资源的管理以及妥善处理资源间的依赖关系。puppet可以管理40多种资源
      例:file、group、user 、host、package、service、cron、exec、yum repo等
    • (3)puppet工作结构
      puppet采用C/S星状的结构,所有的客户端和一个或几个服务器交互。每个客户端周期的(默认半个小时)向服务器发送请求,获得其最新的配置信息,保证和该配置信息同步。每个puppet客户端每半小时(可以设置)连接一次服务器端, 下载最新的配置文件,并且严格按照配置文件来配置客户端. 配置完成以后,puppet客户端可以反馈给服务器端一个消息. 如果出错,也会给服务器端反馈一个消息.
      下载地址:https://yum.puppet.com
      官网地址:https://www.puppet.com
    • (4)puppet的工作模型
      1.单工作模型:手动应用清单(manifest)
      下载:yum install puppet(epel源),在centos6中的epel源没有该安装包
      主程序:/usr/bin/puppet
      配置文件:/etc/puppet/puppet.conf
      2.master/agent模型
      有agent端周期性的向master发送应用请求清单并应用于本地
      下载:
      master端: yum install puppet puppet-server
      agent端:yum install puppet

    二.puppet基本应用(单模型)

    (1)puppet的简单命令

    • help : Display Puppet help.
    • apply: Apply Puppet manifests locally
    • describe Display help about resource types


      搜狗截图20171126152439.png
    • agent: The puppet agent daemon
    • master: The puppet master daemon
    • module: Creates, installs and searches for modules on the Puppet Forge


      搜狗截图20171126153009.png

    (2)资源的定义

    向资源类型的属性赋值来实现,可称为资源类型实例化,定义了资源实例的文件(清单),manifest

    • 定义资源的语法:
      type {'title':
      attribute1 => value1,
      attribute2 => value2,
      }
      注意事项:type必须是小写字符,title是一个字符串,在同一类型中必须唯一
    • 资源属性的三个特殊属性:
      Namevar:简称为name
      ensure:资源的目标状态
      provider:指明资源的管理接口
      最常用的是ensure

    (3)最常见的几种资源的介绍与配置

    1.group

    主要属性:
    name:组名
    gid:组id
    system:是否为系统组
    ensure:目标状态
    members:成员用户

    示例:
    vim group.pp(建议.pp结尾便于区分)

    group{ 'mygrp':
        ensure => present,——设置的状态
        name   => mygrp,——组的名字
         system => true,——定义为系统组
       }
    

    配置完成后让清单生效
    puppet apply -v(显示过程) --noop(干跑,不生效) group.pp
    确定没错后,去掉--noop执行观察结果

    2.user

    属性:
    name:用户名;
    uid: UID;
    gid:基本组ID;
    groups:附加组,不能包含基本组;
    comment:注释;
    expiry:过期时间 ;
    home:家目录;
    shell:默认shell类型;
    system:是否为系统用户 ;
    ensure:present/absent;
    password:加密后的密码串;

    示例:
    vim user1.pp
    user{'user1':
    ensure => present,
    }
    其他都为默认状态
    vim user2.pp

    user{'myuser':
          ensure => present,
          name => user2,
          uid     => 3002,
          shell   => '/bin/tcsh',——指定shell类型默认为/bin/bash
          home   => '/tmp/user1',——指定家目录
          groups  => mygrp,——指定附加组
    }
    

    配置完成后执行puppet apply -v user1.pp和user2.pp
    查看结果


    搜狗截图20171126155953.png

    注意:也可以为同一个用户设置多个附加组,但是要定义之间的依赖关系才能生效
    重新 vim user2.pp

    group{'testgrp':
           ensure => present,
    }
    
    user{'myuser':
          ensure => present,
          name => user2,
          uid     => 3002,
          shell   => '/bin/tcsh',——指定shell类型默认为/bin/bash
          home   => '/tmp/user1',——指定家目录
          require =>  [Group['mygrp'],Group['testgrp']],——定义依赖关系时的Type的首字母必须大写
    
    }
    

    配置完成后还要执行 cat group.pp >> user2.pp,否则无法将mygrp设置为user2的附加组
    然后执行 puppet apply -v user2.pp生效


    搜狗截图20171126161400.png

    引入关系元参数的概念 before/require
    A before B: B依赖于A,定义在A资源中;
    {
    ...
    before => Type['B'],
    ...
    }
    B require A: B依赖于A,定义在B资源中;
    {
    ...
    require => Type['A'],
    ...
    }
    示例:vim user2.pp

     1   group{'testgrp':
      2     ensure => present,
      3     before => User['myuser'],——表示被user{'myuser'}所依赖
      4 }
      5 
      6 
      7 user{'myuser':
      8      ensure  => present,
      9      name    => 'user2',
     10      uid     => 3002,
     11      shell   =>  '/bin/tcsh',
     12      home    =>   '/tmp/user2',
     13      groups  =>  ['mygrp', 'testgrp'],
     14
     15 }
     16 
     17 group{ 'mygrp':
     18      ensure => present,
     19      name   => 'mygrp',
     20      system => true,
     21      before => User['myuser'],——表示被user{'myuser'}所依赖
     22 }
    

    3.package

    核心属性:
    ensure: installed ,present,latest,absent
    name :包名
    source:程序包的安装来源
    provider:指明安装方式

    示例:
    vim package.pp

    package{'redis':
         ensure  => latest,
    }
    

    4.service

    基本属性:
    ensure
    enable
    name
    path:目标路径
    hasrestart:是否启动重启功能,用true和false来区分
    restart:具体的重启的命令
    start
    stop
    status

    示例:
    vim redis.pp

    service {'redis':
         ensure => latest,
         enable => false,——开机不自启动
         hasrestart => true, ——开启重启功能
         restart   => 'systemctl restart redis',
         require => Pakage['redis']——表示依赖于package资源
    }
    package{'redis':
             ensure => latest,
    }
    

    puppet apply -v redis.pp
    表示一旦安装redis包后,自动开启redis服务

    5.file资源

    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:时间戳;

    • 示例
      vim file.pp
     file{'/etc/redis.conf':
          ensure => file,——目标状态为文件
          source => '/root/redis.conf',——定义的原路径
          owner  =>  'redis',——所有者
          group  =>  'root',——所属组
          mode  =>   '0644',——权限
       注意:因为在file中已经定义了目标路径的绝对路径,因此可以不再写path
    }
    

    为了效果明显,在执行puppet apply -v file.pp之前先cp /etc/redis.conf /root/
    vim /root/redis.conf
    将bind地址改为0.0.0.0
    然后执行puppet apply -v file.pp
    发现/etc/redis.conf中的bind地址改为0.0.0.0
    实现复制功能

    • 示例2:实现目录到目录的复制
      vim directory.pp
     1 file{'yum.repos.d':
      2    ensure  => directory,
      3    path    => '/tmp/yum.repos.d',
      4    source  => '/etc/yum.repos.d',
      5    recurse => true,——递归功能目的是将原目录中的文件也一并复制到目标目录下
      6 }
    
    搜狗截图20171125095541.png
    • 如果将文件复制到指定目录上——结果指定的目录仍然是文件
      vim mulu2.pp
    file {'test':
        ensure => directory,
        path     => '/tmp/test',
       source   => ['/etc/issue',  '/etc/group'],
    }
    ![搜狗截图20171125094440.png](http:https://img.haomeiwen.com/i6851471/5ff334a7c03c6b6a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    显示如图仍然是文件,并且只有一个生效
    * 示例3:定义link链接
    vim link.pp
    file{'redis.conf':
         ensure => link,
         path     => '/tmp/redis.conf',
         target   =.> '/etc/redis.conf',——定义目标,path指向target定义的路径
    }
    

    puppet apply -v link.pp


    搜狗截图20171125100154.png

    综上我们可以定义一个综合性的清单来实现安装redis,还要完成文件的复制的功能,从而触发redis服务重启
    vim redis.pp

    package{'redis':
       
          ensure => latest,  
          name   => 'redis',
    } 
    
    file{'redis.conf':
           ensure =>file,
           path     => '/etc/redis.conf',
           source => '/root/redis.conf',
           mode   => '0644',
           owner  => 'root',
           group   => 'redis',
           require => Package['redis'],
    }
    servcie{'redis':
           ensure => running
           name  => 'redis',
           hasrestart => true,
           restart      => 'systemctl restart redis',
           subscribe  => File['redis.conf'],——类似require,定义依赖关系
    }
    
    • subscribe:b依赖a,并且b监控a资源的变化产生的事件
      注意:也可以在file资源中加入notify => Service['redis'],(通知service资源本资源的变化)此时service中的subcribe可以注释掉
      为了效果显著可以将redis删除再执行
      puppet apply -v redis.pp
    • 在实际应用中也可将file中的require和service中的subscribe去掉,直接在package的最后加入->(表示package被file资源依赖),并在file最后加入~>(表示file资源既要先于service资源生效,并通知service资源自己因为变化而产生的事件)
    • 或者在redis.pp清单中的最后加入 Package['redis']->File['redis.conf']~>Service['redis']

    6.exec资源

    主要实现puppet对shell的调用,完成软件的安装
    属性:
    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:
    vim exec.pp

    exec{'makedir':
          command => 'mkdir /tmp/hi.dir',
          path          => '/bin:/bin/sbin:/usr/bin:/usr/sbin',——指定路径,否则无法执行command命令
         creates     =>  '/tmp/hi.dir',——不存在该路径时才执行command命令
    
    }
    

    puppet apply -v exec.pp


    搜狗截图20171125110400.png

    示例2
    vim exec2.pp

     exec{'createsuer':
           command => 'useradd user7',
             path    => '/bin:/sbin:/usr/bin:/usr/sbin',
             unless  => 'id user7',——当使用id命令找不到该用户时,才执行command命令
      }
    
    
    搜狗截图20171125110619.png

    示例3:
    vim exec3.pp定义触发安装zabbix-agent,zabbix-sender的触发条件

      exec{'installpkg':
           command => 'yum -y install zabbix-agent zabbix-sender',
                path    => '/bin:/sbin:/usr/bin:/usr/sbin',
                onlyif  => 'yum repolist |grep -i zabbix',定义触发command执行的命令
       }
    

    vim exec4.pp 实现备份

      file{'/etc/redis.conf':
           source => '/root/redis.conf',
           ensure => file,
       }
       
       exec{'backupfile':
       
           command => 'cp /etc/redis.conf  /backups/',
           path    => ['/bin','/sbin', '/usr/bin', 'usr/sbin'],
          refreshonly => true,
          subscribe => File['/etc/redis.conf'],
      }
    

    前提先创建backups这个目录
    执行 puppet apply -v exec4.pp

    7.cron资源

    属性
    command:要执行的任务;
    ensure:present/absent;
    hour:
    minute:
    monthday:
    month:
    weekday:
    user:以哪个用户的身份运行命令
    target:添加为哪个用户的任务
    name:cron job的名称;

    示例:
    vim cron.pp

    cron {'timesync':
           command => '/usr/sbin/ntpdate 172.18.0.1 &> /dev/null',——定义同步时间命令
        ensure => present,
        minute   => '/3',——每三分钟执行一次
        user      => 'root', ——以root身份运行
    }
    
    ###8.notify资源
    定义通知任务
    属性:
    message: 信息内容
     name: 信息名称
    示例:
    vim  notify.pp
    

    notify {'helloworld':
    message => 'hello everyone ,aolo',
    }


    搜狗截图20171126161400.png

    三.puppet变量

    (1)数据类型

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

    (2)正则表达式:

    (?<ENABLED OPTION>:<PATTERN>)
    (?-<DISABLED OPTION>:<PATTERN>)
    OPTIONS:
    i:忽略字符大小写;
    m:把.当换行符;
    x:忽略<PATTERN>中的空白字符
    (?i-mx:PATTERN)
    不能赋值给变量 ,仅能用在接受=或!操作符的位置;

    (3)puppet的变量种类

    facts:
    由facter提供;top scope;
    内建变量:
    master端变量
    $servername, $serverip, $serverversion
    agent端变量
    $clientcert, $clientversion, $environment
    parser变量
    $module_name
    用户自定义变量:
    变量有作用域,称为Scope;
    top scope: $::var_name
    node scope
    class scope
    使用facter -p来查看facts变量

    (4)puppet流程控制语句:

    if语句:
    if CONDITION {
    ...
    } else {
    ...
    }
    CONDITION的给定方式:
    (1) 变量
    (2) 比较表达式
    (3) 有返回值的函数
    示例:
    vim pkg.pp

      $pkgname='nginx'
    package {'installpkg':
            name => "$pkgname",
             ensure => latest,
    }
    或者
    $pkgname = 'nginx'
    package{"$pkgname":
    ensure  => latest,   
    }
    

    if语句

    vim if.pp

    if $osfamily == 'Debian' {——if $osfamily =~/(?i-mx:debian)/
            $apachename = 'apache2'
      
      }  else {
         $apachename = 'httpd'
      }
        package{"$apachename":
      
             ensure => latest,
     }
    

    以上为双分支写法,还可以定义多分支写法
    vim if2.pp

    if $osfamliy == 'Debian' {
            $apachename = 'apache2'
    } elsif   $osfamily == 'Windows'{
                  $apachename = 'apache'
    } else {
                $ apachename = 'httpd' 
    }
          package {" $anachename":
             ensure => latest,
    }
    

    case语句

    case CONTROL_EXPRESSION {
    case1: { ... }
    case2: { ... }
    case3: { ... }
    ...
    default: { ... }
    }

                 CONTROL_EXPRESSION:
                    (1) 变量
                    (2) 表达式 
                    (3) 有返回值的函数
                    
                各case的给定方式:
                    (1) 直接字串;
                    (2) 变量 
                    (3) 有返回值的函数
                    (4) 正则表达式模式;
                    (5) default 
    

    示例:
    vim case.pp

    case $osfamily{
    
           "Windows" : { $webpkg =  'apache' }
           /(?i-mx: debian)/:  {  $webpkg = 'apache2'  }
           default:  {  $webpkg = 'httpd' }
    }
    

    selector 语句

    CONTROL_VARIABLE ? {
    case1 => value1,
    case2 => value2,
    default => valueN,
    }
    CONTROL_VARIABLE的给定方法:
    (1) 变量
    (2) 有返回值的函数
    各case的给定方式:
    (1) 直接字串;
    (2) 变量
    (3) 有返回值的函数
    (4) 正则表达式模式;
    (5) default
    注意:不能使用列表格式;但可以是其它的selecor;
    示例:
    vim selector.pp

    $webpkg = $osfamily ? {
      "Windows"  => 'apache',
      /(?i-mx: debian)/ => 'apache2',
      default   =>  'htttpd',
    }
      package {"$webpkg":
           ensure => latest,
    }
    

    class(类)语句

    类:puppet中命名的代码模块,常用于定义一组通用目标的资源,可在puppet全局调用;
    类可以被继承,也可以包含子类;
    语法格式:
    class NAME {
    ...puppet code...
    }
    class NAME(parameter1, parameter2) {
    ...puppet code...
    }
    类代码只有声明后才会执行,调用方式:
    (1) include CLASS_NAME1, CLASS_NAME2, ...
    (2) class{'CLASS_NAME':
    attribute => value,
    }
    示例:
    vim class.pp

    class instweb{
           $webpkg =  $osfamily ? { 
           "Windows" => 'apache',
           /(?i-mx:debian)/  => 'apache2',
          default => 'httpd',
    }
      package { "$webpkg":
                 ensure => latest,
    }
    
    include instweb——调用class类,否则不生效
    

    class的综合应用
    vim class2.pp

     class dbserver ($pkg,$srv) {
                 package{"$pkg":
                      ensure => latest,
       
         }
      
              service{"$srv":
              ensure => running,
       
         }
      
      
     }
      
      if  $operatingsystem  == "CentOS" or $operatingsystem == "RedHat"{
          case $operatingsystemmajrelease {
            '7': { $pkgname = 'mariadb-server' $srvname='mariadb'}
            default: {  $pkgname = 'mysql-server' $srvname= 'mysqld' }
      
         }
      }
      class{'dbserver':——子类继承父类
      
            pkg => "$pkgname",
            srv => "$srvname",
      }
    

    class的类继承方法
    首先mkdir redis.modules/
    cd redis.modules/
    cp /etc/redis.conf ./redis-salve.conf
    cp /etc/redis.conf ./redis-master.conf
    实现redis的主从复制,先在172.18.254.242上进行配置,然后将redis.pp复制到172.18.250.89(作为主节点),再讲redis.conf复制到172.18.250.223(从节点)
    vim redis.pp

      1 class redis {
      2      package{'redis' :
      3        ensure => latest,
      4 
      5 }
      6 
      7 service{'redis':
      8 
      9      ensure => running,
     10      enable => true,
     11      hasrestart => true,
     12      restart => 'systemctl  restart redis ',
     13      require => Package['redis'],——定义依赖关系
     14    }
     15 
     16 
     17 }
     18    class redis::master inherits redis {
     19     file{'/etc/redis.conf':
     20 
     21       ensure  => file,
     22       source  => '/root/redis.module/redis-master.conf',
     23       owner   => redis,
     24       group   => root,
     25       require => Package['redis'],——依赖package
     26 }
     27 
     28    Service['redis'] {——在子类中为父类的资源新增属性或覆盖指定的属性的值:
     29 
     30    restart => 'systemctl restart redis.service',
     31 #   require +> File['/etc.redis.conf'],——代表覆盖父类资源
     32     subscribe => File['/etc/redis.conf'],
     33   }
     34 }
     35 
     36 
     37 class redis::slave inherits redis {
     38     file{'/etc/redis.conf':
     39 
     40       ensure  => file,
     41       source  => '/root/redis.module/redis-slave.conf',
     42       owner   => redis,
     43       group   => root,
     44       require => Package['redis'],
     45 }
     46 
     47    Service['redis'] {
     48 
     49    restart => 'systemctl restart redis.service',
     50 #   require +> File['/etc.redis.conf'],
     51     subscribe => File['/etc/redis.conf'],
     52   }
     53 }
     54 #   include redis::master
                                                          
    

    此时在主节点上执行
    只需要在最后一行中调用 include redis::master
    在从节点上执行 include redis:: slave
    为了效果显著在从节点上 vim redis.module/redis-slave.conf
    加入slaveof 172.18.250.89 6379
    在主从节点上安装puppet,执行puppet apply -v redis.conf
    此时vim /etc/redis.conf(在从节点上)


    搜狗截图20171125213958.png

    设置成功
    在主节点上redis-cli
    set key '' who am i''
    get key
    在从节点上也能显示"who am i"
    则证明主从复制成功

    四.puppet模板

    erb:模板语言,embedded ruby;
    puppet兼容的erb语法:
    https://docs.puppet.com/puppet/latest/reference/lang_template_erb.html
    file{'title':
    ensure => file,
    path =>
    content => template('/PATH/TO/ERB_FILE'),
    }
    文本文件中内嵌变量替换机制:
    <%= @VARIABLE_NAME %>

    示例:定义nginx类的调用,实现模板的调用erb

    mkdir nginx.module/
    mv nginx.conf nginx.conf.erb
    vim nginx.conf.erb


    搜狗截图20171126215917.png

    vim nginx.pp

     1 class nginx{
      2 
      3     package { 'nginx':
      4      ensure => latest,
      5 
      6 
      7 } ->
      8 file {'/etc/nginx/nginx.conf':
      9     ensure => file,
     10     content => template('/root/nginx.module/nginx.conf.erb'),——以content形式导入模板,相当于source
     11 
     12 
     13 } ~>
     14  service{'nginx':
     15 
     16       ensure => running,
     17    }
     18 }
     19 
     20 include nginx
    

    puppet apply -v nginx.pp
    执行完成后vim /etc/nginx/nginx.conf


    搜狗截图20171126220340.png

    在从节点上 cd redis.module/
    cp redis-slave.conf redis-slave.conf.erb
    vim redis.pp

    class redis {
         package{'redis' :
           ensure => latest,
    
    }
    
    service{'redis':
    
         ensure => running,
         enable => true,
         hasrestart => true,
         restart => 'systemctl  restart redis ',
         require => Package['redis'],
       }
    
    
    }
       class redis::master inherits redis {
        file{'/etc/redis.conf':
    
          ensure  => file,
          source  => '/root/redis.module/redis-master.conf',
          owner   => redis,
          group   => root,
          require => Package['redis'],
    }
    
       Service['redis'] {
    
       restart => 'systemctl restart redis.service',
    #   require +> File['/etc.redis.conf'],
        subscribe => File['/etc/redis.conf'],
      }
    }
    
    
    注意:class redis::slave($masterip,$masterport='6379') inherits redis {
        file{'/etc/redis.conf':
    
          ensure  => file,
        注意:  content  => template('/root/redis.module/redis-slave.conf.erb'),
          owner   => redis,
          group   => root,
          require => Package['redis'],
    }
    
       Service['redis'] {
    
       restart => 'systemctl restart redis.service',
    #   require +> File['/etc.redis.conf'],
        subscribe => File['/etc/redis.conf'],
      }
    }
    #include redis::slave——注释lnclude
    class{'redis::slave':
          masterip => '172.18.250.89',——直接调用子类
    }
    

    此配置是为了实现自动化对redis的主从复制
    因此为了使效果显著,在从节点上执行 rpm -e redis
    rm -rf /etc/redis.rpmconf
    此时再执行 puppet apply -v redis.conf


    搜狗截图20171125213801.png

    ss -ntl


    搜狗截图20171125213928.png
    vim /etc/redis.conf
    搜狗截图20171125213958.png

    相关文章

      网友评论

        本文标题:2017 11-24 puppet应用

        本文链接:https://www.haomeiwen.com/subject/awbqbxtx.html