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
等。html
puppet 經過聲明性、基於模型的方法進行IT自動化管理。
定義:經過puppet 的聲明性配置語言定義基礎設置配置的目標狀態;
模擬:強制應用改變的配置以前先進行模擬性應用;
強制:自動、強制部署達成目標狀態,糾正任何偏離的配置;
報告:報告當下狀態及目標狀態的不一樣,以及達成目標狀態所進行的任何強制性改變;
puppet三層模型
puppet三層模型以下:node
puppet的使用模型分爲單機使用模型和master/agent模型,下面咱們來看看這兩個模型的原理圖。
單機使用模型
實現定義多個manifests --> complier --> catalog --> applymysql
master/agent模型
master/agent模型實現的是集中式管理,即 agent 端週期性向 master 端發起請求,請求本身須要的數據。而後在本身的機器上運行,並將結果返回給 master 端。
架構和工做原理以下:
架構nginx
工做原理web
ansible
中的模塊,只是抽象的更加完全。ansible
中的角色。 接下來,咱們就以單機模式來具體介紹一下puppet
的各個部分。正則表達式
首先,咱們仍是來安裝一下puppet
,puppet
的安裝可使用源碼安裝,也可使用rpm(官方提供)、epel源、官方提供的yum倉庫來安裝(經過下載官方提供的rpm包能夠指定官方的yum倉庫)。
在這裏,咱們就是用 yum 安裝的方式。redis
yum install -y puppet
安裝完成事後,咱們能夠經過rpm -ql puppet | less
來查看一下包中都有一些什麼文件。
其中主配置文件爲/etc/puppet/puppet.conf
,使用的主程序爲/usr/bin/puppet
。sql
puppet 從如下三個維度來對資源完成抽象:shell
- 類似的資源被抽象成同一種資源**「類型」** ,如程序包資源、用戶資源及服務資源等;
- 將資源屬性或狀態的描述與其實現方式剝離開來,如僅說明安裝一個程序包而不用關心其具體是經過yum、pkgadd、ports或是其它方式實現;
- 僅描述資源的目標狀態,也即指望其實現的結果,而不是其具體過程,如「肯定nginx 運行起來」 而不是具體描述爲「運行nginx命令將其啓動起來」;
這三個也被稱做puppet 的資源抽象層(RAL)
RAL 由type( 類型) 和provider( 提供者,即不一樣OS 上的特定實現)組成。
apache
資源定義經過向資源類型的屬性賦值來實現,可稱爲資源類型實例化;
定義了資源實例的文件即清單,manifest;
定義資源的語法以下:
type {'title': attribute1 => value1, atrribute2 => value2, …… }
注意:type必須使用小寫字符;title是一個字符串,在同一類型中必須唯一;每個屬性之間須要用「,」隔開,最後一個「,」可省略。
例如,能夠同時有名爲nginx 的「service」資源和「package」資源,但在「package」 類型的資源中只能有一個名爲「nginx」的資源。
Namevar
:可簡稱爲name;ensure
:資源的目標狀態;Provider
:指明資源的管理接口;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
來列出,上文中也已經說過了~
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'] #定義依賴關係
如同 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
驗證成功,實驗完成。
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)
注意:不能賦值給變量,僅能用在接受=~
或!~
操做符的位置;
puppet 種類有三種,爲facts
,內建變量
和用戶自定義變量
。
facts:
由facter提供;top scope;
內建變量:
master端變量
$servername, $serverip, $serverversion
agent端變量
$clientcert, $clientversion, $environment
parser變量
$module_name
用戶自定義變量
不一樣的變量也有其不一樣的做用域。咱們稱之爲Scope
。
做用域有三種,top scope,node scope,class scope。
其生效範圍排序爲:top scope > node scope > class scope
其優先級排序爲:top scope < node scope < class scope
puppet 支持if 語句,case 語句和selector 語句。
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, }
相似 if 語句,case 語句會從多個代碼塊中選擇一個分支執行,這跟其它編程語言中的 case 語句功能一致。
case 語句會接受一個控制表達式和一組 case 代碼塊,並執行第一個匹配到控制表達式的塊。
使用語法以下:
case CONTROL_EXPRESSION { case1: { ... } case2: { ... } case3: { ... } …… default: { ... } }
其中,CONTROL_EXPRESSION的給定方式有以下三種:
各case的給定方式有以下五種:
舉例
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'], }
Selector 只能用於指望出現直接值(plain value) 的地方,這包括變量賦值、資源屬性、函數參數、資源標題、其它 selector。
selector 不能用於一個已經嵌套于于selector 的case 中,也不能用於一個已經嵌套於case 的case 語句中。
具體語法以下:
CONTROL_VARIABLE ? { case1 => value1, case2 => value2, ... default => valueN, }
其中,CONTROL_EXPRESSION的給定方式有以下三種:
各case的給定方式有以下五種:
selectors 使用要點:
舉例
vim selector.pp $pkgname = $operatingsystem ? { /(?i-mx:(ubuntu|debian))/ => 'apache2', /(?i-mx:(redhat|fedora|centos))/ => 'httpd', default => 'httpd', } package{"$pkgname": ensure => installed, }
以上,咱們本次的介紹就告一段落,剩餘的部分,請看下回分解。