运维学习笔记-Puppet之Hiera初探

为什么使用Hiera?


Puppet中的manifest同时包含静态的代码(判断/循环逻辑,依赖关系,类定义,资源类型定义等等)和动态的数据(类声明时的参数值和资源声明时的属性值)。说代码是静态的是因为如果在设计阶段考虑比较全面,代码写成之后是很少变化的。但是数据要根据具体情况赋予不同的值。如果manifest设计的不是很灵活,比如某些数据被固化(hardcode)在文件中时,manifest就很难适用于新的场景,重用性就变差了。此外,为了追加/更新数据经常修改manifest也增加了出错的几率。

Puppet的解决方案是将动态的数据从manifest中剥离出来,这样manifest中只需留下代码,不必经常改动。

一种方式是我们要尽量使用Forge上的模块,或者将我们的manifest按同样方式设计,也就是将manifest内的资源的所有属性都通过类参数的形式暴露给用户,这样用户就可以通过传递不同的参数值来自由控制资源的最终状态。

另一种方式就是使用Hiera,也就是将manifest要使用的数据存储在外部的文件中,根据实际情况赋值。在编译catalog时,manifest向Hiera动态查询所需值的具体内容,然后加载到catalog中。

Hiera是如何存储数据的?


Hiera将数据以键/值对的方式存储在外部文件中。查询时,将键传给Hiera,然后Hiera返回对应值。

存储键/值对的文件被称作数据源(data source)文件。数据源文件可以是yaml或json格式,也可以自定义格式。下面是一个yaml格式的数据源的例子。每一行都是一个键/值对,值可以是数字,字符串,布尔值,数组或者hash,也支持数组和hash的嵌套。

# 值是数字

process_count: 10

# 值是字符串

apache-service: apache2

# 值是布尔

root_allowed: no

# 值是数组

apache-packages:

    – apache2

    – apache2-common

    – apache2-utils

# 值是hash

sshd_settings:

    root_allowed: "no"

    password_allowed: "yes"

# hash的另外一种写法

sshd_settings: {root_allowed: "no", password_allowed: "yes"}

json格式的数据源和其他细节请看这里

Hiera是如何组织数据源文件的?


Hiera的一个核心理念是重用数据,具体体现为对数据源文件的层次化分类管理(Hierarchy

    层次1: 所有节点通用的数据定义在一个公共数据源文件中,且只需定义一次

    层次2: 对节点分类(主要是依据facts)。一类节点的通用数据定义在一个公共数据源文件中,且只需定义与上面一层不同的部分

    层次3: 对每一个节点进行配置,每个节点一个数据源文件,且只需定义与上面几层不同的数据

数据源的配置被定义在Hiera的主配置文件(hiera.conf)中。下面是一个配置文件的例子。更多hiera.conf细节请看这里

:backends:                        #支持的数据源文件格式,默认是yaml和json

  – yaml                            #查找yaml格式数据源文件

  – json                             #查找json格式数据源文件

:yaml:                              #yaml格式数据源文件的根目录

  :datadir: "/etc/puppet/environments/%{::environment}/hieradata"            #%{::environment}是指facts中的environment变量。这行定义是说yaml格式的数据源文件的根目录是"/etc/puppet/environments/%{::environment}/hieradata"    

:json:                                #json格式数据源文件的根目录

  :datadir: "/etc/puppet/environments/%{::environment}/hieradata"            

:hierarchy:                        #分类和层次关系(hierarchy)

  – "nodes/%{::fqdn}"         #%{::fqdn}是指facts中的fqdn变量。按fqdn分类的数据源文件存在$datadir/nodes目录下,文件以agent节点的fqdn命名

  – "virtual/%{::virtual}"       #%{::virtual}是指facts中的virtual变量。按virtual值分类的数据源文件存在$datadir/virtual目录下,文件以virtual值命名

  – "common"                    #所有节点的默认配置都存在common.yaml或者common.json中

注意:如果修改了hiera.conf的内容,Puppet master进程必须重启才能生效

如果我的production环境中,server1和server2都是运行在xen上,而server3和server4都是在vmware上,那么根据上面的配置文件,我的数据源文件目录结构就很可能是这个样子

/etc/puppet/environments/production/hieradata

├── common.yaml                    #所有节点的通用配置

├── nodes                                #以fqdn分类的每个节点的配置

│   ├── server1.yaml                #server1的配置

│   ├── server2.yaml                #server2的配置

│   ├── server3.yaml                #server3的配置

│   └── server4.yaml                #server4的配置

└── virtual                                #以virtual分类的通用配置

    ├── xen.yaml                       #所有xen虚拟机的通用配置

    └── vmware.yaml                #所有vmware虚拟机的通用配置

对于server1 (xen虚拟机)来说,它的最终配置会是server1.yaml, xen.yaml 和common.yaml 中配置的组合。

如何从Hiera查询数据?


Hiera支持几种查询方式

1. 自动参数查询(automatic parameter lookup)

这种方式主要用于查询类的参数。

当Hiera配置好后,在manifest中声明类但不给指定参数赋值,比如使用include-like方式(无类参数),或者使用resource-like方式但不显性的给参数赋值,这两种情况下,Puppet都会自动使用<类名>::<参数名>作为键通过Hiera查询相应的参数值。详细信息请看这里

注意: * 不要在template中使用自动参数查询。

            * 如果想禁止这个功能,在master的puppet.conf设置data_binding_terminus = none

2. 使用Hiera内置函数或Hiera命令查询

数据类型 Hiera内置函数 Hiera命令
任何数据类型 hiera(<键>) hiera <键>
数组 hiera_array(<键>) hiera -a <键>
Hash hiera_hash(<键>) hiera -h <键>

注意:    * Hiera内置函数可以在任意的manifest文件中调用或者在puppet apply -e中命令调用。

                * Hiera命令在Hiera安装好后,就可以从shell中使用。

3. 使用Hiera内置函数hiera_include

hiera_include()专门用来在site.pp中查询哪些类分配给了指定节点,等同于在节点定义中使用include-like/resource-like来声明类,可以作为ENC的一个替代方案。

Hiera查询是如何工作的?


查询时,Hiera会按:hierarchy:下面定义的顺序遍历datadir子目录下的数据源文件,寻找匹配的键。

:hierarchy:

  – "nodes/%{::fqdn}"

  – "virtual/%{::virtual}"

  – "common"

如果:hierarchy:的定义是上面这样的,查询的顺序就是datadir下的nodes/%{::fqdn}子目录,然后是virtual/%{::virtual}子目录,最后是common.yaml文件。

如果你是使用以下的查询方式,那么在找到第一个匹配的键之后Hiera就返回了,不在继续查找

        * 自动参数查询(automatic parameter lookup)

        * Hiera内置的hiera函数

        * hiera命令(没有-a或-h)

如果你是使用以下的查询方式,那么Hiera会认为你在查找一个数组,它会遍历所有的数据源文件,然后将所匹配的所有数组值合并到一个数组中返回

        * Hiera内置的hiera_array函数

        * Hiera内置的hiera_include函数

        * hiera -a 命令

如果你是使用以下的查询方式,那么Hiera会认为你在查找一个hash,它会遍历所有的数据源文件,然后将所匹配的所有内容值合并到一个hash中返回。

        * Hiera内置的hiera_hash函数

        * hiera -h 命令

注意:如果这个hash又嵌套了其他的hash或者数组,且某个键在不同的数据源文件中被赋予了不同的hash或者数组,默认情况下,Hiera只会保留第一个匹配到的嵌套hash或者数组。如果你希望在这种情况下执行合并操作,请看这里

Hiera使用示例


我们通过一个例子来展示如何使用Hiera.

1. 演示环境

节点名 OS系统 Puppet组件
master-host CentOs7 Puppet 3.8开源版master,
agent-centos CentOs6 Puppet 3.8开源版agent和facter
agent-ubuntu Ubuntu14 Puppet 3.8开源版agent和facter

2. 实验目标

    * 所有agent节点的标准配置是安装ntp,使用节点系统自带的ntp设置,并启动ntp服务

    * 在且只在所有RedHat家族Linux上安装nginx,使用默认设置,并启动nginx服务(当前RedHat家族Linux上没有nginx

    * 在agent-centos节点上停止ntp服务

    * 在agent-ubuntu节点上使用外部ntp源0.au.pool.ntp.org和1.au.pool.ntp.org(当前agent-ubuntu节点上没有ntp

3. 安装所需模块

在这个演示中,会用到ntp和nginx模块(负责安装,配置并管理相关服务)。简单起见,我们从Forge上下载并安装相关模块到master-host上。当然,你也可以使用自己写的模块。

puppet module install puppetlabs-ntp         #安装ntp模块

puppet module install jfryman-nginx           #安装nginx模块

后面我们会用到puppetlabs-ntp模块中ntp类的两个参数,$::ntp::service_ensure和$::ntp::servers。如果你想了解其他参数的用途,可以查看模块的init.pp(/etc/puppet/modules/ntp/manifests/init.pp

4. 安装Hiera

一般在安装puppetserver的过程中,Hiera会被自动安装。如果你的master上没有Hiera软件包,请看这里了解安装过程。    

5. 配置

    a. Hiera主配置文件(/etc/puppet/hiera.yaml)

:backends:                                        

  – yaml                                             #告诉Hiera只查找yaml格式的数据源文件

:yaml:                        

  :datadir: "/etc/puppet/hieradata"    #yaml格式的数据源文件的根目录是/etc/puppet/hieradata

:hierarchy:                                       #定义数据源的分类和层次。

  – "nodes/%{::fqdn}"                        #按fqdn分类命名数据源文件并保存在/etc/puppet/hieradata/nodes目录下,比如agent-centos节点的文件名就是agent-centos.yaml

  – "osfamily/%{::osfamily}"                #在/etc/puppet/hieradata/osfamily目录下含有为以osfamily分类的数据源文件,例如RedHat家族Linux的数据源文件就是RedHat.yaml

  – common                                       #所有节点通用的默认配置

    b. 配置site.pp

node "agent-centos","agent-ubuntu" {       #节点定义

    hiera_include('classes')             #调用hiera_include函数向Hiera查询classes键值所对应的数组内容。这个键可以是其他名字,只要在数据源文件中保持名字一致就可以

}

    b. 配置所有节点的默认配置(/etc/puppet/hieradata/common.yaml)

classes:                                         #所有节点默认都调用ntp类。

    – ntp                            

ntp::service_ensure: running         #ntp::service_ensure是puppetlabs-ntp模块中,ntp类的service_ensure参数,是指服务的运行状态(也就是service资源中的ensure属性)这里给他赋值为 running

    上面定义是说每个节点默认都要安装ntp数据包,使用默认ntp配置并启动服务

    c. 配置agent-centos节点(/etc/puppet/hieradata/nodes/agent-centos.yaml)

ntp::service_ensure: stopped            #停止ntp服务

    d. 配置agent-ubuntu节点(/etc/puppet/hieradata/nodes/agent-ubuntu.yaml)

ntp::servers:                                  #ntp::service_ensure是puppetlabs-ntp模块中ntp类的参数,用来指定ntp源。

    – 0.au.pool.ntp.org                    #第一个ntp源是0.au.pool.ntp.org

    – 1.au.pool.ntp.org                    #第二个ntp源是1.au.pool.ntp.org

    做了以上配置后,agent-ubuntu节点会使用0.au.pool.ntp.org和1.au.pool.ntp.org作为ntp源。

    e. 配置RedHat家族Linux(/etc/puppet/hieradata/osfamily/RedHat.yaml)  

classes:                                     #配置所有RedHat家族Linux都调用nginx类

    – nginx                             

经过以上的配置,agent-centos的节点定义将会是agent-centos.yaml,RedHat.yaml和common.yaml整合后的内容,等同于以下设置。

node "agent-centos" {                 #agent-centos节点定义

        class { "ntp":                       #声明ntp类,来自common.yaml

            service_ensure => "stopped",     #停止ntp服务。高优先级的agent-centos.yaml覆盖了低优先级的common.yaml中的设置

        }

        include nginx                        #声明nginx类,来自于RedHat.yaml

}

而agent-ubuntu的节点定义是agent-ubuntu.yaml和common.yaml的内容整合后的结果,相当于下面的配置

node "agent-ubuntu" {                        #agent-ubuntu节点定义

       class { "ntp":                                #声明ntp类,来自common.yaml

                service_ensure => "running", #运行ntp服务,来自common.yaml

                servers=> ["0.au.pool.ntp.org", "1.au.pool.ntp.org"],#设置ntp源,来自于agent-ubuntu.yaml

        }

}

6. 检查配置

在应用前,可以使用hiera命令或者puppet apply命令来检查配置结果是否正确。

    a. 用hiera命令

    如果想检查agent-centos6(osfamily的值是RedHat)和agent-ubuntu(osfamily的值是Debian)上所分配的classes是哪些,可以使用下面的命令

[root@master-host~]hiera -a  'classes'  '::osfamily=RedHat' '::fqdn=agent-centos'  -c /etc/puppet/hiera.yaml

["ntp","nginx"]                             

[root@master-host~]hiera -a  'classes'  '::osfamily=Debian' '::fqdn=agent-ubuntu'  -c /etc/puppet/hiera.yaml

["ntp"]

    在上面命令中,-a说明被查询的classes是一个数组,如果它在不同数据源文件中都有定义,要求Hiera整合匹配的结果。如果不写-a,Hiera在找到第一个匹配classes的内容时就会立即返回。

    此外,'::osfamily=RedHat'和 '::fqdn=agent-centos6'是来告诉Hiera使用传入的facts值,如果没有指定,Hiera会使用当前系统的facts值。

    b. 用puppet apply命令 

    上面的检查也可以用puppet apply来执行

[root@master-host~]FACTER_fqdn=agent-centos FACTER_osfamily=RedHat puppet apply -e "notice(hiera_array('classes'))"

Notice: Scope(Class[main]): nginx ntp

Notice: Compiled catalog for master-centos6 in environment production in 0.05 seconds

Info: Applying configuration version '1467801050'

Notice: Finished catalog run in 0.11 seconds

[root@master-host~]FACTER_fqdn=agent-ubuntu FACTER_osfamily=Debian puppet apply  -e "notice(hiera_array('classes'))"

Notice: Scope(Class[main]): ntp

Notice: Compiled catalog for master-centos6 in environment production in 0.05 seconds

Info: Applying configuration version '1467801027'

Notice: Finished catalog run in 0.14 seconds

    上面命令中使用的FACTER_fqdn和FACTER_osfamily都是告诉puppet使用指定的fqdn和osfamily值。此外,hiera_array用来说明classes是一个数组,Hiera会将所有匹配结果整合后再返回。

7. 运行并检查结果

在agent节点上启动agent进程

puppet agent -v –no-daemonize

在agent将catalog应用完成后,检查agent-centos节点

[root@agent-centos~]# service ntpd status

ntpd is stopped                                     #ntp服务被停止了

[root@agent-centos~]# rpm -qa | grep nginx

nginx-1.10.1-1.el6.ngx.i386                  #nginx安装包已安装

[root@agent-centos~]service nginx status

nginx (pid  4531) is running…                #nginx服务已运行

检查agent-ubuntu节点

root@agent-ubuntu:~# dpkg -l ntp                                #ntp包已安装

||/ Name           Version      Architecture Description

+++-==============-============-============-=================================

ii  ntp            1:4.2.6.p5+d i386         Network Time Protocol daemon and

root@agent-ubuntu:~# service ntp status

 * NTP server is running                                                    #ntp服务已运行

root@agent-ubuntu:~# grep server /etc/ntp.conf        #ntp.conf中的ntp源与预期相符

server 0.au.pool.ntp.org iburst                 

server 1.au.pool.ntp.org iburst

原创文章,作者:MVP,如若转载,请注明出处:http://www.178linux.com/22350

(0)
上一篇 2016-07-07 19:07
下一篇 2016-07-07 19:07

相关推荐

  • 系统基础之Btrfs文件系统详解

    btrfs文件系统:技术预览版(centos7) 描述: Btrfs(B-tree,Butter FS,Better fs),GPL授权,Orale,2007 写实复制特性(Cow)     cp –reflink (只能在btrfs文件系统中使用) 想取代ext系统系统, 支…

    Linux干货 2016-09-21
  • keepalive配置文件详解

    第一部分:全局定义块 1、email通知。作用:有故障,发邮件报警。 2、Lvs负载均衡器标识(lvs_id)。在一个网络内,它应该是唯一的。 3、花括号“{}”。用来分隔定义块,因此必须成对出现。如果写漏了,keepalived运行时,不会得到预期的结果。由于定义块内存在嵌套关系,因此很容易遗漏结尾处的花括号,这点要特别注意。 global_defs{ n…

    2017-09-17
  • select case的用法-函数练习-20160819

    §·select  case的用法 *介绍select 循环与菜单 ◎语法 select  variable  in  list[ ] do 循环体命令 Done  ◎select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示PS3 提示符,等待用户输 入 ◎用户…

    Linux干货 2016-08-19
  • 从Linux小白到大牛——与狼共舞的日子8

    马哥教育网络班21期+第8周课程练习 1、请描述网桥、集线器、二层交换机、三层交换机、路由器的功能、使用场景与区别。 网桥是第2层的设备,它设计用来创建两个或多个LAN分段。其中,每一个分段都是一个独立的冲突域。网桥设计用来产生更大可用宽带。它的目的是过滤LAN的通信流,使得本地的通信流保留在本地,而让那些定向到LAN其他部分(分段)的通信流转发到那里去。每…

    Linux干货 2016-11-14
  • 用户管理简述

    组内用户管理汇总 基于组来管理用户 相关命令:gpasswd groupmems 添加用户 gpasswd -a wangcai group :向group里添加用户 wangcai gpasswd -M wangcai,xiaoqiang group :向group里批量添加xiaoqiang wangcai ,不过这个方式会覆盖之前的组员 groupme…

    2017-02-23
  • 第三周(3):课堂练习与作业

    课堂练习: 1、找出ifconfig命令结果中本机的所有IPv4地址 [root@centos6 ~]# ifconfig | tr -cs '[0-9].' '\n'|sort -ut. -k3n 127.0.0.1 10.1….

    Linux干货 2016-08-08