正文
一、puppet 介紹
1、puppet是什么
puppet
是一個IT基礎設施自動化管理工具,它能夠幫助系統管理員管理基礎設施的整個生命周期: 供應(provisioning)、配置(configuration)、聯動(orchestration)及報告(reporting)。
基於puppet ,可實現自動化重復任務、快速部署關鍵性應用以及在本地或雲端完成主動管理變更和快速擴展架構規模等。
遵循GPL 協議(2.7.0-), 基於ruby
語言開發。
2.7.0 以后使用(Apache 2.0 license)
對於系統管理員是抽象的,只依賴於ruby
與facter
。
能管理多達40 多種資源,例如:file
、user
、group
、host
、package
、service
、cron
、exec
、yum repo
等。
2、puppet的工作機制
1)工作模型
puppet 通過聲明性、基於模型的方法進行IT自動化管理。
定義:通過puppet 的聲明性配置語言定義基礎設置配置的目標狀態;
模擬:強制應用改變的配置之前先進行模擬性應用;
強制:自動、強制部署達成目標狀態,糾正任何偏離的配置;
報告:報告當下狀態及目標狀態的不同,以及達成目標狀態所進行的任何強制性改變;
puppet三層模型
puppet三層模型如下:

2)工作流程

3)使用模型
puppet的使用模型分為單機使用模型和master/agent模型,下面我們來看看這兩個模型的原理圖。
單機使用模型
實現定義多個manifests --> complier --> catalog --> apply

master/agent模型
master/agent模型實現的是集中式管理,即 agent 端周期性向 master 端發起請求,請求自己需要的數據。然后在自己的機器上運行,並將結果返回給 master 端。
架構和工作原理如下:
架構

工作原理

3、puppet 名詞解釋
- 資源:是puppet的核心,通過資源申報,定義在資源清單中。相當於
ansible
中的模塊,只是抽象的更加徹底。 - 類:一組資源清單。
- 模塊:包含多個類。相當於
ansible
中的角色。 - 站點清單:以主機為核心,應用哪些模塊。
二、puppet 資源詳解
接下來,我們就以單機模式來具體介紹一下puppet
的各個部分。
1、程序安裝及環境
首先,我們還是來安裝一下puppet
,puppet
的安裝可以使用源碼安裝,也可以使用rpm(官方提供)、epel源、官方提供的yum倉庫來安裝(通過下載官方提供的rpm包可以指定官方的yum倉庫)。
在這里,我們就是用 yum 安裝的方式。Puppet 不在 CentOS 的基本源中,需要加入 PuppetLabs 提供的官方源:
wget http://yum.puppetlabs.com/puppetlabs-release-pc1-el-6.noarch.rpm
yum install puppetlabs-release-pc1-el-6.noarch.rpm
yum install -y ruby facter puppet-server (server端)
yum install -y ruby facter puppet (agent端)
安裝完成過后,我們可以通過rpm -ql puppet | less
來查看一下包中都有一些什么文件。
其中主配置文件為/etc/puppet/puppet.conf
,使用的主程序為/usr/bin/puppet
。
2、puppet 資源簡介
1)資源抽象
puppet 從以下三個維度來對資源完成抽象:
- 相似的資源被抽象成同一種資源**“類型”** ,如程序包資源、用戶資源及服務資源等;
- 將資源屬性或狀態的描述與其實現方式剝離開來,如僅說明安裝一個程序包而不用關心其具體是通過yum、pkgadd、ports或是其它方式實現;
- 僅描述資源的目標狀態,也即期望其實現的結果,而不是其具體過程,如“確定nginx 運行起來” 而不是具體描述為“運行nginx命令將其啟動起來”;
這三個也被稱作puppet 的資源抽象層(RAL)
RAL 由type( 類型) 和provider( 提供者,即不同OS 上的特定實現)組成。
2)資源定義
資源定義通過向資源類型的屬性賦值來實現,可稱為資源類型實例化;
定義了資源實例的文件即清單,manifest;
定義資源的語法如下:
type {'title':
attribute1 => value1,
atrribute2 => value2,
……
}
注意:type必須使用小寫字符;title是一個字符串,在同一類型中必須惟一;每一個屬性之間需要用“,”隔開,最后一個“,”可省略。
例如,可以同時有名為nginx 的“service”資源和“package”資源,但在“package” 類型的資源中只能有一個名為“nginx”的資源。
3)資源屬性中的三個特殊屬性:
Namevar
:可簡稱為name;ensure
:資源的目標狀態;Provider
:指明資源的管理接口;
3、常用資源總結
1)查看資源
我們可以使用puppet describe
來打印有關Puppet資源類型,提供者和元參數的幫助。使用語法如下:
puppet describe [-h|--help] [-s|--short] [-p|--providers] [-l|--list] [-m|--meta] [type]
-l:列出所有資源類型;
-s:顯示指定類型的簡要幫助信息;
-m:顯示指定類型的元參數,一般與-s一同使用;
2)group:管理系統上的用戶組。
查看使用幫助信息:

屬性:
name:組名,可以省略,如果省略,將繼承title的值;
gid:GID;
system:是否為系統組,true OR false;
ensure:目標狀態,present/absent;
members:成員用戶;
簡單舉例如下:
vim group.pp
group{'mygrp':
name => 'mygrp',
ensure => present,
gid => 2000,
}
我們可以來運行一下:

3)user:管理系統上的用戶。
查看使用幫助信息:

屬性:
name:用戶名,可以省略,如果省略,將繼承title的值;
uid: UID;
gid:基本組ID;
groups:附加組,不能包含基本組;
comment:注釋;
expiry:過期時間 ;
home:用戶的家目錄;
shell:默認shell類型;
system:是否為系統用戶 ;
ensure:present/absent;
password:加密后的密碼串;
簡單舉例如下:
vim user1.pp
user{'keerr':
ensure => present,
system => false,
comment => 'Test User',
shell => '/bin/tcsh',
home => '/data/keerr',
managehome => true,
groups => 'mygrp',
uid => 3000,
}
4)package:puppet的管理軟件包。
查看使用幫助信息:

屬性:
ensure:installed, present, latest, absent, any version string (implies present)
name:包名,可以省略,如果省略,將繼承title的值;
source:程序包來源,僅對不會自動下載相關程序包的provider有用,例如rpm或dpkg;
provider:指明安裝方式;
簡單舉例如下:
vim package1.pp
package{'nginx':
ensure => installed,
procider => yum
}
5)service:定義服務的狀態
查看使用幫助信息:
puppet describe service -s -m

屬性:
ensure:服務的目標狀態,值有true(running)和false(stopped)
enable:是否開機自動啟動,值有true和false
name:服務名稱,可以省略,如果省略,將繼承title的值
path:服務腳本路徑,默認為/etc/init.d/下
start:定制啟動命令
stop:定制關閉命令
restart:定制重啟命令
status:定制狀態
簡單舉例如下:
vim service1.pp
service{'nginx':
ensure => true,
enable => false
}
6)file:管理文件、目錄、軟鏈接
查看使用幫助信息:

屬性:
ensure:目標狀態,值有absent,present,file,directory和link
file:類型為普通文件,其內容由content屬性生成或復制由source屬性指向的文件路徑來創建;
link:類型為符號鏈接文件,必須由target屬性指明其鏈接的目標文件;
directory:類型為目錄,可通過source指向的路徑復制生成,recurse屬性指明是否遞歸復制;
path:文件路徑;
source:源文件;
content:文件內容;
target:符號鏈接的目標文件;
owner:定義文件的屬主;
group:定義文件的屬組;
mode:定義文件的權限;
atime/ctime/mtime:時間戳;
簡單舉例如下:
vim file1.pp
file{'aaa':
path => '/data/aaa',
source => '/etc/aaa',
owner => 'keerr',
mode => '611',
}
7)exec:執行命令,慎用。通常用來執行外部命令
查看使用幫助信息:
puppet describe exec -s -m

屬性:
command(namevar):要運行的命令;
cwd:指定運行該命令的目錄;
creates:文件路徑,僅此路徑表示的文件不存在時,command方才執行;
user/group:運行命令的用戶身份;
path:指定命令執行的搜索路徑;
onlyif:此屬性指定一個命令,此命令正常(退出碼為0)運行時,當前command才會運行;
unless:此屬性指定一個命令,此命令非正常(退出碼為非0)運行時,當前command才會運行;
refresh:重新執行當前command的替代命令;
refreshonly:僅接收到訂閱的資源的通知時方才運行;
簡單舉例如下:
vim exec1.pp
exec{'cmd':
command => 'mkdir /data/testdir',
path => ['/bin','/sbin','/usr/bin','/usr/sbin'],
# path => '/bin:/sbin:/usr/bin:/usr/sbin',
}
8)cron:定義周期性任務
查看使用幫助信息:

屬性:
command:要執行的任務(命令或腳本);
ensure:目標狀態,present/absent;
hour:時;
minute:分;
monthday:日;
month:月;
weekday:周;
user:以哪個用戶的身份運行命令(默認為root);
target:添加為哪個用戶的任務;
name:cron job的名稱;
簡單舉例如下:
vim cron1.pp
cron{'timesync':
command => '/usr/sbin/ntpdata 172.16.0.1',
ensure => present,
minute => '*/3',
user => 'root',
}
我們可以運行一下,查看我們的crontab,來看看該任務是否已經被添加:
[root@master manifests]# puppet apply -v --noop cron1.pp #試運行
[root@master manifests]# puppet apply -v cron1.pp #運行
[root@master manifests]# crontab -l #查看計划任務
# HEADER: This file was autogenerated at 2017-12-14 15:05:05 +0800 by puppet.
# HEADER: While it can still be managed manually, it is definitely not recommended.
# HEADER: Note particularly that the comments starting with 'Puppet Name' should
# HEADER: not be deleted, as doing so could cause duplicate cron jobs.
# Puppet Name: timesync
*/3 * * * * /usr/sbin/ntpdata 172.16.0.1
9)notify:調試輸出
查看使用幫助信息:

屬性:
message:記錄的信息
name:信息名稱
該選項一般用於master/agent模式
中,來記錄一些操作的時間,比如重新安裝了一個程序呀,或者重啟了應用等等。會直接輸出到代理機的運行日志中。
以上,就是我們常見的8個資源。其余的資源我們可以使用puppet describe -l
來列出,上文中也已經說過了~
4、資源的特殊屬性
puppet
中也提供了before、require、notify和subscribe四個參數來定義資源之間的依賴關系和通知關系。
before:表示需要依賴於某個資源
require:表示應該先執行本資源,在執行別的資源
notify:A notify B:B依賴於A,且A發生改變后會通知B;
subscribe:B subscribe A:B依賴於A,且B監控A資源的變化產生的事件;
同時,依賴關系還可以使用->
和~>
來表示:
-> 表示后資源需要依賴前資源
~> 表示前資源變動通知后資源調用
舉例如下:
vim file.pp
file{'test.txt': #定義一個文件
path => '/data/test.txt',
ensure => file,
source => '/etc/fstab',
}
file{'test.symlink': #依賴文件建立超鏈接
path => '/data/test.symlink',
ensure => link,
target => '/data/test.txt',
require => File['test.txt'],
}
file{'test.dir': #定義一個目錄
path => '/data/test.dir',
ensure => directory,
source => '/etc/yum.repo.d/',
recurse => true,
}
我們還可以使用在最下面統一寫依賴關系的方式來定義:
vim redis.pp
package{'reids':
ensure => installed,
}
file{'/etc/redis.conf':
source => '/root/manifets/files/redis.conf',
ensure => file,
owner => redis,
group => root,
mode => '0640',
}
service{'redis':
ensure => running,
enable => true,
hasrestart => true,
}
Package['redis'] -> File['/etc/redis.conf'] -> Service['redis'] #定義依賴關系
tag 標簽
如同 anssible 一樣,puppet 也可以定義“標簽”——tag,打了標簽以后,我們在運行資源的時候就可以只運行某個打過標簽的部分,而非全部。這樣就更方便於我們的操作。
一個資源中,可以有一個tag
也可以有多個。具體使用語法如下:
type{'title':
...
tag => 'TAG1',
}
type{'title':
...
tag => ['TAG1','TAG2',...],
}
調用時的語法如下:
puppet apply --tags TAG1,TAG2,... FILE.PP
實例
首先,我們去修改一下redis.pp
文件,添加一個標簽進去
vim redis.pp
package{'redis':
ensure => installed,
}
file{'/etc/redis.conf':
source => '/root/manifets/file/redis.conf',
ensure => file,
owner => redis,
group => root,
mode => '0640',
tag => 'instconf' #定義標簽
}
service{'redis':
ensure => running,
enable => true,
hasrestart => true,
}
Package['redis'] -> File['/etc/redis.conf'] -> Service['redis']
然后,我們手動先開啟redis
服務:
systemctl start redis
現在,我們去修改一下file
目錄下的配置文件:
vim file/redis.conf
requirepass keerya
接着,我們就去運行redis.pp
,我們的配置文件已經修改過了,現在想要實現的就是重啟該服務,實現,需要使用密碼keer
登錄:
puppet apply -v --tags instconf redis.pp

現在,我們就去登錄一下redis看看是否生效:
redis-cli -a keerya

驗證成功,實驗完成。
5、puppet 變量
puppet 變量以“$”開頭,賦值操作符為“=”,語法為$variable_name=value
。
數據類型:
字符型:引號可有可無;但單引號為強引用,雙引號為弱引用;支持轉義符;
數值型:默認均識別為字符串,僅在數值上下文才以數值對待;
數組:[]中以逗號分隔元素列表;
布爾型值:true, false;不能加引號;
hash:{}中以逗號分隔k/v數據列表; 鍵為字符型,值為任意puppet支持的類型;{ ‘mon’ => ‘Monday’, ‘tue’ => ‘Tuesday’, };
undef:從未被聲明的變量的值類型;
正則表達式:
(?<ENABLED OPTION>:<PATTERN>)
(?-<DISABLED OPTION>:<PATTERN>)
OPTIONS:
i:忽略字符大小寫;
m:把.當換行符;
x:忽略<PATTERN>中的空白字符;
(?i-mx:PATTERN)
注意:不能賦值給變量,僅能用在接受=~
或!~
操作符的位置;
1)puppet的變量種類
puppet 種類有三種,為facts
,內建變量
和用戶自定義變量
。
facts:
由facter提供;top scope;
內建變量:
master端變量
$servername, $serverip, $serverversion
agent端變量
$clientcert, $clientversion, $environment
parser變量
$module_name
用戶自定義變量
2)變量的作用域
不同的變量也有其不同的作用域。我們稱之為Scope
。
作用域有三種,top scope,node scope,class scope。
其生效范圍排序為:top scope > node scope > class scope

其優先級排序為:top scope < node scope < class scope
6、puppet 流程控制語句
puppet 支持if 語句,case 語句和selector 語句。
1)if 語句
if語句支持單分支,雙分支和多分支。具體語法如下:
單分支:
if CONDITION {
statement
……
}
雙分支:
if CONDITION {
statement
……
}
else{
statement
……
}
多分支:
if CONDITION {
statement
……
}
elsif CONDITION{
statement
……
}
else{
statement
……
}
其中,CONDITION的給定方式有如下三種:
- 變量
- 比較表達式
- 有返回值的函數
舉例
vim if.pp
if $operatingsystemmajrelease == '7' {
$db_pkg='mariadb-server'
}else{
$db_pkg='mysql-server'
}
package{"$db_pkg":
ensure => installed,
}
2)case 語句
類似 if 語句,case 語句會從多個代碼塊中選擇一個分支執行,這跟其它編程語言中的 case 語句功能一致。
case 語句會接受一個控制表達式和一組 case 代碼塊,並執行第一個匹配到控制表達式的塊。
使用語法如下:
case CONTROL_EXPRESSION {
case1: { ... }
case2: { ... }
case3: { ... }
……
default: { ... }
}
其中,CONTROL_EXPRESSION的給定方式有如下三種:
- 變量
- 表達式
- 有返回值的函數
各case的給定方式有如下五種:
- 直接字串;
- 變量
- 有返回值的函數
- 正則表達式模式;
- default
舉例
vim case.pp
case $osfamily {
"RedHat": { $webserver='httpd' }
/(?i-mx:debian)/: { $webserver='apache2' }
default: { $webserver='httpd' }
}
package{"$webserver":
ensure => installed, before => [ File['httpd.conf'], Service['httpd'] ],
}
file{'httpd.conf':
path => '/etc/httpd/conf/httpd.conf',
source => '/root/manifests/httpd.conf',
ensure => file,
}
service{'httpd':
ensure => running,
enable => true, restart => 'systemctl restart httpd.service',
subscribe => File['httpd.conf'],
}
3)selector 語句
Selector 只能用於期望出現直接值(plain value) 的地方,這包括變量賦值、資源屬性、函數參數、資源標題、其它 selector。
selector 不能用於一個已經嵌套於於selector 的case 中,也不能用於一個已經嵌套於case 的case 語句中。
具體語法如下:
CONTROL_VARIABLE ? {
case1 => value1,
case2 => value2,
...
default => valueN,
}
其中,CONTROL_EXPRESSION的給定方式有如下三種:
- 變量
- 表達式
- 有返回值的函數
各case的給定方式有如下五種:
- 直接子串;
- 變量;
- 有返回值的函數;
- 正則表達式模式;
- default
selectors 使用要點:
- 整個selector 語句會被當作一個單獨的值,puppet 會將控制變量按列出的次序與每個case 進行比較,並在遇到一個匹配的 case 后,將其值作為整個語句的值進行返回,並忽略后面的其它 case。
- 控制變量與各 case 比較的方式與 case 語句相同,但如果沒有任何一個 case 與控制變量匹配時,puppet 在編譯時將會返回一個錯誤,因此,實踐中,其必須提供default case。
- selector 的控制變量只能是變量或有返回值的函數,切記不能使用表達式。
- 其各 case 可以是直接值(需要加引號) 、變量、能調用返回值的函數、正則表達式模式或 default。
- 但與 case 語句所不同的是,selector 的各 case 不能使用列表。
- selector 的各 case 的值可以是一個除了 hash 以外的直接值、變量、能調用返回值的函數或其它的 selector。
舉例
vim selector.pp
$pkgname = $operatingsystem ? {
/(?i-mx:(ubuntu|debian))/ => 'apache2',
/(?i-mx:(redhat|fedora|centos))/ => 'httpd',
default => 'httpd',
}
package{"$pkgname":
ensure => installed,
}
寫在后面
以上,我們本次的介紹就告一段落,剩余的部分,請看下回分解。
作者:珂兒吖
出處:http://www.cnblogs.com/keerya/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
大家寫文都不容易,希望尊重勞動成果喲~