T O P

[资源分享]     自动化运维工具之Puppet变量、正则表达式、流程控制、类和模板

  • By - 楼主

  • 2020-12-04 00:00:11
  •   前文我们了解了puppet的file、exec、cron、notify这四种核心资源类型的使用以及资源见定义通知/订阅关系,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/14073437.html;今天我们来了解下puppet中的变量、正则表达式和条件判断的相关话题;

      puppet中的变量

      在puppet中变量的定义和使用都是要加“$”,比如定义变量$webserver=nginx;则表示把nginx这个字符串复制给$webserver这个变量;引用变量直接使用$webserver即可;在puppet中赋值操作符为“=”,表示把等号右边边的值赋给左边的变量,任何正常数据类型(非正则)的值都可以赋予puppet中的变量,比如字符串、数值、布尔值、数组、hash以及特殊的undef值(即变量未赋值);

      puppet中的数据类型

        字符型:非结构化的文本字符串,可以使用引号,也可以不使用引号;单引号表示强引用,双引号表示弱引用;所谓强引用表示变量不会替换,弱引用表示能够进行变量替换;字符型值是支持用转义符;

        数字型:可为整数或浮点数,不过,puppet只有在数值上下文才把数值当作数值型对待,其他情况一律以字符型处理;比如进行加减乘除等运算时,它会把数值型值当作数值进行计算;

        数组:数组值为中括号“[]”中的以逗号分隔的项目列表,最后一个项目后面可以没有逗号;数组中的元素可以为任意可用数据类型,包括hash或其他数组,数组中的元素为数组,我们把这样的数组叫多维数组;数组的索引为从0开始的整数,也可以使用负数索引;

        布尔型:true和false,不能加任何引号;if语句的测试条件和比较表达式都会返回布尔型值,另外,其他数据类型也可以自动转换为布尔型值,如字符串,空串为false,非空则true;数值型就是0为false,非0为true等等;

        undef:从未被声明的变量的值类型即为undef;也可手动为某变量赋予undef值,即直接使用不加引号的undef字符串;有点类似shell中的unset;

        hash:即为外键值数据类型,键和值之间使用“=>”分隔,键值对定义在“{}”中,彼此间以逗号分隔;其键为字符型数据,而值可以为puppet中支持的任意数据类型;访问hash类型的数据元素要使用“键”当作索引进行访问;

      puppet中变量作用域

      提示:所谓变量作用域表示变量的使用生效的范围,在puppet中作用域可用于限定变量及资源默认属性的作用范围;但不能用于限定资源名称及资源引用的生效范围;任何给定的scope都可以访问它自己的内容,以及接收来自于其父scope、节点scope以及top scope的内容;简单讲就是作用域小的可以引用作用域大的变量,也可以更改作用域大的变量的值;但是作用域大的不能操作作用域小的变量;如上图所示,top scope仅能访问直接的变量和属性默认值;node scope能访问自己的及top scope的变量和属性默认值;example::parent,example::other和example::four能访问自己的以及节点scope和top scope的变量和默认值;如果要访问非当前scope中的变量,则需要通过完全限制名称进行;如$vhostdir=$apache::params::vhostdir;这里需要注意一点,如果top scope的名称为空,如要引用其变量可以使用类似$::sofamily的方式进行引用;

      puppet中的内建变量

      在puppet中变量来源可以从facter,agent,master,解释器以及用户自定义的变量;其中facter是一个工具,它可以收集系统信息,规范化之后存放在一系列变量中,并传递给puppet;facter的各变量是top scope的变量,这意味着,可以在各个manifest中直接通过${fact name}访问所需的fact变量;查看系统fact变量有哪些,可以使用facter -p输出fact变量;agent端的变量常用的有$environment这表示agent端的环境变量,$clientcert表示agent端的证书;$clientversion表示agent puppet的版本信息;master 端常用变量有$servername,该变量表示服务端名称;$serverip服务端ip,$serverversion服务端puppet的版本信息;解释器中的变量$module_name表示正在执行的模块名称;这里需要注意agent和master的内建变量只有在master/agent这种模型中才有效,单机模型无效;

      puppet中常用的操作符

    操作符 描述 操作符 描述 操作符 描述
    == 等于 =~ 正则模式匹配 +
    != 不等于 !~ 正则模式不匹配 -
    < 小于 in 成员关系判定 *
    > 大于 and /
    <= 小于等于 or << 左移位
    >= 大于等于 ! >> 右移位

     

     

     

     

     

     

     

     

     

      puppet中的正则表达式

      正则表达式在puppet中属于非标准的数据类型,不能赋值给变量,仅能用于有限的几个接受正则表达式的地方使用,即接受使用“=~”或“!~”匹配操作符的位置,通常包含case语句中的selector,以及节点名称匹配的位置;它不能传递给函数或用于资源属性定义;

      puppet中正则表达式的两个特殊使用方式

      (?<ENABLED OPTION>:<PATTERN>)和(?-<DISABLED OPTION>:<PATTERN>),其中OPTIONS有i,m,x,其中i表示忽略字符大小写;m表示把“.”点号当作换行符;x表示忽略<PATTERN>中的空白字符;比如(?imx:PATTENR)就表示忽略字符大小写,把PATTERN中的点号当作换行符,并且忽略其中的空白字符;(?i-mx:PATTERN)表示忽略字符大小写,不把pattern中的点号当换行符,也不忽略pattern中的空白字符;

      puppet中的流程控制

      所谓流程控制就是在puppet代码中加入了条件控制语句,如if语句,case语句,selector语句,只有满足了条件才会执行对应的代码;if语句语法如下

      单分支

    if  CONDITION {
        ...
    }
    

      双分支

    if  CONDITION {
        ...
    } else {
        ...
    }
    

      多分支

    if  CONDITION {
        ...
    } elsif {
        ...
    } else{
        ...
    }
    

      提示:条件可以是变量,比较表达式或有返回值的函数;

      示例:通过判断不同操作系统来安装apache

    [root@node12 ~]# cat if.pp
    if $operatingsystem == "CentOS" {
            $webserver = "httpd"
    }elsif $operatingsystem == "Ubuntu" {
            $webserver = "apache2"
    }else{
            $webserver = "apahce"
    }
    
    package{"$webserver":
            ensure  => installed,
    }
    [root@node12 ~]# 
    

      提示:以上资源清单表示,通过判断$operatingsystem这个变量的值来赋值$webserver的值;如果对应$operatingsystem的值为CentOS,则$webserver的值就为httpd,如果是Ubuntu $webserver的值就为apache2,如果前两个条件都不满足,则$webserver的值为apache;然后通过$webserver这个变量的值来安装包;

      应用资源清单

    [root@node12 ~]# puppet apply -v --noop if.pp
    Notice: Compiled catalog for node12.test.org in environment production in 0.65 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 '1606994860'
    Notice: /Stage[main]/Main/Package[httpd]/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
    Notice: Finished catalog run in 1.24 seconds
    [root@node12 ~]# puppet apply -v  if.pp      
    Notice: Compiled catalog for node12.test.org in environment production in 0.18 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 '1606994891'
    Notice: /Stage[main]/Main/Package[httpd]/ensure: created
    Notice: Finished catalog run in 7.99 seconds
    [root@node12 ~]# 
    

      提示:从上述信息中可以看到,当前安装的包上httpd;原因是本机是一个centos系统;$operatingsystem这个变量是一个fact变量,主要保存操作系统名称;

      示例:if语句中使用正则表达式

    [root@node12 ~]# cat if.pp
    if $operatingsystem =~/(?i-mx:(centos|redhat))/{
            $webserver = "httpd"
    }elsif $operatingsystem =~ /(?i-mx:(ubuntu|debian))/{
            $webserver = "apache2"
    }else{
            $webserver = "apahce"
    }
    
    package{"$webserver":
            ensure  => installed,
    }
    [root@node12 ~]# 
    

      提示:使用正则表达式需要将正则表达式写在“//”之间;

      卸载httpd,应用资源清单

    [root@node12 ~]# rpm -e httpd
    [root@node12 ~]# puppet apply -v  if.pp
    Notice: Compiled catalog for node12.test.org in environment production in 0.18 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 '1606995583'
    Notice: /Stage[main]/Main/Package[httpd]/ensure: created
    Notice: Finished catalog run in 1.86 seconds
    [root@node12 ~]# 
    

      提示:可以看到应用清单并没有报错,提示httpd已经创建;

      puppet中的case语句

      语法

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

      提示:case语句和if语句的作用是类似的,case语句会从多个代码块中选择一个分支执行,只要其中任意一个case的值满足对应的控制表达式,就执行对应case后面的代码块,然后退出;如果所有case都不满足,则执行default对应的代码块;这里的控制表达式可以是变量,可以是比较表达式,也可以是有返回值的函数;case可以是字符串,正则表达式,变量,有返回值的函数和default;

      示例

    [root@node12 ~]# cat case.pp
    case $osfamily {
            "RedHat":{ $webserver="httpd" }
            /(?i-mx:debian)/:{ $webserver="apache2" }
            default:{ $webserver="apache" }
    }
    
    package{"$webserver":
            ensure  => installed,
    }
    [root@node12 ~]# 
    

      卸载httpd,执行资源清单,看看httpd是否会被安装?

    [root@node12 ~]# rpm -e httpd
    [root@node12 ~]# puppet apply -v  case.pp 
    Notice: Compiled catalog for node12.test.org in environment production in 0.18 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 '1606996150'
    Notice: /Stage[main]/Main/Package[httpd]/ensure: created
    Notice: Finished catalog run in 1.82 seconds
    [root@node12 ~]# rpm -q httpd
    httpd-2.4.6-97.el7.centos.x86_64
    [root@node12 ~]# 
    

      提示:可以看到httpd可以正常的安装;

      selector语句

      语法

    CONTROL_VARIABLE ? {
        case1 => value1,
        case2 => value2,
        ...
        default => valueN,
    }
    

      提示:整个selector语句会被当作一个单独的值,puppet会将控制变量按列出的次序依次与每个case进行比较,并在遇到一个匹配的case后,将其值作为整个语句的值进行返回,并忽略后面的其他case;控制变量与各case比较的方式和case语句相同,但如果没有任何一个case与控制变量匹配,puppet在编译时将报错,因此,我们在使用selector必须提供一个default case;控制变量只能是一个变量或一个有返回值的函数,不能使用表达式;各个case的值可以是字符串,变量,有返回值的函数,正则表达式或default;

      示例

    [root@node12 ~]# cat selector.pp
    $pkgname = $operatingsystem ? {
            /(?i-mx:(ubuntu|debian))/       => 'apache2',
            /(?i-mx:(redhat|fedora|centos))/        => 'httpd',
            default => 'apache',
    }
    package{"$pkgname":
            ensure  => installed,
    }
    [root@node12 ~]# 
    

      卸载httpd,应用资源清单

    [root@node12 ~]# rpm -e httpd
    [root@node12 ~]# puppet apply -v --noop selector.pp
    Notice: Compiled catalog for node12.test.org in environment production in 0.18 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 '1606997882'
    Notice: /Stage[main]/Main/Package[httpd]/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
    Notice: Finished catalog run in 0.08 seconds
    [root@node12 ~]# puppet apply -v  selector.pp      
    Notice: Compiled catalog for node12.test.org in environment production in 0.18 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 '1606997889'
    Notice: /Stage[main]/Main/Package[httpd]/ensure: created
    Notice: Finished catalog run in 1.96 seconds
    [root@node12 ~]# rpm -q httpd
    httpd-2.4.6-97.el7.centos.x86_64
    [root@node12 ~]# 
    

      提示:可以看到httpd通过使用selector的方式定义的资源清单一样可以正常安装;

      puppet中的类

      类是用于同于目标的一组资源,因此,它是命名的代码块,在某一个位置创建之后可在puppet全局使用;puppet中的类和其他编程语言中的类的功能很类似,puppet中的类可被继承,也可以有子类;

      类的定义语法

    class class_name($var1=value1,$var2=value2){
        ... puppet code ...
    }
    

      提示:class是关键字,class_name是类名,类名只能以小写字母开头,可以包含小写字母,数字,下划线;小括号里是定义类的形参,每个形参可以有默认值,也可以没有,多个形参用逗号隔开;大括号里写puppet的代码;

      示例:定义一个apache的类

    [root@node12 ~]# cat apache.pp
    class apache {
            package{"httpd":
                    ensure  => installed,
            }
            service{"httpd":
                    ensure  => running,
            }
    }
    [root@node12 ~]# 
    

      提示:以上清单中定义了一个apache的类,主要完成了安装包和启动服务;这里需要注意一点,类定义好以后,如果我们不声明类,则它不会执行,有点类似函数一样,要向让类执行,我们需要声明类;

      在puppet中类的声明常用的方式有两种,第一种是使用include关键字+类名;第二种是类似定义资源一样来声明类,其中资源类型为class,title必须为类名,这种方式通常用于有参数的类的声明;

      示例:使用include关键字+类名声明类

    [root@node12 ~]# cat apache.pp
    class apache {
            package{"httpd":
                    ensure  => installed,
            }
            service{"httpd":
                    ensure  => running,
            }
    }
    
    include apache
    
    [root@node12 ~]# 
    

      执行清单

    [root@node12 ~]# ss -tnl
    State      Recv-Q Send-Q         Local Address:Port                        Peer Address:Port              
    LISTEN     0      128                        *:26379                                  *:*                  
    LISTEN     0      128                        *:22                                     *:*                  
    LISTEN     0      100                127.0.0.1:25                                     *:*                  
    LISTEN     0      128                        *:27017                                  *:*                  
    LISTEN     0      128                       :::22                                    :::*                  
    LISTEN     0      100                      ::1:25                                    :::*                  
    [root@node12 ~]# puppet apply -v --noop apache.pp 
    Notice: Compiled catalog for node12.test.org 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 '1607005266'
    Notice: /Stage[main]/Apache/Service[httpd]/ensure: current_value stopped, should be running (noop)
    Info: /Stage[main]/Apache/Service[httpd]: Unscheduling refresh on Service[httpd]
    Notice: Class[Apache]: Would have triggered 'refresh' from 1 events
    Notice: Stage[main]: Would have triggered 'refresh' from 1 events
    Notice: Finished catalog run in 0.13 seconds
    [root@node12 ~]# puppet apply -v  apache.pp       
    Notice: Compiled catalog for node12.test.org in environment production in 0.27 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 '1607005272'
    Notice: /Stage[main]/Apache/Service[httpd]/ensure: ensure changed 'stopped' to 'running'
    Info: /Stage[main]/Apache/Service[httpd]: Unscheduling refresh on Service[httpd]
    Notice: Finished catalog run in 0.22 seconds
    [root@node12 ~]# ss -tnl
    State      Recv-Q Send-Q         Local Address:Port                        Peer Address:Port              
    LISTEN     0      128                        *:26379                                  *:*                  
    LISTEN     0      128                        *:22                                     *:*                  
    LISTEN     0      100                127.0.0.1:25                                     *:*                  
    LISTEN     0      128                        *:27017                                  *:*                  
    LISTEN     0      128                       :::80                                    :::*                  
    LISTEN     0      128                       :::22                                    :::*                  
    LISTEN     0      100                      ::1:25                                    :::*                  
    [root@node12 ~]# 
    

      提示:可以看到httpd服务已经启动;

      示例:定义带参类

    [root@node12 ~]# cat class1.pp
    class dbserver ($pkg='mariadb-server',$svr='mariadb'){
            package{"$pkg":
                    ensure  => latest,
            }
            service{"$svr":
                    ensure  => running,
                    enable  => true,
            }
    }
    
    if $operatingsystem == "CentOS" or $operatingsystem == "RedHat"{
            case $operatingsystemmajrelease {
                    '7': { $pkgname='mariadb-server' $svrname='mariadb' }
                    default: { $pkgname='mysql-server' $svrname='mysqld' }
            }
    }
    
    class{"dbserver":
            pkg     => $pkgname,
            svr     => $svrname,
    }
    [root@node12 ~]# 
    

      提示:以上清单主要完成对于不同版本的centos,安装和启动不同的服务;在centos7上安装mariadb-server,启动mariadb服务;其他版本的centos安装mysql-server,启动mysqld服务;这里需要注意一点,声明类中的行参不能带$,我们可以理解为行参就是类的一个属性;

      执行清单

    [root@node12 ~]# ss -tnl
    State      Recv-Q Send-Q         Local Address:Port                        Peer Address:Port              
    LISTEN     0      128                        *:26379                                  *:*                  
    LISTEN     0      128                        *:22                                     *:*                  
    LISTEN     0      100                127.0.0.1:25                                     *:*                  
    LISTEN     0      128                        *:27017                                  *:*                  
    LISTEN     0      128                       :::80                                    :::*                  
    LISTEN     0      128                       :::22                                    :::*                  
    LISTEN     0      100                      ::1:25                                    :::*                  
    [root@node12 ~]# puppet apply -v --noop class1.pp 
    Notice: Compiled catalog for node12.test.org in environment production in 0.27 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 '1607007562'
    Notice: /Stage[main]/Dbserver/Service[mariadb]/ensure: current_value stopped, should be running (noop)
    Info: /Stage[main]/Dbserver/Service[mariadb]: Unscheduling refresh on Service[mariadb]
    Notice: Class[Dbserver]: Would have triggered 'refresh' from 1 events
    Notice: Stage[main]: Would have triggered 'refresh' from 1 events
    Notice: Finished catalog run in 0.47 seconds
    [root@node12 ~]# puppet apply -v  class1.pp       
    Notice: Compiled catalog for node12.test.org in environment production in 0.27 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 '1607007569'
    Notice: /Stage[main]/Dbserver/Service[mariadb]/ensure: ensure changed 'stopped' to 'running'
    Info: /Stage[main]/Dbserver/Service[mariadb]: Unscheduling refresh on Service[mariadb]
    Notice: Finished catalog run in 2.76 seconds
    [root@node12 ~]# ss -tnl
    State      Recv-Q Send-Q         Local Address:Port                        Peer Address:Port              
    LISTEN     0      128                        *:26379                                  *:*                  
    LISTEN     0      128                        *:22                                     *:*                  
    LISTEN     0      100                127.0.0.1:25                                     *:*                  
    LISTEN     0      128                        *:27017                                  *:*                  
    LISTEN     0      50                         *:3306                                   *:*                  
    LISTEN     0      128                       :::80                                    :::*                  
    LISTEN     0      128                       :::22                                    :::*                  
    LISTEN     0      100                      ::1:25                                    :::*                  
    [root@node12 ~]# systemctl is-enabled mariadb.service 
    enabled
    [root@node12 ~]# 
    

      提示:可以看到在当前系统上执行清单,启动了mariadb;

      类的继承

      类的继承是子类继承父类中的所有功能代码,它可以对父类中的所有属性进行修改,其定义语法如下

    class childer_class_name inherits parent_class_name{
        ...puppet code ...
    }
    

      提示:子类名称需使用完全限定名称,比如父类是apache,子类名可以写成apache::web;类似这种;inherits是关键字表示继承之意,后面加父类名称;

      示例

    [root@node12 ~]# cat redis.pp
    class redis{
            package{"redis":
                    ensure  => installed,
            }
            service{"redis":
                    ensure  => running,
                    enable  => true,
                    hasrestart      => true,
                    restart => 'service redis restart',
            }
    }
    
    class redis::master inherits redis {
            file{"/etc/redis.conf":
                    ensure  => file,
                    source  => '/root/redis-master.conf',
            }
            Service["redis"]{
                    subscribe       => File["/etc/redis.conf"],
                    restart => 'systemctl restart redis'
            }
    }
    
    include redis::master
    [root@node12 ~]# 
    

      提示:以上清单定义了两个类,一个是父类名为reids,另一个为子类名为redis::master;子类继承父类,并在其基础上新增了file资源以及增加了service资源的订阅关系;

      本地redis-master.conf配置文件内容

    [root@node12 ~]# cat /root/redis-master.conf 
    bind 0.0.0.0
    protected-mode yes
    port 6379
    tcp-backlog 511
    timeout 0
    tcp-keepalive 300
    daemonize no
    supervised no
    pidfile /var/run/redis_6379.pid
    loglevel notice
    logfile /var/log/redis/redis.log
    databases 16
    save 900 1
    save 300 10
    save 60 10000
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename dump.rdb
    dir /var/lib/redis
    slave-serve-stale-data yes
    slave-read-only yes
    repl-diskless-sync no
    repl-diskless-sync-delay 5
    repl-disable-tcp-nodelay no
    slave-priority 100
    appendonly no
    appendfilename "appendonly.aof"
    appendfsync everysec
    no-appendfsync-on-rewrite no
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    aof-load-truncated yes
    lua-time-limit 5000
    slowlog-log-slower-than 10000
    slowlog-max-len 128
    latency-monitor-threshold 0
    notify-keyspace-events ""
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64
    list-max-ziplist-size -2
    list-compress-depth 0
    set-max-intset-entries 512
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
    hll-sparse-max-bytes 3000
    activerehashing yes
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit slave 256mb 64mb 60
    client-output-buffer-limit pubsub 32mb 8mb 60
    hz 10
    aof-rewrite-incremental-fsync yes
    [root@node12 ~]# 
    

      执行清单,看看redis是否会监听在本机所有地址的6379端口?

    [root@node12 ~]# ss -tnl
    State       Recv-Q Send-Q       Local Address:Port                      Peer Address:Port              
    LISTEN      0      128                      *:22                                   *:*                  
    LISTEN      0      100              127.0.0.1:25                                   *:*                  
    LISTEN      0      128                      *:27017                                *:*                  
    LISTEN      0      50                       *:3306                                 *:*                  
    LISTEN      0      128                     :::80                                  :::*                  
    LISTEN      0      128                     :::22                                  :::*                  
    LISTEN      0      100                    ::1:25                                  :::*                  
    [root@node12 ~]# puppet apply -v --noop redis.pp 
    Notice: Compiled catalog for node12.test.org in environment production in 0.32 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 '1607008817'
    Notice: /Stage[main]/Redis::Master/File[/etc/redis.conf]/content: current_value {md5}cb9ab7d298a50a0de20077de143e3f73, should be {md5}12e59b058c0ef61ad52bcfa2d4de58ff (noop)
    Info: /Stage[main]/Redis::Master/File[/etc/redis.conf]: Scheduling refresh of Service[redis]
    Notice: Class[Redis::Master]: Would have triggered 'refresh' from 1 events
    Notice: /Stage[main]/Redis/Service[redis]/ensure: current_value stopped, should be running (noop)
    Info: /Stage[main]/Redis/Service[redis]: Unscheduling refresh on Service[redis]
    Notice: Class[Redis]: Would have triggered 'refresh' from 1 events
    Notice: Stage[main]: Would have triggered 'refresh' from 2 events
    Notice: Finished catalog run in 0.18 seconds
    [root@node12 ~]# puppet apply -v  redis.pp       
    Notice: Compiled catalog for node12.test.org in environment production in 0.33 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 '1607008824'
    Info: /Stage[main]/Redis::Master/File[/etc/redis.conf]: Filebucketed /etc/redis.conf to puppet with sum cb9ab7d298a50a0de20077de143e3f73
    Notice: /Stage[main]/Redis::Master/File[/etc/redis.conf]/content: content changed '{md5}cb9ab7d298a50a0de20077de143e3f73' to '{md5}12e59b058c0ef61ad52bcfa2d4de58ff'
    Info: /Stage[main]/Redis::Master/File[/etc/redis.conf]: Scheduling refresh of Service[redis]
    Notice: /Stage[main]/Redis/Service[redis]/ensure: ensure changed 'stopped' to 'running'
    Info: /Stage[main]/Redis/Service[redis]: Unscheduling refresh on Service[redis]
    Notice: Finished catalog run in 0.13 seconds
    [root@node12 ~]# ss -tnl
    State       Recv-Q Send-Q       Local Address:Port                      Peer Address:Port              
    LISTEN      0      128                      *:6379                                 *:*                  
    LISTEN      0      128                      *:22                                   *:*                  
    LISTEN      0      100              127.0.0.1:25                                   *:*                  
    LISTEN      0      128                      *:27017                                *:*                  
    LISTEN      0      50                       *:3306                                 *:*                  
    LISTEN      0      128                     :::80                                  :::*                  
    LISTEN      0      128                     :::22                                  :::*                  
    LISTEN      0      100                    ::1:25                                  :::*                  
    [root@node12 ~]# 
    

      提示:可以看到redis监听在本机任何地址的6379端口;

      模板

      puppet中的模板和ansible中的模板功能很类似,主要用在为一些服务提供配置文件模板,不同于ansible中的模板,puppet中的模板使用的erb模板语言,ansible使用的是jinja2模板语言;在puppet中使用模板的语法如下

    file{'title':
        ensure	=> file,
        content	=> template('/PATH/TO/ERB_FILE'),
    }
    

      提示:在复制配置文件时,指定源需使用content来指定,并且调用内建函数template来指定要复制的源文件,通常这个源文件就是一个模板配置文件;

      在模板文件中使用内嵌的变量替换机制,其语法如下

    <%= @VARIABLE_NAME %>
    

      提示:我们需要把要替换的值用上述变量的方式代替即可;

      示例:替换redis监听地址

    [root@node12 ~]# grep ^bind redis-master.conf.erb
    bind <%= @ipaddress %>
    [root@node12 ~]# 
    

      提示:以上内容表示bind 后面的值为ipaddress这个变量的值;这个变量是fact变量,主要用于存放本机ip地址;

      定义资源清单

    [root@node12 ~]# cat redis.pp
    class redis{
            package{"redis":
                    ensure  => installed,
            }
            service{"redis":
                    ensure  => running,
                    enable  => true,
                    hasrestart      => true,
                    restart => 'service redis restart',
            }
    }
    
    class redis::master inherits redis {
            file{"/etc/redis.conf":
                    ensure  => file,
                    content => template('/root/redis-master.conf.erb'),
            }
            Service["redis"]{
                    subscribe       => File["/etc/redis.conf"],
                    restart => 'systemctl restart redis'
            }
    }
    
    include redis::master
    [root@node12 ~]# 
    

      提示:以上清单在定义配置文件源文件时,指定content属性为内建函数template调用/root/redis-master.conf.erb;表示使用这个模板文件覆盖/etc/redis.conf文件内容;

      执行清单,看看对应redis是否监听在本机192.168.0.52这个地址上呢?

    [root@node12 ~]# ss -tnl
    State       Recv-Q Send-Q       Local Address:Port                      Peer Address:Port              
    LISTEN      0      128                      *:6379                                 *:*                  
    LISTEN      0      128                      *:22                                   *:*                  
    LISTEN      0      100              127.0.0.1:25                                   *:*                  
    LISTEN      0      128                      *:27017                                *:*                  
    LISTEN      0      50                       *:3306                                 *:*                  
    LISTEN      0      128                     :::80                                  :::*                  
    LISTEN      0      128                     :::22                                  :::*                  
    LISTEN      0      100                    ::1:25                                  :::*                  
    [root@node12 ~]# puppet apply -v --noop redis.pp 
    Notice: Compiled catalog for node12.test.org in environment production in 0.33 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 '1607010053'
    Notice: /Stage[main]/Redis::Master/File[/etc/redis.conf]/content: current_value {md5}12e59b058c0ef61ad52bcfa2d4de58ff, should be {md5}52397ae299aa46fe4103654abd62f5fd (noop)
    Info: /Stage[main]/Redis::Master/File[/etc/redis.conf]: Scheduling refresh of Service[redis]
    Notice: Class[Redis::Master]: Would have triggered 'refresh' from 1 events
    Notice: /Stage[main]/Redis/Service[redis]: Would have triggered 'refresh' from 1 events
    Notice: Class[Redis]: Would have triggered 'refresh' from 1 events
    Notice: Stage[main]: Would have triggered 'refresh' from 2 events
    Notice: Finished catalog run in 0.12 seconds
    [root@node12 ~]# puppet apply -v  redis.pp       
    Notice: Compiled catalog for node12.test.org in environment production in 0.33 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 '1607010059'
    Info: FileBucket got a duplicate file {md5}12e59b058c0ef61ad52bcfa2d4de58ff
    Info: /Stage[main]/Redis::Master/File[/etc/redis.conf]: Filebucketed /etc/redis.conf to puppet with sum 12e59b058c0ef61ad52bcfa2d4de58ff
    Notice: /Stage[main]/Redis::Master/File[/etc/redis.conf]/content: content changed '{md5}12e59b058c0ef61ad52bcfa2d4de58ff' to '{md5}52397ae299aa46fe4103654abd62f5fd'
    Info: /Stage[main]/Redis::Master/File[/etc/redis.conf]: Scheduling refresh of Service[redis]
    Notice: /Stage[main]/Redis/Service[redis]: Triggered 'refresh' from 1 events
    Notice: Finished catalog run in 0.15 seconds
    [root@node12 ~]# ss -tnl
    State       Recv-Q Send-Q       Local Address:Port                      Peer Address:Port              
    LISTEN      0      128           192.168.0.52:6379                                 *:*                  
    LISTEN      0      128                      *:22                                   *:*                  
    LISTEN      0      100              127.0.0.1:25                                   *:*                  
    LISTEN      0      128                      *:27017                                *:*                  
    LISTEN      0      50                       *:3306                                 *:*                  
    LISTEN      0      128                     :::80                                  :::*                  
    LISTEN      0      128                     :::22                                  :::*                  
    LISTEN      0      100                    ::1:25                                  :::*                  
    [root@node12 ~]# grep ^bind /etc/redis.conf 
    bind 192.168.0.52
    [root@node12 ~]# 
    

      提示:可以看到对应redis已经监听在192.168.0.52这个地址,并且配置文件中的bing的值也是192.168.0.52;

      在模板中使用自定义变量

    [root@node12 ~]# grep -Ei "^bind|port" redis-master.conf.erb
    bind <%= @redis_bindip%>
    port <%= @redis_port %>
    [root@node12 ~]# 
    

      在资源中定义变量

    [root@node12 ~]# cat redis.pp
    class redis{
            package{"redis":
                    ensure  => installed,
            }
            service{"redis":
                    ensure  => running,
                    enable  => true,
                    hasrestart      => true,
                    restart => 'service redis restart',
            }
    }
    
    class redis::master($redis_bindip='0.0.0.0',$redis_port='6379') inherits redis {
            file{"/etc/redis.conf":
                    ensure  => file,
                    content => template('/root/redis-master.conf.erb'),
            }
            Service["redis"]{
                    subscribe       => File["/etc/redis.conf"],
                    restart => 'systemctl restart redis'
            }
    }
    
    class{"redis::master":
            redis_port      => '16379',
    }
    [root@node12 ~]# 
    

      提示;在该资源中声明类时,传递了redis_port这个形参的值为16379,默认的redis_bindip为0.0.0.0;

      执行清单,看看redis是否监听在本机所有地址的16379端口?

    [root@node12 ~]# puppet apply -v  redis.pp 
    Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
    Notice: Compiled catalog for node12.test.org in environment production in 0.38 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 '1607010599'
    Info: /Stage[main]/Redis::Master/File[/etc/redis.conf]: Filebucketed /etc/redis.conf to puppet with sum 52397ae299aa46fe4103654abd62f5fd
    Notice: /Stage[main]/Redis::Master/File[/etc/redis.conf]/content: content changed '{md5}52397ae299aa46fe4103654abd62f5fd' to '{md5}13a04cb20de2d787e0e18c1c13560cab'
    Info: /Stage[main]/Redis::Master/File[/etc/redis.conf]: Scheduling refresh of Service[redis]
    Notice: /Stage[main]/Redis/Service[redis]: Triggered 'refresh' from 1 events
    Notice: Finished catalog run in 0.15 seconds
    [root@node12 ~]# ss -tnl
    State       Recv-Q Send-Q       Local Address:Port                      Peer Address:Port              
    LISTEN      0      128                      *:22                                   *:*                  
    LISTEN      0      100              127.0.0.1:25                                   *:*                  
    LISTEN      0      128                      *:16379                                *:*                  
    LISTEN      0      128                      *:27017                                *:*                  
    LISTEN      0      50                       *:3306                                 *:*                  
    LISTEN      0      128                     :::80                                  :::*                  
    LISTEN      0      128                     :::22                                  :::*                  
    LISTEN      0      100                    ::1:25                                  :::*                  
    [root@node12 ~]# grep -Ei "^bind|port" /etc/redis.conf 
    bind 0.0.0.0
    port 16379
    [root@node12 ~]# 
    

      提示:可以看到对应redis监听在本机所有地址的16379端口,并且对应配置文件也发生了相应的变量替换;

      以上就是puppet中的变量、正则表达式、流程控制、类和模板的使用和演示;有了这些基本编程元素的存在,使得puppet的资源清单变得灵活和通用,我们可以写一个资源清单适用几乎所有的不同的系统;

    本帖子中包含资源

    您需要 登录 才可以下载,没有帐号?立即注册