為什么使用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.www58058.com/22350