柴少鹏的官方网站 技术在分享中进步,水平在学习中升华

puppet系列(三)类、变量以及属性

http://blog.51niux.com/?id=105和http://blog.51niux.com/?id=106 已经重记录了puppet的安装,命令,目录结构,配置文件,资源详解等。

这里呢,对于puppet的类,以及书写范式,以及正则等做一些记录。

puppet的注释支持两种风格,一种是shell注释风格#,一种是C语言风格注释/* */

一、类的介绍

class 类名。上一章已经大量了引用了类的知识。

1.1 无参数类和有参数类的区别

之前记录的都是无参数的类,如:class notifytest1::notify_hello{},就是class 类名{},然后{}里面定义各种资源,也是我们经常用到的一种方式。

有参数class类,就是有参数传入,不过不怎么常用,如下面的例子:

class apache_install ($stat = 'installed') {

         package {'apache':

                   ensure => $stat,       #这就是当执行的时候,installed的参数会传入给stat,这就是传参。

                    name => 'httpd',

           }

}

1.2 继承

puppet通过inherits关键字引入了继承的概念,继续可以减少重用代码,如集群初始化肯定是一样的,但是初始化完毕呢有的是要做web的,有的是要做代理的等,就是有相同的部分有不同的部分。

节点继承:

# cat  /etc/puppet/manifests/nodes/base.pp
node  base {
     include base_package
}
node /192.168.1.*/ inherits base {    
#正常的这里不应该是192.168.1什么什么,应该是主机名,如郑州web服务就是,zzidc.web*.uc什么什么,这里以IP比较醒目一点。这里的意思就是首先的所有192.168.1段的IP继承了base里面的类base_package操作,然后自身呢再执行一下类apache_install   。这里有一点不太清楚,不支持192.168.1.\d+这种写法,所以我就用了*这种写法。这里如果只是像某一个节点继承,如:'192.168.1.103'就单引号括起来。

     include apache_install
}

# cat /etc/puppet/modules/base_package/manifests/init.pp   #这里只是为了举个例子测试一下结果,正常的这里应该是一个exec和file资源,file资源负责将我们要安装基础包的脚本下发到每个要初始化的客户端,然后再通过exec来执行这个脚本来进行初始化的操作。
class base_package{
      package {'base':
             name => 'lrzsz',
             ensure => installed,
      }
}

# cat /etc/puppet/modules/apache_install/manifests/init.pp   #这里就是192.168.1.*自己本身的类了,执行apache的安装。

class apache_install{
       package{'apache':
              ensure => installed,
              name => 'httpd',
       }      
}

下面是客户端的操作截图:

图片.png

类的继承:

类继承也就是定义一个base类,然后其他的类来继承这个base类,如果其他类里面的参数跟base类里面有不一样的,那么就会去覆盖基础类的内容。现在不支持多重继承。

下面是引用权威指南里面的例子(最后/etc/passwd文件的的权限就是0644,属主是root,属组就变为了wheel,如果引用base::freebsd类的话。):

class base::linux{
   file {‘/etc/passwd’:
owner =>’root’,
group=>’root’,
mode=>’0644’,
 }
}
class base::freebsd inherits base::unix {
   file[‘/etc/passwd’] {
   group =>’wheel’,
}
}

博文来自:www.51niux.com

二、变量

2.1 变量介绍

变量是什么大家都很清楚,puppet里面变量名可以由字母、数字和下划线组成,且大小写敏感。

puppet变量必须以“$”为前缀,后接“=”进行复制,如file资源里面加内容,可以先定义一个变量:$content = "this is a content",双引号用于里面不是一个单纯的字符串,单引号就是将里面的内容单纯的作为一个字符串 ,然后file资源里面再让content => $content。再第二篇的file资源详解关于模板那里就有关于变量的操作举例,当变量包含再字符串里面的时候用{}括起来能更好的识别变量名,另外puppet里面变量也不能重复赋值。

2.2 变量作用域

变量并非在所有的代码范围中都是有效可用的,而限定这个变量使用有效范围就是作用域。同一个作用域中不可以声明相同的变量名。

top作用域:声明变量后可以再class类内核node节点内调用的作用域被称为top作用域,也可以称为全局作用域。

node作用域:在node节点中声明变量后只能在node节点中被调用,这种作用域被称为节点作用域。在多个节点中声明相同的变量时,同一时间只能有一个node节点被调用。

local作用域:变量声明后只能在class类内使用,这种域被称为local作用域或本地作用域。

作用域的优先级:

当相同的变量名出现在同一个代码文件中时,它的优先级是local作用域最高,node作用域次之,top作用域级别最低。

2.3 Facter变量

facter主要的内置变量:

# facter

architecture => x86_64      #CPU的位数,这里是64位的操作系统

blockdevice_sda_model => ST3300657SS  #硬盘型号,这里是希捷ST3300657SS

blockdevice_sda_size => 300000000000     #硬盘大小,这里是300G

hostname => localhost                 #系统主机名

interfaces => bond0,em1,em2,lo,p1p1,p1p2   #系统存在的网络接口

ipaddress => 192.168.1.103              #IP地址

is_virtual => false                  #是否是虚拟机,false代表不是,true代表是

kernel => Linux                    #内核版本

kernelrelease => 3.10.0-327.el7.x86_64  #内核版本

memoryfree => 53.25 GB    #系统内存剩余

memorysize => 62.75 GB    #系统总内存

operatingsystem => CentOS     #操作系统
operatingsystemmajrelease => 7    #操作系统系列
operatingsystemrelease => 7.2.1511   #操作系统具体版本

physicalprocessorcount => 2     #CPU物理数量

processorcount => 16    #CPU总核数

productname => PowerEdge R410  #服务器型号

puppetversion => 3.8.7   #puppet版本

rubyversion => 2.0.0  #ruby版本

selinux => false   #selinux默认是不是开启状态,false表示不开启,true表示默认开启

serialnumber => B7YB83X    #服务器的序列号

swapfree => 8.00 GB  #swap分区剩余

swapsize => 8.00 GB  #swap分区总大小

system_uptime => {"seconds"=>24109675, "hours"=>6697, "days"=>279, "uptime"=>"279 days"}  #系统的开机时间

uptime => 279 days    #uptime天数
uptime_days => 279    #uptime天数
uptime_hours => 6697   #uptime小时数
uptime_seconds => 24109675   #uptime秒数

2.4  puppet的内置变量

由puppet.conf配置文件定义,并在puppet代码文件中可以直接使用的变量称为内置变量。内置变量氛围agent端和master端。

agent端:

$enviromnent :  指定是生产环境、开发环境还是测试环境。默认是生成环境:production.

$clientcert : agent的certname信息。也就是agent的配置文件里面设置的自己的名称。

master端:

$servername :  master的fqdn

$serverip:master的IP

$module_name : master中的模块名

三、数据类型

3.1 字符串类型

字符串类型需要以双引号或单引号进行声明。puppet默认的数据类型就是字符串类型,不能使用Puppet关键字。这里有几个特殊的符号作为变量值时,需要进行转义:

\$ : $符号

\”: 双引号

\' : 单引号

\\ : 反斜杠

\n : 回车换行符

\r : 回车换行

\t  : tab键,一个tab键默认是7个空格

\s : 空格

3.2 数值类型(很少用)

数值类型是指定义成的数值形式的数据,这种数据可以直接进行加、减、乘、除等数学运算。

下面是puppet运算符的优先级从高到底排序:

! : 取反

In : 范围

* 和 / : 乘和除

- 和 + : 减和加

<<和>> : 左移和右移

== 和 != :等于和不同于

>= <=和>< :大于等于、小于等于和大于、小于

And : 与

Or : 或

3.3 正则表达式

在前面我们也简单用了下正则表达式,正则表达式我们在node哪里正则定义多主机的时候是很有用的,因为随着主机的众多不可能一个个的node定义下去。

[] : 用于描述范围(如[A-Z],表示范围在A~Z之间的大写字母)。

(): 用于包含正则表达式。

\w:用于描述字母或数字,相当于[0-9a-zA-Z]。

\W : 非字母或数字。

\s: 匹配[\t\n\r\f],其中(\t)为制表符、(\r)为回车符、(\n)为换行符、(\f)为换页符、(\s)表示匹配这些符号的简写方式。

\S :  匹配非空字符。

\d:匹配[0-9]数字。

\D :  匹配非数字。

\b : 匹配退格符。

\B : 非字边界。

*:前面元素出现0次或多次。

+:前面元素出现1次或多次。

{m,n}:前面匀速最少出现m此,最多出现n次.

?: 前面元素最多出现1次,等价于{0,1}。

|:与前面或后面表达式匹配。

i :表示忽略大小写。

博文来自:www.51niux.com

四、资源的公有属性

4.1 before和require资源公有属性

(这两个属性很重要的,有的时候好多资源都写到一个pp文件也就是一个class类里面,对于资源执行先后的顺序要求又比依赖的话,就要加上这两个共有属性来限定资源执行的顺序。)

before资源公有属性(当前者资源成功执行后,再通知下一个资源执行):

# cat /etc/puppet/manifests/nodes/test.pp    #这里定义一个node,去加载test1类./etc/puppet目录下的manifests和modules目录中文件要以.pp结尾
node  /192.168.1.\d+$/{ 
      include test1  
#include函数会根据puppet.conf文件中的modulepath参数搜索基础模块的模块目录路径并自动加载基础模块目录中的init.pp文件。
}

# cat /etc/puppet/modules/test1/manifests/init.pp   #首先我们创建的模块是存放在modules下面的,另外一定要以我们上面node里面include制定的类来创建以test1命名的目录。然后此目录下面的.pp文件都要放到manifests目录下面,并且一定要先用init.pp文件来定义文件之间的关联关系。

class test1{  #test1相当于基础类,下面的test1::beforetest1表示模块类

      include test1::beforetest1 #这就相当于给test1模块test1::beforetest1为test1模块加载了一个模块beforetest1,init.pp文件会加载beforetest1.pp文件

}

# cat /etc/puppet/modules/test1/manifests/beforetest1.pp  #因为init.pp文件加载的是beforetest1,所以文件也要是beforetest1.pp。不然找不到。

class test1::beforetest1{            #这里的类名就要跟init.pp里面定义的一致了。
      user{'test9':                   
         uid => 609,
         before => Exec["homedir"],        
#主要是这里,这里就是表示在上面的user资源的test9用户创建成功后,去调用一个exec资源,注意第一个字母要大写,标准格式就是。资源["标题"]。这里homedir就是exec资源的标题。
       }
       exec{"homedir":                             
  #这里的exec资源就对应着上面的调用。
            command => "mkdir /home/test9",
            path => ["/usr/bin","/usr/sbin","/bin","/sbin"],
       }
}

下面是客户端执行结果截图:

图片.png

require资源公有属性(在本资源执行之前,需要确认其他资源是否已经被成功执行):

# cat /etc/puppet/modules/test1/manifests/require1.pp   #做这些类文件更改,puppetmaster是不同重启服务的。
class test1::require1{
       file {'/opt/scripts':
          ensure => directory,
       }
       file {'/opt/scripts/test.sh':
          source => 'puppet://master.puppet/test1/test.sh',
          mode   => '755',
          require => File["/opt/scripts"],
       }
}

#这里就是定义了第一个file类,用来创建/opt/scripts目录,然后第二个file类是要发送一个test.sh文件到客户端的/opt/scripts目录下面去,所以我们就要确保此目录存在,所以require => File["/opt/scripts"] 就是在本资源'/opt/scripts/test.sh'发送脚本到客户端的操作执行之前,确保File["/opt/scripts"]执行了

下面是客户端的执行结果:

图片.png

4.2 notify和subscire资源共有属性

这两个的主要功能是资源与资源之间的状态的通知,notify资源共有属性为主动通知,subscire资源共有属性为被动通知。

notify资源公有属性(主要用来主动通知其他资源本资源的状态):

# cat /etc/puppet/modules/test1/manifests/notifytest1.pp
class test1::notifytest1{
      package {'ntp':
          ensure => installed,
          notify => Service['ntpd'],
      }
      service {'ntpd':
          ensure => running,
          enable => true,
      }
}

#package资源的ntp包如果安装成功,就会通知service资源,service资源就会启动ntpd服务并且添加到开机自启动,否则package资源失败,后面的service资源会跳过执行。

下面是我估计将DNS注释掉,搞的一个失败后的操作截图:

图片.png

subscire资源公有属性(与notify相反,用于被动通知,当依赖检查资源发生变化时,主动更新所在资源符状态。)

# cat /etc/puppet/modules/test1/manifests/subsciretest1.pp
class test1::subsciretest1{
      package {'ntp':
          ensure => installed,
      }
      service {'ntpd':
          ensure => running,
          enable => true,
          subscribe => Package['ntp'],
      }
}

#这个就是检查到Package的ntp安装成功,或者说ntp是存在的,service资源就会去发送变化,如果ntpd服务没有启动会让其启动。下面是测试效果:

图片.png

4.3 其他

其他的简单介绍一下,有兴趣可以自己查询一下。

还有两种还算比较常用是stage资源共有属性和audit资源共有属性。

还有两种描述方式:

->:表示资源之间的先后关闭,等同于before和require资源。如:File['/tmp/test1'] -> exec['bash_test']

~> : 用于表示资源之间的通知,等同于notify和subscire两个资源公有属性。如在两个资源之间加一行:~>,用来表示~>上面的资源执行成功后下面的资源才执行,不然就跳过。

五、条件判断语句

5.1 if...elsif...else语句

下面用一个很常用的例子,就是关闭防火墙功能,Centos6和Centos7的防火墙名称一个叫Iptables,一个叫firewalld。

# cat /etc/puppet/modules/test1/manifests/init.pp
class test1{
      if $operatingsystemmajrelease == '6'
         { include test1::centos6 }
      elsif $operatingsystemmajrelease == '7'
         { include test1::centos7 }
      else
         { include test1::default }
}

#这句话很好理解,就是如果客户端的系统大版本是6就加载centos6类文件,如果大版本是7,就加载centos7类文件,然后如果是其他的版本如Centos5等就加载默认的类文件。

# cat /etc/puppet/modules/test1/manifests/centos6.pp   #其他的都不粘贴了都是一个意思,另外标题那里可以相同,因为每次只会加载一种而不会同时三个都加载引起冲突。
class test1::centos6{
       service {'iptables':
          ensure => false,
          enable => false,
       }
}

#同时注意还有if...,if...else,if...elsif...elsif...else等语法。同时还可以与正则表达式匹配,如 if $hostname =~ /^zzidc.web\d+/{} 。或者通过in取范围方式,如if $operatingsystem in ["CentOS","Redhat"]{}

5.2 case语句

# cat /etc/puppet/modules/test1/manifests/init.pp   #还是关闭防火墙的操作,case语句就看着更简洁一点。
class test1{
      case $operatingsystemmajrelease {
          '7': { include test1::centos7 }
          '6','5' : { include test1::centos6 }
           default : { include test1::default }
      }
}

5.3 selector语句

它和C语言或Ruby语言中的三元运算类似,意思是在两个选项中任选其中一个赋值。

# cat /etc/puppet/modules/test1/manifests/iptables_off.pp
class test1::iptables_off {
            service{'iptables_off':
            name => $operatingsystemmajrelease ? {
                    '7' => 'firewalld',
                   /(6|5)/ => 'iptables',
                    default => 'iptables',
             },   
            ensure => false,
            enable => false,
            }
}

#这种就用于赋值了,name根据大版本来赋值,如果大版本是7,那么name就是firewalld,如果大版本是6或者5,那么守护程序名称就是iptables,剩下的走默认也是iptables。

作者:忙碌的柴少 分类:puppet系列 浏览:2959 评论:0
留言列表
发表评论
来宾的头像