#### Puppet擴展篇1-自定義fact結合ENC(hirea)的應用實踐
在大量節點加入Puppet之后,你至少會面臨兩個比較大的問題:
1、由于節點數的增多,site.pp文件必然會編寫更多的節點條目,以及節點包含的類。假設你用Puppet管理500個節點,存在三種情況:1、所有節點有共同的類,也可以理解為模塊;2、所有節點分成了50組,每組節點有不同的應用,每組應用編寫一個模塊;3、每個節點也應該有一個自己的模塊,在這種環境下,可想而知,site.pp文件是多么的復雜,多么的難以維護。
2、在使用MCO推送更新的時候,后面可以跟上fact變量用于過濾一組節點。而官方給的facter只能滿足普遍存在的fact變量,可是,你要對一組節點進行歸類怎么辦呢,比如有10個節點的應用是Apache,15個節點屬于Nginx等,那么就要自定義fact變量。現在面臨的問題是,所有節點都要自定義fact變量,又如何做到集中管理呢?
# 一、先來解決節點與類勾連的問題
其實、節點與類之間的勾連,更多時候是要借助ENC(外部節點分類器)來完成,因為puppet軟件本身并不具備此類功能。Puppet-dashboard企業版和Foreman已經具備了這方面的功能,而且是圖形界面操作,還是很方便的。眾所周知,Puppet-dashboard社區版目前最新版本為1.2.23,到目前為止已經有一年多未更新了,可見Puppetlabs的意圖很明確,逼著你用企業版。而Foreman部署和使用略復雜些,其次Foreman很重,它的內部并不僅僅是包含puppet還包含了很多其它管理工具,非常龐大,可以酌情考慮使用。接下來要介紹的是官方推薦的hiera軟件,一個很強大的ENC,編寫的文件只要遵循yaml格式即可,使用非常方便,可惜的是沒有圖形界面。但這并不代表你不會開發圖形界面哦。
# 1、在Master端安裝hiera工具
hiera工具和Puppetmaster結合需要通過hiera-puppet工具完成,在puppet-server 3.0.*版本后,這個工具已經集成到了puppet-server安裝包中。而我們現在使用的環境仍然是puppet2.7版本,所以需要安裝hiera-puppet工具。
~~~
[root@puppetmaster RHEL6U4]# yum install hiera hiera-puppet #注意依賴關系
...
Dependencies Resolved
===========================================================================
Package Arch Version Repository Size
===========================================================================
Installing:
hiera noarch 1.3.2-1.el6 rhel-puppet 23 k
hiera-puppet noarch 1.0.0-1.el6 rhel-puppet 14 k
Installing for dependencies:
ruby-irb x86_64 1.8.7.352-7.el6_2 rhel-base 311 k
ruby-rdoc x86_64 1.8.7.352-7.el6_2 rhel-base 375 k
rubygem-json x86_64 1.5.5-1.el6 rhel-puppet 763 k
rubygems noarch 1.3.7-1.el6 rhel-puppet 206 k
Transaction Summary
===========================================================================
...
~~~
# 2、編輯hiera主配置文件hiera.yaml
### 2.1、創建軟連接
默認hiera.yaml主配置文件在/etc目錄下,為了結合后期版本控制系統集中管理,建議將此文件copy到/etc/puppet目錄下,然后創建軟連接指向/etc/hiera.yaml即可。
~~~
[root@puppetmaster ~]# mv /etc/hiera.yaml /etc/puppet/
[root@puppetmaster ~]# ln -s /etc/puppet/hiera.yaml /etc/hiera.yaml
[root@puppetmaster ~]# ll /etc/hiera.yaml
lrwxrwxrwx 1 root root 22 Apr 20 20:05 /etc/hiera.yaml -> /etc/puppet/hiera.yaml
~~~
### 2.2、編輯hiera.yaml
- 添加全局變量common,注釋掉defaults、global和clientcert。
- 添加系統類型變量osfamily
- 添加主機名變量hostname
- 添加datadir路徑位置,中間用了puppet環境變量,這里的環境變量和puppet應用的環境變量是一致的。如果你只有一種環境,只需要將其中變量去掉即可。
**備注:** 以上變量其實就是fact變量。
~~~
[root@puppetmaster ~]# vim /etc/puppet/hiera.yaml
---
:backends:
- yaml
:hierarchy:
# - defaults
# - "%{clientcert}"
- common
- "%{environment}"
- "%{osfamily}"
- "%{hostname}"
# - global
:yaml:
:datadir:"/etc/puppet/environments/%{environment}/hiera"
~~~
hiera主配置文件編寫完成之后,需要重啟puppetmaster后方可生效。
~~~
[root@puppetmaster hiera]# /etc/init.d/puppetmaster restart
Stopping puppetmaster: [ OK ]
Starting puppetmaster: [ OK ]
~~~
### 2.3、創建變量common對應的文件
~~~
[root@puppetmaster hiera]# vim common.yaml
---
puppetserver:
- 'puppetmaster.kisspuppet.com'
~~~
通過hiera命令測試
~~~
[root@puppetmaster ~]# hiera puppetserver environment=kissprd
["puppetmaster.kisspuppet.com"]
[root@puppetmaster ~]# hiera puppetserver environment=kissdev
nil
~~~
通過以上命令可以得知在環境為kissprd的情況下,puppetserver的變量為puppetmaster.kisspuppet.com,值為nil的意思是不存在。
### 2.4、創建變量osfamily對應的文件
~~~
[root@agent1 ~]# facter osfamily
RedHat
[root@puppetmaster hiera]# vim RedHat.yaml
---
classes:
- 'puppet'
- 'yum'
~~~
通過hiera命令測試
~~~
[root@puppetmaster hiera]# hiera classes environment=kissprd
nil
[root@puppetmaster hiera]# hiera classes environment=kissprd osfamily=RedHat
["motd", "puppet", "yum"]
[root@puppetmaster hiera]# hiera classes environment=kissprd osfamily=SLES
nil
~~~
通過以上命令可以得在環境為kissprd,系統為RedHat的情況下,classes的變量為三個值(puppet、yum)。
### 2.5、創建變量hostname對應的所有節點文件
~~~
[root@agent1 ~]# facter hostname
agent1
[root@puppetmaster hiera]# vim agent1.yaml
---
classes:
- 'motd'
certname:
- 'agent1_cert.kisspuppet.com'
[root@puppetmaster hiera]# vim agent2.yaml
---
classes:
- 'motd'
certname:
- 'agent2_cert.kisspuppet.com'
[root@puppetmaster hiera]# vim agent3.yaml
---
certname:
- 'agent3_cert.kisspuppet.com'
~~~
通過hiera命令測試
~~~
[root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent
1
["motd"]
[root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent
2
["motd"]
[root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent
3
nil
[root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent1
["agent1_cert.kisspuppet.com"]
[root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent2
["agent2_cert.kisspuppet.com"]
[root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent3
["agent3_cert.kisspuppet.com"]
~~~
通過以上命令測試可以得知,系統fact變量hostname為agent1和agent2的情況下,hiera變量classes為motd。certname變量為各自的certname變量。
# 3、應用hiera變量于Puppetmaster
### 3.1、將hiera變量應用于site.pp文件中
以前的寫法:
~~~
[root@puppetmaster ~]# vim /etc/puppet/environments/kissprd/manifests/site.pp
$puppetserver = 'puppetmaster.kisspuppet.com'
class environments{
include puppet,yum
}
node 'puppetmaster_cert.kisspuppet.com'{
include environments
}
node 'agent1_cert.kisspuppet.com'{
include environments,motd
}
node 'agent2_cert.kisspuppet.com'{
include environments,motd
}
node 'agent3_cert.kisspuppet.com'{
include environments
}
~~~
應用了hiera之后的寫法:
~~~
[root@puppetmaster ~]# vim /etc/puppet/environments/kissprd/manifests/site.pp
$puppetserver = hiera('puppetserver') #引用了hiera中common.yaml中的全局變量puppetserver
node default {
hiera_include('classes') #引用了hiera中osfamily和hostname變量
}
~~~
**備注:**以后添加節點,只需要編寫yaml文件即可,而site.pp文件無需在進行修改。
### 3.2、將hiera變量應用于模塊puppet中
未使用hiera之前的編寫方式
~~~
[root@puppetmaster hiera]# vim /etc/puppet/environments/kissprd/environment/modules/puppet/manifests/params.pp
class puppet::params {
$puppetserver = 'puppetmaster.kisspuppet.com'
$certname = "${::hostname}_cert.kisspuppet.com"
case $operatingsystemmajrelease{
5: {
$puppet_release = '2.7.23-1.el5'
$facter_release = '1.7.3-1.el5'
}
6: {
$puppet_release = '2.7.23-1.el6'
$facter_release = '1.7.3-1.el6'
}
default: {
fail("Module puppet is not supported on ${::operatingsystem}")
}
}
}
~~~
應用了hiera變量之后的編寫方式
~~~
[root@puppetmaster hiera]# vim /etc/puppet/environments/kissprd/environment/modules/puppet/manifests/params.pp
class puppet::params {
$puppetserver = hiera('puppetserver') #應用了hiera全局文件common.yaml中的puppetserver變量
$certname = hiera('certname') #應用了hiera中變量hostname對應的節點文件$hostname.yaml中的certname變量
case $operatingsystemmajrelease{
5: {
$puppet_release = '2.7.23-1.el5'
$facter_release = '1.7.3-1.el5'
}
6: {
$puppet_release = '2.7.23-1.el6'
$facter_release = '1.7.3-1.el6'
}
default: {
fail("Module puppet is not supported on ${::operatingsystem}")
}
}
}
~~~
# 4、測試
### 4.1、測試classes
~~~
[root@agent1 ~]# puppet agent -t --environment=kissprd
info: Retrieving plugin
info: Loading facts in /var/lib/puppet/lib/facter/hwclock.rb
info: Caching catalog for agent1_cert.kisspuppet.com
info: Applying configuration version '1398007834'
notice: Hardware-Clock: Sun 20 Apr 2014 11:30:35 PM CST -0.059676 seconds
notice: /Stage[main]/Motd/Notify[ Hardware-Clock: Sun 20 Apr 2014 11:30:35 PM CST -0.059676 seconds]/message: defined 'message' as ' Hardware-Clock: Sun 20 Apr 2014 11:30:35 PM CST -0.059676 seconds'
notice: /Stage[main]/Motd/File[/etc/motd]/content:
--- /etc/motd 2014-04-20 23:30:26.000000000 +0800
+++ /tmp/puppet-file20140420-9781-fm0gig-0 2014-04-20 23:30:37.000000000 +0800
@@ -0,0 +1,3 @@
+-- --
+--------puppet test---------
+-- --
info: FileBucket got a duplicate file {md5}d41d8cd98f00b204e9800998ecf8427e
info: /Stage[main]/Motd/File[/etc/motd]: Filebucketed /etc/motd to puppet with sum d41d8cd98f00b204e9800998ecf8427e
notice: /Stage[main]/Motd/File[/etc/motd]/content: content changed '{md5}d41d8cd98f00b204e9800998ecf8427e' to '{md5}87ea3a1af8650395038472457cc7f2b1'
notice: Finished catalog run in 0.76 seconds
[root@agent1 ~]# cat /etc/motd
-- --
--------puppet test---------
-- --
[root@agent3 ~]# >/etc/motd
[root@agent3 ~]# puppet agent -t --environment=kissprd
info: Retrieving plugin
notice: /File[/var/lib/puppet/lib/facter]/ensure: created
notice: /File[/var/lib/puppet/lib/facter/hwclock.rb]/ensure: defined content as '{md5}d8cc9fe2b349a06f087692763c878e28'
info: Loading downloaded plugin /var/lib/puppet/lib/facter/hwclock.rb
info: Loading facts in /var/lib/puppet/lib/facter/hwclock.rb
info: Caching catalog for agent3_cert.kisspuppet.com
info: Applying configuration version '1398007834'
notice: Finished catalog run in 0.67 seconds
[root@agent3 ~]# cat /etc/motd
[root@agent3 ~]#
~~~
從以上測試可以得知類motd應用到了agent1并未應用到agent3,說明hiera傳輸變量正確。
### 4.2、測試hiera變量certname和puppetserver
~~~
[root@agent3 ~]# vim /etc/puppet/puppet.conf
### config by puppet ###
[main]
logdir = /var/log/puppet
rundir = /var/run/puppet
ssldir = $vardir/ssl
pluginsync = true
[agent]
classfile = $vardir/classes.txt
localconfig = $vardir/localconfig
# server = puppetmaster.kisspuppet.com #注釋掉進行測試
# certname = agent3_cert.kisspuppet.com
runinterval = 10
[root@agent3 ~]# puppet agent -t --environment=kissprd --server=puppetmaster.kisspuppet.com --certname=agent3_cert.kisspuppet.com
info: Retrieving plugin
info: Loading facts in /var/lib/puppet/lib/facter/hwclock.rb
info: Caching catalog for agent3_cert.kisspuppet.com
info: Applying configuration version '1398008880'
notice: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]/content:
--- /etc/puppet/puppet.conf 2014-04-20 23:46:05.839948111 +0800
+++ /tmp/puppet-file20140420-5618-45rytg-0 2014-04-20 23:48:01.653944253 +0800
@@ -7,6 +7,6 @@
[agent]
classfile = $vardir/classes.txt
localconfig = $vardir/localconfig
-# server = puppetmaster.kisspuppet.com
-# certname = agent3_cert.kisspuppet.com
+ server = puppetmaster.kisspuppet.com
+ certname = agent3_cert.kisspuppet.com
runinterval = 10
info: FileBucket adding {md5}13430e5962e7584c9422e5adc1f3ba43
info: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]: Filebucketed /etc/puppet/puppet.conf to puppet with sum 13430e5962e7584c9422e5adc1f3ba43
notice: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]/content: content changed '{md5}13430e5962e7584c9422e5adc1f3ba43' to '{md5}23545b7afd09af671920f122a20db952'
info: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]: Scheduling refresh of Class[Puppet::Service]
info: Class[Puppet::Service]: Scheduling refresh of Service[puppet]
notice: /Service[puppet]: Triggered 'refresh' from 1 events
notice: Finished catalog run in 0.54 seconds
[root@agent3 ~]# cat /etc/puppet/puppet.conf
### config by puppet ###
[main]
logdir = /var/log/puppet
rundir = /var/run/puppet
ssldir = $vardir/ssl
pluginsync = true
[agent]
classfile = $vardir/classes.txt
localconfig = $vardir/localconfig
server = puppetmaster.kisspuppet.com
certname = agent3_cert.kisspuppet.com
runinterval = 10
~~~
通過以上測試可以得知hiera變量certname和puppetserver傳輸正常。
**特別說明:** 由于hiera定義的變量需要通過轉換才能變為puppet能夠使用的變量,而這個轉換是需要耗費CPU資源的,筆者曾經測試過一組節點(50個)同時傳輸hiera的變量數超過2000個,出現CPU負載過高的性能瓶頸問題需要特別注意。其次hiera數據除了用yaml格式保存外還可以存放在redis數據庫中,這樣查詢起來性能會高很多,具體可參考官網,《pro puppet 》第二版也有這方面的介紹,可參閱。
**通過以上測試至少解決了兩個問題:**
- site.pp編寫繁瑣復雜的問題。
- certname名定義問題(可以不適用其他fact變量進行定義,比如不再使用hostname變量,這樣做的好處是即使節點hostname名變化也不會影響puppet通信)
### 二、集中管理自定義fact變量
**思路:** 參考[Puppet基礎篇10-自定義fact實現的四種方式介紹](http://kisspuppet.com/2014/03/30/puppet_learning_base10/)在puppetmaster端編寫一個facts模塊,傳輸一個變量文件至節點對應的目錄里面,變量文件名可以通過主機名進行定義。
### 1、在現有facts模塊中直接添加
之前facts模塊中的結構
~~~
[root@puppetmaster modules]# tree facts/
facts/
├── files
├── lib
│ └── facter
│ └── hwclock.rb #通過pluginsync模式發布的自定義fact變量,無需修改
├── manifests
└── templates
5 directories, 1 file
~~~
### 2、添加管理file資源的pp文件
~~~
[root@puppetmaster manifests]# vim config.pp #定義file資源
class facts::config{
file{ "/etc/facter/facts.d/$hostname.txt": #文件名稱通過變量hostname獲取
owner => "root",
group => "root",
mode => 0400,
source => "puppet:///modules/facts/facts.d/$hostname.txt", #文件名稱通過節點變量hostname獲取
require => Class['facts::exec'],
}
}
[root@puppetmaster manifests]# vim exec.pp #定義可執行資源保證目錄 /etc/facter/facts.d 存在
class facts::exec{
exec {"create fact external":
command => "mkdir -p /etc/facter/facts.d ",
path => ["/usr/bin","/usr/sbin","/bin","/sbin"],
creates => "/etc/facter/facts.d",
}
}
[root@puppetmaster manifests]# vim init.pp
class facts{
include facts::config,facts::exec
}
~~~
### 3、創建file資源對應的下載文件
~~~
[root@puppetmaster facts.d]# pwd
/etc/puppet/environments/kissprd/environment/modules/facts/files/facts.d
[root@puppetmaster facts.d]# vim agent1.txt
env=prd
app=weblogic
[root@puppetmaster facts.d]# vim agent2.txt
env=qa
app=db2
[root@puppetmaster facts.d]# vim agent3.txt
env=prd
app=nginx
~~~
### 4、應用模塊facts至hiera中
由于模塊facts屬于全局的,應用于common.ymal或者RedHat.ymal中即可。
~~~
[root@puppetmaster hiera]# vim RedHat.yaml
---
classes:
- 'puppet'
- 'yum'
- 'facts'
~~~
### 5、節點測試
~~~
[root@agent3 ~]# ll /etc/facter/facts.d
ls: cannot access /etc/facter/facts.d: No such file or directory
[root@agent3 ~]# puppet agent -t --environment=kissprd
info: Retrieving plugin
info: Loading facts in /var/lib/puppet/lib/facter/hwclock.rb
info: Caching catalog for agent3_cert.kisspuppet.com
info: Applying configuration version '1398010573'
notice: /Stage[main]/Facts::Exec/Exec[create fact external]/returns: executed successfully
notice: /Stage[main]/Facts::Config/File[/etc/facter/facts.d/agent3.txt]/ensure: defined content as '{md5}3330b8efe95f6747de47a9eca3a5411e'
notice: Finished catalog run in 0.66 seconds
[root@agent3 ~]# cat /etc/facter/facts.d/agent3.txt
env=prd
app=nginx
[root@agent3 ~]# facter env
prd
[root@agent3 ~]# facter app
nginx
~~~
其它節點測試略
**注意:**以上方法只是提供給你一種集中管理自定義fact的思路,并不是最好的解決方案,只不過這種方法目前筆者用于上產環境中感覺還不錯,特此分享。
- 序
- 第一章:Puppet基礎篇
- 編寫此系列文檔的目的
- 如何學習和使用Puppet
- 安裝Puppet前期的準備工作
- 安裝、配置并使用Puppet
- 如何建立master和agent之間的認證關系
- Puppet更新方式的選型
- 編寫第一個完整測試模塊puppet
- 編寫第二個完整測試模塊yum
- Puppetmaster多環境配置
- 自定義fact實現的四種方式介紹
- 第二章:Puppet擴展篇
- 自定義fact結合ENC(hirea)的應用實踐
- 如何使用虛擬資源解決puppet沖突問題
- 如何擴展master的SSL傳輸性能(apache)
- 如何擴展master的SSL傳輸性能(nginx)
- 通過多進程增強master的負載均衡能力(nginx+mongrel)
- 通過橫向擴展puppetmaster增加架構的靈活性
- puppet代碼與版本控制系統的結合
- Puppet dashboard的部署及測試
- 第三章:MCollective架構篇
- MCollecitve架構的引入
- MCollective+MQ架構的部署
- Puppet插件的部署及測試
- MCollective各種插件的部署及測試
- MCollective安全性設計
- MQ的安全性設計
- 多MQ下MCollective高可用部署
- 第四章:Foreman架構的引入
- Foreman作為自動化運維工具為什么會如此強大
- 安裝前環境準備
- 安裝Foreman1.5架構(all-in-one)
- 安裝Foreman1.6架構(foreman與puppetmaster分離)
- 安裝Foreman1.7架構(源碼,僅測試使用)
- 整合puppetmaster
- Foreman結合mcollective完成push動作
- Foreman結合puppetssh完成push動作
- Foreman的ENC環境與fact環境的對比
- hostgroup如何轉換為本地的fact
- 智能變量與puppet模塊參數化類的結合
- Foreman報告系統的使用
- Foreman-proxy如何做負載均衡
- Foreman上如何展現代碼及文件內容
- Foreman如何和虛擬化管理軟件結合
- 如何借助Foreman完成自動化部署操作系統(一)
- 如何借助Foreman完成自動化部署操作系統(二)
- Foreman CLI(Hammer)工具的使用
- Foreman目前的不足之處