1  概述


模板文件是在puppet模块下面templates目录中以”.erb”结尾的文件,puppet模板主要用于文件,例如各种服务的配置文件,相同的服务,不同的配置就可以考虑使用模板文件。

模块是Puppet自包含的代码和数据集合。绝大多数的清单都可以放到模块中,唯一的例外是manifests下的主清单site.pp,包含站点级和节点级的代码。

本文将结合例子介绍如何使用模板和模块


2  模板


2.1 概念介绍


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'),
}

#注意,content要根据template来处理

文本文件/PATH/TO/ERB_FILE中内嵌变量替换机制:这个格式要注意,如下:


<%= @VARIABLE_NAME %>

2.2 例子 


例1  配置nginx模板

准备nginx配置模板,修改nginx配置的work_processes为变量

vim  nginx.conf.erb
worker_processes <%= @processorcount %>;

定义类

vim nginx.pp
class nginx {
    package{'nginx':
        ensure => latest;
    } ->
    file{'/etc/nginx/nginx.conf':
        ensure => file,
        content => template('/root/nginx.conf.erb'),
    } ~>
    service{'nginx':
        ensure => running,
    }   
}
include nginx

执行脚本


puppet apply nginx.pp

例2  配置redis从节点

修改从的redis配置文件为模板文件,注意,用class来传递变量,调用类

vim redis_slave.pp
class redis {
    package{'redis':
        ensure => latest,
    }   
    service{'redis':
        ensure => running,
        enable => true,
        hasrestart => true,
        restart => 'service redis restart',
        require => Package['redis'],
    }   
}
class redis::slave($masterip,$masterport='6379') inherits redis {
    file{'/etc/redis.conf':
        ensure => file,
        content => template('/root/puppet/redis.module/redis-slave.conf.erb'),
        owner => redis,
        group => root,
        require => Package['redis'],
    }   
    Service['redis'] {
        restart => 'systemctl restart redis.service',
        subscribe => File['/etc/redis.conf'],
    }   
}
class{'redis::slave':
        masterip => '172.18.50.73';
}

修改配置文件为模板

vim redis-slave.conf.erb
slaveof <%= @masterip %> <%= @masterport %>

执行该脚本

puppet apply redis_slave.pp

3  模块


3.1  概念介绍


模块就是一个按约定的、预定义的层级结构存放了多个文件或子目录的目录,目录里的这些文件或子目录必须遵循一定格式的命名规范; 

puppet会在配置的路径下查找所需要的模块;

MODULES_NAME:

manifests/

init.pp

files/

templates/

lib/

spec/

tests/

模块名只能以小写字母开头,可以包含小写字母、数字和下划线;但不能使用”main"和"settings“;

manifests/

init.pp:必须一个类定义,类名称必须与模块名称相同;

files/:静态文件;

puppet URL:

puppet:///modules/MODULE_NAME/FILE_NAME #这里不需要指定绝对路径,因为路径是固定的

templates/:

tempate('MOD_NAME/TEMPLATE_FILE_NAME')

lib/:插件目录,常用于存储自定义的facts以及自定义类型;

spec/:类似于tests目录,存储lib/目录下插件的使用帮助和范例;

tests/:当前模块的使用帮助或使用范例文件;

注意:

1、puppet 3.8及以后的版本中,资源清单文件的文件名要与文件子类名保持一致,例如某子类名为“base_class::child_class”,其文件名应该为child_class.pp;

2、无需在资源清单文件中使用import语句;

3、manifests目录下可存在多个清单文件,每个清单文件包含一个类,其文件名同类名;

puppet config命令:

获取或设定puppet配置参数;

puppet config print [argument]

puppet查找模块文件的路径:modulepath

puppet config print modulepath

set更改参数的值,以下命令更改后直接保存在配置文件里

例子

puppet config set server master.sunny.com

查看配置文件/etc/puppet/puppet.conf ,[main]段多了如下一行

server = master.sunny.com

模块放置路径:/etc/puppet/modules

要共享自己编写的模块,可以放到puppet  forge上,这个网站:https://forgeapi.puppetlabs.com是用来存放模块

如在Puppet Forge中搜索redis模块

    puppet module search redis


3.2  例子  开发redis模块


参加模块相关目录,注意路径结构

mkdir -pv /etc/puppet/modules/redis/{manifests,files,templates,lib,spec,tests}

建议先在其他路径下,如/root下创建一个modules模块,等模板都编辑完成后在拷贝到/etc/puppet/modules下。

mkdir -pv /root/modules/redis/{manifests,files,templates,lib,spec,tests}

把静态文件放到files里,模板文件(erb格式)放到templates里

cp /root/puppet/redis.module/redis-master.conf /root/modules/redis/files/

cp /root/puppet/redis.module/redis-slave.conf.erb /root/modules/redis/templates/

在manifests下定义和模块名同名的类,在init.pp里,同时定义master.pp和slave.pp的子类,模块方式注意文件的路径的定义有简化的

格式 和绝对路径两种,因为在模块下,文件放置的路径是固定的,所以,用相对路径就可以查找到配置文件模板的路径

source 定义模板的路径

source => 'puppet:///modules/MOD_NAME/FILE_NAME',

例子

source => 'puppet:///modules/redis/redis-master.conf',

等价于写绝对路径

source => '/etc/puppet/modules/redis/files/redis-master.conf',

content定义模板的路径

格式 content  =>  template('MOD_NAME/ERB_FILE')

例子

content => template('redis/redis-slave.conf.erb'),

等价于写绝对路径

content => template('/etc/puppet/modules/redis/templates/redis-slave.conf.erb'),
vim /root/modules/redis/manifests/init.pp
class redis {
    package{'redis':
        ensure => latest,
    }   
    service {'redis':
        ensure => running,
        enable => true,
        hasrestart => true,
        restart => 'service redis restart',
        require => Package['redis'],
    }   
}
vim /root/modules/redis/manifests/master.pp
class redis::master inherits redis {
    file{'/etc/redis.conf':
        ensure => file,
        source => '/etc/puppet/modules/redis/files/redis-master.conf',
        owner => redis,
        group => root,
        require => Package['redis'],
    }   
    Service['redis']{
        restart => 'systemctl restart redis',
        subscribe => File['/etc/redis.conf'],
    }   
}

#slave配置文件,这里利用变量来传递参数

vim /root/modules/redis/manifests/slave.pp
class redis::slave($masterip,$masterport='6379') inherits redis {
    file{'/etc/redis.conf':
        ensure => file,
        content => template('/etc/puppet/modules/redis/templates/redis-slave.conf.erb'),
        owner => redis,
        group => root,
        require => Package['redis'],
    }   
    Service['redis']{
        restart => 'systemctl restart redis',
        subscribe => File['/etc/redis.conf'],
    }   
}

#注意修改配置文件如下

vim  /root/modules/redis/templates/redis-slave.conf.erb
slaveof <%= @masterip %> <%= @masterport %>

#目前目录结构如下

[root@CentOS7C modules]#tree

.

└── redis

    ├── files

    │   └── redis-master.conf

    ├── lib

    ├── manifests

    │   ├── init.pp

    │   ├── master.pp

    │   └── slave.pp

    ├── spec

    ├── templates

    │   └── redis-slave.conf.erb

    └── tests


文件都准备完成后,把redis整个模块放到对应的软件指定的目录/etc/puppet/modules/下

cp -r /root/modules/redis/ /etc/puppet/modules/

测试

查看模块

[root@CentOS7C ~]#puppet module list
/etc/puppet/modules
└── redis (???)
/usr/share/puppet/modules (no modules installed)

redis模块后面显示为???,为redis的相关元数据信息,用来描述模块的,但是显示异常,忽略该情况

声明类

为哪个主机调用这个类,这里演示为当前主机调用,没有跨主机

注意,调用是指明类名,而不是指明模块

测试调用基类

puppet apply -v --noop -d --test -e "include redis"

测试调用子类,注意slave子类有变量,需要传递值

puppet apply -v --noop -d --test -e "include redis::master"
puppet apply -v --noop -d --test -e "class {'redis::slave': masterip => '172.18.50.73', masterport => '6379',}"

执行

puppet apply  -e "include redis::master"
puppet apply  -e "class {'redis::slave': masterip => '172.18.50.73', masterport => '6379',}"