Puppet —自動化部署工具詳解
一個集羣的自動化部署過程可以分爲三個階段:供應階段(操作系統部署階段)、初始化配置階段、命令和管控階段。
操作系統部署階段常用的工具有:pxe , cobbler 等
初始化配置階段工具 :ansible(agentless) , puppet(master/agent) (ruby), saltstack (python) 等
命令和管控階段工具 :ansible(playbook) , fabric(fab) , func 等
Puppet 是一款應用非常廣泛的高性能環境自動化部署工具,本文以 puppet-3.8.7-1.el7.noarch 版本爲例來了解下這款程序的工作機制和應用方法。
與 Ansible 程序利用 ssh 遠程協議與從節點主機通信不同的是,Puppet 中的 Master 和 Agent 間採用 https 協議通信,Puppet 的執行效率更高。
puppet 的兩種工作模型
Standalone (單機)模型:手動應用清單
Master/Agent (主從)模型:由agent週期性地向Master請求清單並自動應用於本地
puppet 程序介紹
Master端主機需要安裝的程序包:facter,puppet,puppet-server
Agent端主機需要安裝的程序包:facter,puppet
- 程序配置文件路徑 :/etc/puppet
- puppet主程序路徑 :/usr/bin/puppet
puppet 程序的工作架構分級
查看puppet的程序目錄,其中的每個文件或目錄都有其重要功用
ls /etc/puppet
auth.conf environments fileserver.conf manifests modules puppet.conf
配置類文件
puppet.conf :puppet程序的通用主配置文件,其中定義了 “[main]” , “[agent]” 兩個配置段,定義了部分 puppet 程序的初始化默認配置,可使用 “puppet config print” 命令查看 puppet 程序的所有配置項的默認值
auth.conf :認證信息文件,其中定義了主節點和各個從節點主機的各類權限,可在此處設置主從間通信的訪問權限
fileserver.conf :文件系統配置文件,可在此文件中定義新的掛載點,供主從間通信使用
Master/Agent 模型
environments :環境,指將要部署的環境
- 在實際應用中,一般有 development , testing , production 等幾種常見部署環境
manifests :主機清單,此目錄下應存在一個 site.pp 文件,該文件定義了集羣中的每臺主機的主機名和每臺主機要執行的動作(引用的模塊名、類名),每臺主機連接
Standalone 模型
manifests :主機清單存放目錄,用於本地編輯 site.pp 文件,將所有附屬的Agent的主機信息都放在主機清單中
modules :模塊存放目錄,可以在此處開發modules,開發完成後放置於environments的對應環境下
Puppet中的 modules 開發
1.resource (資源)
- 資源的格式示例:
type{'title':
attribute_1 => 'value_1',
attribute_2 => 'value_2',
...
}
- 資源引用:Type[‘title’]
注意:資源中的 “type” 必須要小寫,在被引用時,資源中的 “Type” 首字母大寫,其餘字母小寫;title是一個字符串,在同一類型中必須惟一。
2.資源類型:
常用的資源有8個 :group, user, package, service, file , exec, cron, notify,每個資源中都含有不同的屬性
資源有三個的特殊屬性
- Namevar, 可簡稱爲name;name可省略,此時將由title表示
- ensure:資源的目標狀態;
- Provider:指明資源的管理接口資源間關係的元參數metaparameters:
- 前置/依賴關係:before/require
A before B: B依賴於A,定義在A資源中;
{
...
before => Type['B'],
...
}
B require A: B依賴於A,定義在B資源中;
{
...
require => Type['A'],
...
}
- 通知/訂閱關係:notify/subscribe
notify
A notify B:B依賴於A,且A發生改變後會通知B;
{
...
notify => Type['B'],
...
}
subscribe
B subscribe A:B依賴於A,且B監控A資源的變化產生的事件;
{
...
subscribe => Type['A'],
...
}
- 關係元參數也可以用符號表示 :->, ~>
Package['httpd'] -> File['httpd.conf'] -> Service['httpd']
- user:Manage users.
屬性:
name:用戶名
uid: UID
gid:基本組ID
groups:附加組,不能包含基本組
comment:註釋
expiry:過期時間
home:家目錄
shell:默認shell類型
system:是否爲系統用戶
ensure:present/absent
password:加密後的密碼串
- group:Manage groups.
屬性:
name:組名
gid:GID
system:是否爲系統組,true OR false
ensure:目標狀態,present/absent
members:成員用戶
- package:Manage packages.
屬性:
ensure:installed, present, latest, absent
name:包名
source:程序包來源,僅對不會自動下載相關程序包的provider有用,例如rpm或dpkg
- service:Manage running services.
屬性:
ensure:Whether a service should be running. Valid values are `stopped` (also called `false`), `running` (also called `true`).
enable:Whether a service should be enabled to start at boot. Valid values are `true`, `false`, `manual`.
name:
path:The search path for finding init scripts. Multiple values should be separated by colons or provided as an array. 腳本的搜索路徑,默認爲/etc/init.d/
hasrestart:
hasstatus:
start:手動定義啓動命令
stop:
status:
restart:Specify a *restart* command manually. If left unspecified, the service will be stopped and then started. 通常用於定義reload操作
- file:Manages files, including their content, ownership, and permissions.
屬性:
ensure:Whether the file should exist, and if so what kind of file it should be. Possible values are `present`, `absent`, `file`, `directory`, and `link`.
file:類型爲普通文件,其內容由content屬性生成或複製由source屬性指向的文件路徑來創建;
link:類型爲符號鏈接文件,必須由target屬性指明其鏈接的目標文件;
directory:類型爲目錄,可通過source指向的路徑複製生成,recurse屬性指明是否遞歸複製
path:文件路徑;
source:源文件;
content:文件內容;
target:符號鏈接的目標文件;
owner:屬主
group:屬組
mode:權限;
atime/ctime/mtime:時間戳
可使用puppet URL :puppet:///modules/MODULE_NAME/FILE_NAME
- exec:Executes external commands. Any command in an
exec
resource must be able to run multiple times without causing harm — that is, it must be idempotent.
屬性:
command (namevar):要運行的命令
cwd:The directory from which to run the command
creates:文件路徑,僅此路徑表示的文件不存在時,command方纔執行
user/group:運行命令的用戶身份
path:The search path used for command execution. Commands must be fully qualified if no path is specified
onlyif:此屬性指定一個命令,此命令正常(退出碼爲0)運行時,當前command纔會運行
unless:此屬性指定一個命令,此命令非正常(退出碼爲非0)運行時,當前command纔會運行
refresh:重新執行當前command的替代命令
refreshonly:僅接收到訂閱的資源的通知時方纔運行
- cron:Installs and manages cron jobs. Every cron resource created by Puppet requires a command and at least one periodic attribute (hour, minute, month, monthday, weekday, or special).
屬性:
command:要執行的任務
ensure:present/absent
hour:
minute:
monthday:
month:
weekday:
user:以哪個用戶的身份運行命令
target:添加爲哪個用戶的任務
name:cron job的名稱
- notify:Sends an arbitrary message to the agent run-time log.
屬性:
message:信息內容
name:信息名稱
3.puppet 的 variable (變量)
FQN: $::scope1::scope2::variable
$variable_name=value
數據類型:字符串、數值、布爾型、數組、hash、undef
- 字符型:引號可有可無;但單引號爲強引用,雙引號爲弱引用;
- 數值型:默認均識別爲字符串,僅在數值上下文才以數值對待;
- 數組:[]中以逗號分隔元素列表;
- 布爾型值: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)
4.變量類型
facts:
由facter提供;top scope;
內建變量:
master端變量
agent端變量
parser變量
用戶自定義變量:
變量有作用域,稱爲Scope;
top scope: 如 $::var_name
node scope
class scope
5.puppet流程控制語句
if , case , selector , unless
- if 語句
if CONDITION {
...
} else {
...
}
CONDITION的給定方式:
(1) 變量
(2) 比較表達式
(3) 有返回值的函數
- 示例:
vim /etc/puppet/modules/webserver.pp
#內容如下:
if $osfamily =~ /(?i-mx:debian)/ {
$webserver = 'apache2'
} else {
$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'],
}
case 語句
- 語法及格式
case CONTROL_EXPRESSION {
case1: { ... }
case2: { ... }
case3: { ... }
...
default: { ... }
}
CONTROL_EXPRESSION:
(1) 變量
(2) 表達式
(3) 有返回值的函數
各case的給定方式:
(1) 直接字串;
(2) 變量
(3) 有返回值的函數
(4) 正則表達式模式;
(5) default
- case 語句示例:
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'],
}
selector 語句
- 語法及格式
CONTROL_VARIABLE ? {
case1 => value1,
case2 => value2,
...
default => valueN,
}
CONTROL_VARIABLE的給定方法:
(1) 變量
(2) 有返回值的函數
各case的給定方式:
(1) 直接字串;
(2) 變量
(3) 有返回值的函數
(4) 正則表達式模式;
(5) default
注意:不能使用列表格式;但可以是其它的selecor
- 示例:
$webserver = $osfamily ? {
"Redhat" => 'httpd',
/(?i-mx:debian)/ => 'apache2',
default => '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'],
}
6.puppet的類
類:puppet中命名的代碼模塊,常用於定義一組通用目標的資源,可在puppet全局調用;類可以被繼承,也可以包含子類;
- 語法格式:
class NAME {
...puppet code...
}
class NAME(parameter1, parameter2) {
...puppet code...
}
- 類代碼只有聲明後纔會執行,調用方式:
(1) include CLASS_NAME1, CLASS_NAME2, ...
(2) class{'CLASS_NAME':
attribute => value,
}
子類
sub_class_name:
base_class::sub_class_name
子類中引用父類的資源:
Type['title'] {
attribute => value,
atrribute +> value,
}
在子類中爲父類的資源新增屬性或覆蓋指定的屬性的值:
Type['title'] {
attribute1 => value,
...
}
在子類中爲父類的資源的某屬性增加新值:
Type['title'] {
attribute1 +> value,
...
}
- 示例
#定義父類nginx
class nginx {
package{'nginx':
ensure => installed,
}
service{'nginx':
ensure => running,
enable => true,
restart => '/usr/sbin/nginx -s reload',
}
}
#定義nginx的子類nginx::web
class nginx::web inherits nginx {
Service['nginx'] {
subscribe => File['ngx-web.conf'],
}
file{'ngx-web.conf':
path => '/etc/nginx/conf.d/ngx-web.conf',
ensure => file,
source => '/root/manifests/ngx-web.conf',
}
}
#定義nginx的子類nginx::proxy
class nginx::proxy inherits nginx {
Service['nginx'] {
subscribe => File['ngx-proxy.conf'],
}
file{'ngx-proxy.conf':
path => '/etc/nginx/conf.d/ngx-proxy.conf',
ensure => file,
source => '/root/manifests/ngx-proxy.conf',
}
}
#調用(聲明)nging的子類nginx::proxy
include nginx::proxy
7.puppet模板
erb:模板語言,embedded ruby;
- 在資源中使用模板的格式
file{'title':
ensure => file,
content => template('MOD_NAME/ERB_FILE'),
}
- 文本文件中內嵌變量替換機制:
<%= @VARIABLE_NAME %>
8.puppet模塊
模塊就是一個按約定的、預定義的結構存放了多個文件或子目錄的目錄,目錄裏的這些文件或子目錄必須遵循一定格式的命名規範
- puppet模塊的目錄結構
MODULES_NAME:
manifests/
init.pp:必須一個類定義,類名稱必須與模塊名稱相同
files/:靜態文件
templates/:
lib/:插件目錄,常用於存儲自定義的facts以及自定義類型
spec/:類似於tests目錄,存儲lib/目錄下插件的使用幫助和範例
tests/:當前模塊的使用幫助或使用範例文件
模塊名只能以小寫字母開頭,可以包含小寫字母、數字和下劃線;但不能使用 “main” 和 “settings”
注意:
- puppet 3.8及以後的版本中,資源清單文件的文件名要與文件聽類名保持一致,例如某子類名爲“base_class::child_class”,其文件名應該爲child_class.pp
- 無需再資源清單文件中使用import語句
- manifests目錄下可存在多個清單文件,每個清單文件包含一個類,其文件名同類名
9.模塊執行測試
- standalone模式:測試命令如下
puppet apply [-d|--debug] [-v|--verbose] [-e|--execute] [--noop] <CLASS_NAME.pp>
- master/agent模式 :通過master節點的主機資源清單實現執行過程,agent每隔30分鐘到master端請求與自己相關的catalog
master: site manifest
node 'node_name' {
...puppet code...
}
10.puppet的幫助文檔
程序包下載路徑:
https://yum.puppetlabs.com/
官方文檔:
https://docs.puppet.com/puppet/3/reference/
內建函數:
https://docs.puppet.com/puppet/3/reference/function.html
配置參數列表:
https://docs.puppet.com/puppet/3/reference/configuration.html
puppet兼容的erb語法:
https://docs.puppet.com/puppet/latest/reference/lang_template_erb.html