Chinaunix首页 | 论坛 | 博客
  • 博客访问: 630833
  • 博文数量: 244
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-27 09:53
个人简介

记录学习,记录成长

文章分类

全部博文(244)

我的朋友

分类: 系统运维

2016-06-24 00:10:00

一.类class
官方文档:

1.概述
类是用于通用目标的一组资源(只有在打算重复使用这段代码时才有必要声明成类),因此它是命名的代码块,在某个位置创建之后可以在puppet全局使用。

类可以放在模块中,通过声明的方式进行使用,而声明时通过include这么等函数就可以实现,或者声明可以使用一个类似于资源申报语法一样的语法来使用;

它类似与其他编程语言中类的功能,puppet的类可以被继承也可以包含子类。


2.语法格式
基础语法格式:
class class_name {
    puppet_code
}

类的名称只能以小写字母开头,可以包含小写字母、数字和下划线;

每个类都会引入一个新的变量作用域(scope),这意味着在任何时候访问类中的变量时,都得使用其完全限定名称(不过,在本地scope可以重新top scope中的变量赋予一个新值);

在manifest文件中定义的类不会直接被执行,它们需要实现声明后才能被执行(声明通常可以理解为调用);


示例:
不带参数的类:
class base::linux {
      file { '/etc/passwd':
            owner => 'root',
            group => 'root',
            mode  => '0644',
      }
      file { '/etc/shadow':
            owner => 'root',
            group => 'root',
            mode  => '0440',
      }
}

带参数的类:
同一个类在不同的OS上上可能会略有不同,因此需要通过获取相应系统的fact来实现有区别对待,然而万一相应的OS没有输出类所期望的fact或者是类依赖于非fact因素时,此机制将无法满足需求,此时就需要使用带参数的类来完成此类功能,在定义参数的类时,需要将参数声明在类名后的小括号内(参数可以有默认值,如果使用多个参数,彼此间要使用逗号分隔),在类的内部使用参数的方式同使用本地变量;

语法格式:
class  class_name (para1='val1',para2='val2'...) {
    puppet_code
}

例如:
class apache (String $version = 'latest') {
      package {'httpd':
            ensure => $version, # Using the class parameter from above
            before => File['/etc/httpd.conf'],
      }
      file {'/etc/httpd.conf':
            ensure  => file,
            owner   => 'httpd',
            content => template('apache/httpd.conf.erb'), # Template from a module
     }
      service {'httpd':
            ensure    => running,
            enable    => true,
            subscribe => File['/etc/httpd.conf'],
      }
}


3.声明(调用)类的方式
3.1使用标准方式include
接受:
        一个类的名称(如apache)或类的引用(如Class['apache']);
        一个以逗号分隔的类名称或类引用的列表;
        一个类名称或类引用的数组;
如:
        include base::linux

        include Class['base::linux'] # 声明一个类引用

        include base::linux, apache # 声明一个类名的列表

        $my_classes = ['base::linux', 'apache']
        include $my_classes # 声明一个类名的数组


3.2使用require(不是元属性的那个require)
通常需要在指定的代码段的位置使用require指明调用那个class就可以了,不常用;
如:
define apache::vhost (Integer $port, String $docroot, String $servername, String $vhost_name) {
 require apache
 ...
}
In the above example, Puppet will ensure that every resource in the apache class gets applied before every resource in any apache::vhost instance;

接受:
        一个类的名称(如apache)或类的引用(如Class['apache']);
        一个以逗号分隔的类名称或类引用的列表;
        一个类名称或类引用的数组;

3.3使用contain
例如:
class ntp {
     file { '/etc/ntp.conf':
     ...
    require => Package['ntp'],
    notify  => Class['ntp::service'],
     }
     contain ntp::service
     package { 'ntp':
     ...
     }
}
In the above example, any resource that forms a before or require relationship with class ntp will also be applied before or after class ntp::service, respectively.

接受:
        一个类的名称(如apache)或类的引用(如Class['apache']);
        一个以逗号分隔的类名称或类引用的列表;
        一个类名称或类引用的数组;

补充关于containing-classes的说明:

3.4使用hiera_include
例如:
# /etc/puppetlabs/puppet/hiera.yaml
...
hierarchy:
     - "%{::clientcert}"
     - common

# /etc/puppetlabs/code/hieradata/web01.example.com.yaml
---
classes:
     - apache
     - memcached
     - wordpress

# /etc/puppetlabs/code/hieradata/common.yaml
---
classes:
     - base::linux

# /etc/puppetlabs/code/environments/production/manifests/site.pp
    hiera_include(classes)

On the node web01.example.com in the production environment, the example above would declare the classes apache, memcached, wordpress, and base::linux. On other nodes, it would only declare base::linux.

hiera_include仅接受:
    a single lookup key

3.5使用resource-like declarations
即可以在声明一个类的时候像申报一个资源一样来调用一个类;

例如:
# Specifying the "version" parameter:
class {'apache':
     version => '2.2.21',
}
# Declaring a class with no parameters:
class {'base::linux':}

3.6使用ENC的机制来声明

二.类的继承与覆盖
puppet运维管理中,为了方便使用代码,我们通常都是写成类,而为更加好的重用代码,比如,在另外一个地方引出,你不可能又复制代码过去,这样对以后的修改或者说维护都很不方便,这时候,人们就把相同的代码给抽出来了,在别的地方需要用的时候(子类),直接引用(父类),继承父类的特性,后来为了更方便与扩展,可以允许(子类)有其它特性,也可以覆盖父类的特性,包括:
        继承资源属性
        覆盖资源属性:(=>)
        追加资源属性:(+>)


一般格式:
class  class_name  inherits  parent_class_name {
    puppet_code
}

一般的,子类的命名方式为"父类名::子类名"

例如:
class nginx {
    package {'nginx':
        ensure => present,
    }
    file {'/etc/nginx/nginx.conf':
        ensure => file,
        source => '/tmp/nginx/nginx.conf',
        require => Package['nginx'],
    }
}
class nginx_sub inherits nginx {
        file {'/etc/nginx/nginx.conf':
        ensure => present,
        source => '/usr/local/nginx/nginx.conf',
#在子类继承时,可以使用和父类同名同类型的资源(两者的file),在子类中赋值了和父类属性相同但值却不同
#时,子类的这个值会覆盖父类的值,即source为/usr/local/nginx/nginx.conf而不是/tmp/nginx/nginx.conf
        require +> Package['tomcat'],
#这里是追加属性;
    }
    service {'nginx':
        ensure => true,
        path => '/etc/rc.d/init.d/nginx',
    }
}
include nginx_sub #调用子类

可参考文章:




三.模块
官方文档:

1.概述
到目前为止,所做的资源申报、定义类、声明类等所有的功能都只是在一个manifest文件中实现,但这并非是最有效的基于puppet管理IT基础架构的方式;

实践中,我们一般需要把manifest文件分解成易于理解的结构,例如将类文件、配置文件甚至包括后面将提到的模块文件等分类存放,并且通过某种机制在必要时将它们整合起来,这种机制就叫做"模块",它有助于以结构化,层次化的方式使用puppet,而puppet则基于"模块自动装载器"完成模块装载;

从另一个角度来说,模块实际上就是一个按约定的、预定义的结构,存放了很多个文件或子目录的目录结构,目录里的这些文件或子目录必须遵循其命名规范,puppet会按照此种规范在特定位置查找所需的模块文件,不过这些特定目录也可以通过puppet的配置参数modulepath定义;

一句话就是:模块就是一个目录结构,目录名就是模块名


2.使用模块
只要在某模块中定义了一个类,就可以在任何manifest文件中使用它,puppet会自动去查找并装载包含了这个类的定义的manifest文件。因此,可以在puppet上提供多个模块,并按需要在manifest文件任意使用它们。

例如:
site.pp为站点清单,使用node指明有多少个节点,每个节点是如何调用类的
这里用的是site.pp,可以看下面完整的示例来了解如何使用模块的;
# /etc/puppetlabs/code/environments/production/manifests/site.pp
node default {
      include apache
     class {'ntp':
        enable => false;
     }
 apache::vhost {'personal_site':
        port    => 80,
        docroot => '/var/www/personal',
        options => 'Indexes MultiViews',
     }
}
要确保模块可用,可以将其放到puppet的参数modulepath定义的路径下,而且要确保有正确的模块名;
而模块存放的位置为:
[root@bogon puppet]# puppet  agent  --configprint  modulepath
/etc/puppet/modules:/usr/share/puppet/modules
如果想使用额外的目录,在puppet apply时需使用--modulepath指定模块位置;

3.模块目录结构布局
通常,模块只是一个特定的,可预见的目录结构:

        manifests
            init.pp
        files
        templates
        lib
        facts.d
        examples
        spec
其中:
MODULE_NAME:模块名称,也即模块目录名称;模块名称只能以小写字母开头,可以包含小写字母,数字和下划线;

manifests目录:清单存储目录,存放各种.pp清单文件,每个清单文件只包含一个类或一个定义的类,且建立的清单文件名与类名相同,如nginx::web对应web.pp清单文件,此中文件访问路径格式为:Module_Name::[SubDirectoryName::]ManifestFileName;

init.pp文件:包含一个一个单独的类定义,且类的名称必须与模块名相同,该文件必须存在;

files目录:文件存储目录,包含了一组静态文件,这些文件可被节点下载使用,每个文件的访问路径遵循puppet:///modules/MODULE_NAME/filename路径格式,如puppet:///modules/my_module/service.conf 会被映射到文件 my_module/files/service.conf;

templates目录:存储了清单文件用到的模板文件,其访问路径遵循template('ModuleName/TemplateName')格式;

lib目录:插件目录,常用于自定义fact及自定义资源类型等;

facts.d目录:包含额外的fact;

examples目录:当前模块的使用帮助或使用范例文件,类似如何声明当前模块中的类定义及定义的类型等;

spec目录:类似于examples目录的功能,只不过,其是为lib目录中定义的个插件提供使用范例和说明的;

完整示例如下:


使用时,就可以这样:
    puppet  apply  -e 'include my_module'    #应用init.pp清单
    puppet  apply  -e 'include my_module::other_class'    #应用子类

4.模块管理
puppet命令子命令module作用,具体使用方法可puppet module help:
module         Creates, installs and searches for modules on the Puppet Forge.

4.1在线模块下载地址:

4.2显示本地已安装的模块:
[root@bogon ~]# puppet module list
/etc/puppet/modules (no modules installed)
/usr/share/puppet/modules (no modules installed)

4.3搜索模块
[root@bogon ~]# puppet module search module_name
Notice: Searching ...
NAME                           DESCRIPTION            AUTHOR    KEYWORDS           
bobtfish-disable_caller_module_name  Private classes are hateful for user...  @bobtfish  private           


4.4安装模块
[root@bogon ~]# puppet module install module_name


5.具体示例
官方文档:

5.1列出可用的Nginx模块
[root@bogon nginx]# puppet module search nginx
Notice: Searching ...
NAME                        DESCRIPTION                           AUTHOR            KEYWORDS           
zooz-nginx                 Puppet module for nginx web server.   @zooz             nginx fedora
......


5.2下载Nginx模块(最好对应当前的puppet版本)
[root@bogon ~]# puppet module install zooz-nginx
Notice: Preparing to install into /etc/puppet/modules ...
Notice: Downloading from ...
Notice: Installing -- do not interrupt ...
/etc/puppet/modules
└── zooz-nginx (v0.0.3)

5.3查看安装的Nginx模块目录树
[root@bogon modules]# tree ./
./
└── nginx
    ├── files
    ├── lib
    │   ├── facter
    │   └── puppet
    │       ├── parser
    │       │   └── functions
    │       ├── provider
    │       └── type
    ├── manifests
    │   ├── init.pp
    │   ├── snippet_conf.pp
    │   ├── snippet.pp
    │   ├── upstream_conf.pp
    │   ├── upstream.pp
    │   ├── vhost_conf.pp
    │   └── vhost.pp
    ├── metadata.json
    ├── Modulefile
    ├── README.md
    ├── templates
    │   ├── nginx.conf.erb
    │   ├── upstream_conf.erb
    │   └── vhost_conf.erb
    └── tests

5.4测试
[root@bogon modules]# rpm -q nginx
package nginx is not installed

[root@bogon modules]# service nginx status
nginx: 未被识别的服务

[root@bogon ~]# puppet apply -e 'include nginx'
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Notice: Compiled catalog for bogon in environment production in 2.78 seconds
Notice: /Stage[main]/Nginx/Package[nginx]/ensure: created
Notice: /Stage[main]/Nginx/File[/etc/nginx/nginx.conf]/content: content changed '{md5}d9dfc198c249bb4ac341198a752b9458' to '{md5}219bec7aa8c070fd26bd62945a629e27'
Notice: /Stage[main]/Nginx/File[/etc/nginx/vhost.d]/ensure: created
Notice: /Stage[main]/Nginx/File[/etc/nginx/snippet.d]/ensure: created
Notice: /Stage[main]/Nginx/File[/var/cache/nginx]/ensure: created
Notice: /Stage[main]/Nginx/File[/etc/nginx/conf.d/default.conf]/ensure: removed
Notice: /Stage[main]/Nginx/Service[nginx]/ensure: ensure changed 'stopped' to 'running'
Notice: Finished catalog run in 16.45 seconds

验证:
[root@bogon ~]# service nginx status
nginx (pid  5936) 正在运行...

接着调用nginx的upstream子类:
[root@bogon ~]# puppet apply -e 'include nginx::upstream'
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Error: create_resources(): second argument must be a hash at /etc/puppet/modules/nginx/manifests/upstream.pp:20 on node bogon
Error: create_resources(): second argument must be a hash at /etc/puppet/modules/nginx/manifests/upstream.pp:20 on node bogon

要求upstream.pp文件的第20行的第二个参数必须是hash,额,暂时还不知道如何修改,不过只要修改好就能用了;

贴出来upstream和upstream_conf清单文件内容:
[root@bogon manifests]# cat upstream.pp 
class nginx::upstream inherits nginx {
      if $::nginx::upstream != 'undef' {   #20行
            create_resources(nginx::upstream_conf, hiera_hash('nginx::upstream', undef))
      }
}

[root@bogon manifests]# cat upstream_conf.pp
define nginx::upstream_conf(
  $server                  = undef,
  $ip_hash                 = false,
  $keepalive               = undef,
  $least_conn              = false,
  $check                   = undef,
  $check_http_send         = undef,
  $check_http_expect_alive = undef,) {
  $conf_template = 'upstream_conf.erb'
  if $server == undef {
        fail('At least one backend server must be specified.')
  }

  file { "${nginx::vhost_dir}/${title}_upstream.conf":
        ensure  => 'file',
        mode    => '0644',
        owner   => 'root',
        group   => $nginx::user,
        content => template("${module_name}/${conf_template}"),
        notify  => Service[$nginx::service_name],
      }
}


参考文章:
Linux自动化运维之puppet的类和模块 | Linux–不是那么难 



阅读(2526) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~