本文收錄在Linux運維企業架構實戰系列
1、認識puppet
1.1 引入
puppet是什么,咱們先不用專業的名詞解釋它,咱們先描述一些工作場景,看明白這些工作場景,自然會知道puppet是什么。
(1)場景一:
管理員想要在100台服務器上同時創建一個名叫"along"的用戶,怎么辦,當然,我們可以"手動解決",登錄每一台服務器,然后一台一台的創建用戶,如果你真的這樣干,那么我只能說,算你狠!!!但是,既然我們這篇文章是介紹puppet的,我們肯定會推薦你使用puppet解決這個問題。
(2)場景二:
公司新買了一堆雲服務器,這些服務器最終可能要提供相同的服務,現在需要管理員在這一堆服務器上安裝一些相同的應用,而且安裝完成后,還需要這些服務器上的應用自動啟動,怎么辦,當然,手動解決算你狠,兄弟我服了,你說你寫腳本解決,嗯,這是個辦法,在我沒有認識puppet之前我可能也會寫個腳本,但是我們是介紹puppet的,我們會推薦你使用puppet解決這個問題。
(3)場景三:
在一些服務器中,執行大批量的重復操作,我們可以使用puppet。
看完上述三個場景,你應該已經大概猜出puppet是干嗎的了,沒錯,說的糙一點,你可以把它理解成批量處理工具,但是你又不能完全把它理解成批量處理工具,因為除了批量處理,他還有一些別的功能和特性,我們暫且先這么認為,以便我們入門。
1.2 介紹
(1)我自己對puppet的了解
像puppet這種工具有幾個專業的名詞可以用來稱呼它們:"配置管理工具"、"自動化運維管理工具"。
Linux中,常見的配置管理工具有puppet、saltstack、ansible(博主之前講解過)、chef等,它們的功能類似,puppet算是這個領域里面的老大哥,時間久(我說的是創始時間久,不要想歪了····),成熟,被廣泛的應用,google、twitter、redhat,cisco等大公司都用到了它,功能強大,puppet是使用ruby研發的,saltstack和ansible都屬於python系的, ansible和saltstack與puppet相比,屬於后起之秀,我們以后也可能會對它們進行總結,但是現在,我們只聊puppet。
(2)專業術語介紹
- ① puppet是一種Linux/Unix平台下的集中配置管理系統,使用自有的puppet描述語言,可管理配置文件、用戶、cron任務、軟件包、系統服務等。puppet把這些系統實體稱之為資源,puppet的設計目標是簡化對這些資源的管理以及妥善處理資源間的依賴關系。
- ② Puppet是開源的基於Ruby的系統配置管理工具,puppet是一個C/S結構。所有的puppet客戶端同一個服務器端的puppet通訊,每個puppet客戶端每半小時(可以設置)連接一次服務器端,下載最新的配置文件,並且嚴格按照配置文件來配置服務器。 配置完成以后,puppet客戶端可以反饋給服務器端一個消息, 如果出錯,也會給服務器端反饋一個消息。
- ③ Puppet是用於大規模集群管理的神器。其本身使用Ruby語言開發,基於C/S架構。在每台機器上部署的客戶端每隔一個指定的時間會連接到Master檢查資源變化情況,若資源發生變化,將按配置動作進行相應的操作。
- ④ Puppet將所有可操作對象抽象為資源,目前涵蓋了40多種,如:File、User、Group、Host、Package、Service、Cron、Exec等,下面我會一一講述。
- ⑤ Puppet 通過抽象資源的方式,使得每台機器能夠“清楚”其本身“應該”是什么“狀態”,而客戶端根據當前是否達到這個狀態決定采取指定的動作。這使得Puppet 不僅可用於傳統的應用部署,而且通過合理的手段,也能夠將比應用部署更頻繁的配置管理一並解決。甚至可以在Master端外接自己開發的平台,通過集中配 置方式管理各項“資源”,實現高度靈活的自動化管理體系。
1.3 puppet 名詞解釋
- 資源:是puppet的核心,通過資源申報,定義在資源清單中。相當於ansible中的模塊,只是抽象的更加徹底。
- 類:一組資源清單。
- 模塊:包含多個類。相當於ansible中的角色。
- 站點清單:以主機為核心,應用哪些模塊。
本篇文章主要講解資源;類、模塊、站點清單都在下篇進行詳解。
1.4 puppet常用資源類型
group | 組 |
user | 用戶 |
packge | 程序包 |
service | 服務 |
file | 文件 |
exec | 執行自定義命令 |
cron | 周期性任務計划 |
notify | 通知 |
yumrepo | 源 |
host | /etc/hosts中主機解析 |
1.5 puppet命令使用
(1)查詢資源類型和幫助信息
puppet describe [-h|--help] [-s|--short] [-p|--providers] [-l|--list] [-m|--meta] [type]
- -l:列出所有資源類型;
- -s:顯示指定類型的簡要幫助信息;也就是基本選項
- -m:顯示指定類型的元參數,一般與-s 一同使用;這些選項只是來描述這個類型的
(2)執行資源清單命令
puppet apply [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose] [-e|--execute] [--detailed-exitcodes] [-l|--logdest <file>] [--noop] [--catalog <catalog>] [--write-catalog-summary] <file>
- -d:打開調試信息,會顯示很多信息
- -v:顯示詳細信息
- -e:直接執行給定的命令
- -l:執行結果保存到指定日志的文件中,否則執行結果會輸出到標准輸出
- --noop:dry run 干跑,只是測試的跑一邊,不真正的執行
- --catalog:應用JSON目錄
1.6 puppet的優缺點
這類垂直管理系統的使用及活躍,極大減輕了運維人員在重復性、批量化操作方面的負擔,能夠非常有效地在各自領域完成既定的運維子目標。但其缺陷在於只能針對某一垂直領域的特定問題進行高效處理,對於它們之間的關聯性很難應對。因為運維的本質是保證服務的可用性,而自動化運維則是在完全保證這一前提下,盡可能將需要人干涉的部分處理掉,所以判斷其優劣的標准則是——與人工處理比,對服務的保證有沒有提高。如果僅是解決報警、部署這些單一動作,后續仍然需要人去處理、去關注、去判斷的話,就離這個目標還有距離,談不上真正的自動化,只能算是工具化。
puppet是一個開源的軟件自動化配置和部署工具,它使用簡單且功能強大,正得到了越來越多地關注,現在很多大型IT公司均在使用puppet對集群中的軟件進行管理和部署,如google利用puppet管理超過6000台地mac桌面電腦(2007年數據)。
puppet設計架構是基於c/s架構的。服務器端保存着所有對客戶端服務器的配置代碼,在puppet里面叫做manifest. 客戶端下載manifest之后,可以根據manifest對服務器進行配置,例如軟件包管理,用戶管理和文件管理等等。
2、puppet的使用模型及工作流程
puppet的使用模型分為 單機使用模型 和 master/agent模型;本文主要講解單機使用模型,便於入門。
2.1 master/agent模型
從上述專業的解釋中,我們可以得知puppet是C/S架構的,也就是說,它有服務端,也有客戶端,管理員可以通過puppet服務端(master),管理每一台被管理的服務器,但是需要puppet客戶端作為中介,也就是說,puppet客戶端作為代理(agent),接收來自puppet服務端的配置信息,按照服務端(master)發送過來的配置信息,對被管理服務器進行配置,真正執行配置操作的是puppet客戶端,puppet服務端只負責將配置信息准備好,發送給puppet客戶端,以便客戶端執行具體操作,puppet客戶端還有另一個作用,就是向puppet服務端發送報告,當客戶端按照配置信息執行完成相關配置以后,會將執行信息發送到服務端,比如執行成功與否,執行結果等,默認情況下,每30分鍾,puppet客戶端會向puppet服務端發起一次請求,請求受管理服務器的配置信息, puppet服務端將配置信息發送給客戶端,客戶端根據反回的信息進行判斷,判斷被管理服務器是否符合管理員定義的配置,puppet的這種工作模式就是C/S架構的,也可以理解為master/agent的工作模式,用文字描述顯得太無力,我們畫個圖來看看。
那么,我們把上圖中的兩台服務器拿出來,詳細說說它們之間的具體工作流程,但是此處我們需要說明,在master/agent模型下工作的puppet的工作流程比我們總結的要復雜一點,但是為了入門方便,我們只取出其中的一部分核心的流程進行總結,在后面的實際應用中,我們會不斷的豐富這些流程,此處先給出一個簡化過的流程圖,如下圖所示。
過程分析:
① 客戶端puppet agent請求catalog,我們已經說過,catalog其實就是被管理服務器對應的配置文件(經過處理過的配置文件),服務端master收到agent的請求,然后找到對應被管理服務器的"站點清單",或者被稱為"主機清單",因為一台"被管理服務器"可能同時擔任多個"角色",每個角色可能都會對應一個"manifest"(也就是清單),所以,我們可以為每一台被管理服務器配置一個"站點清單",站點清單也可以理解成為一種"清單",只是它是針對一台服務器而存在的一種清單。
② 服務端master找到被管理服務器的站點清單后,根據站點清單,找到對應服務器需要哪些"清單",因為一台服務器可能會需要多張"清單",上圖中為了示例,只畫出了一個清單,但是這不代表必定只有一個。
③ master將找到的所有"清單"進行處理,處理為catalog。
④ master將處理過的catalog發送到agent端。
⑤ agent收到master發送過來的catalog,然后,agent會查詢"被管理服務器的當前狀態",看看服務器的當前狀態是否符合catalog中定義的目標狀態。
⑥ 如果"被管理服務器的當前狀態"與"catalog中定義的目標狀態"一致,那么資源對應的操作將不會執行,如果"被管理服務器的當前狀態"與"catalog中定義的目標狀態"不一致,那么資源對應的操作將會執行,以便讓"被管理服務器"達到管理員指定的"目標狀態"。
⑦ 經過上一步的"狀態判斷",執行對應操作,不管執行是否成功,都會生成對應的報告信息。
⑧ agent將生成的報告信息發送給master端。
上述過程,就是puppet在master/agent模式下的工作流程,我們說過,默認情況下,客戶端每隔30分鍾向服務端請求一次配置信息,然后根據服務端返回的配置信息,判斷當前服務器是否處於管理員定義的目標狀態,如果被管理的服務器不處於管理員定義的目標狀態,則需要執行對應的操作,使得被管理主機最終處於管理員定義的目標狀態,我們也可以不必每次都等待30分鍾,我們可以從master端推送catalog到agent端,主動告訴agent端,配置已經發生了改變,請執行對應的操作。這是后話,我們以后再聊。
2.2 單機使用模型
當然,puppet也可以不在master/agent模式下工作,我們可以在受管理服務器上只安裝puppet客戶端,使用客戶端手動執行對應配置文件,相當於配置文件中的信息並不是通過puppet服務端發送過來,而是通過本地的配置文件獲取,也是可以的,我們暫且稱這種不需要puppet服務端的工作模式為單機模式,我們在學習puppet時,可以使用單機的模式進行練習,但是在生產環境中,一般都使用master/agent的方式使用puppet。
實現定義多個manifests --> complier --> catalog --> apply
3、puppet資源詳解
3.1 puppet資源介紹
3.1.1 程序安裝及環境
首先,我們還是來安裝一下puppet,puppet的安裝可以使用源碼安裝,也可以使用rpm(官方提供)、epel源、官方提供的yum倉庫來安裝(通過下載官方提供的rpm包可以指定官方的yum倉庫)。
在這里,我們就是用 yum 安裝的方式。
[root@along ~]# yum -y install puppet
3.1.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.2 group:Manage groups
3.2.1 類型屬性選項
(1)屬性 Parameters:
- name:組名;
- gid:GID;
- system:是否為系統組,true OR false;
- ensure:目標狀態,present(創建)/absent(刪除);
- members:成員用戶;
(2)puppet describe group -s -m 使用之前,可以查詢這個類型的選項
3.2.2 演示
① 編輯manifest( 清單)
[root@along manifest]# vim group.pp group{'mygrp': name => 'mygrp', ensure => present, gid => 2000, }
② 執行並驗證 manifest
---先預執行一次,檢查是否有語法錯誤 [root@along manifest]# puppet apply -v --noop group.pp Notice: Compiled catalog for along in environment production in 0.18 seconds Info: Applying configuration version '1550042227' Notice: /Stage[main]/Main/Group[mygrp]/ensure: current_value absent, should be present (noop) Notice: Class[Main]: Would have triggered 'refresh' from 1 events Notice: Stage[main]: Would have triggered 'refresh' from 1 events Info: Creating state file /var/lib/puppet/state/state.yaml Notice: Finished catalog run in 0.03 seconds ---真正執行,執行成功 [root@along manifest]# puppet apply -v group.pp Notice: Compiled catalog for along in environment production in 0.06 seconds Info: Applying configuration version '1550042298' Notice: /Stage[main]/Main/Group[mygrp]/ensure: created Notice: Finished catalog run in 0.09 seconds ---查詢驗證 [root@along manifest]# cat /etc/group |grep mygrp mygrp:x:2000:
3.3 user:Manage users
3.3.1 類型屬性選項
(1)屬性 Parameters:
- name:用戶名;
- uid: UID;
- gid:基本組ID;
- groups:附加組,不能包含基本組;
- comment:注釋;
- expiry:過期時間 ;
- home:家目錄;
- shell:默認shell類型;
- system:是否為系統用戶 ;
- ensure:present/absent 存在/不存在;
- password:加密后的密碼串;
(2)puppet describe user -s -m 使用之前,可以查詢這個類型的選項
3.3.2 演示
① 編輯manifest( 清單)
[root@along manifest]# vim user1.pp user{'along1': ensure => present, system => false, comment => 'Test user', shell => '/usr/sbin/nologin', home => '/app/along', managehome => true, groups => 'mygrp', uid => 3000, }
② 執行manifest
[root@along manifest]# puppet apply -v --noop user1.pp [root@along manifest]# puppet apply -v user1.pp Notice: Compiled catalog for along in environment production in 0.08 seconds Info: Applying configuration version '1550042932' Notice: /Stage[main]/Main/User[along1]/ensure: created Notice: Finished catalog run in 0.12 seconds [root@along manifest]# cat /etc/passwd |grep along1 along1:x:3000:3000:Test user:/mnt/along:/usr/sbin/nologin
3.4 package:Manage packages
3.4.1 類型屬性選項
① 屬性:
- ensure:installed, present, latest, absent, any version string (implies present)
- name:包名;
- ource:程序包來源,僅對不會自動下載相關程序包的provider有用,例如rpm或dpkg;
- provider:指明安裝方式;rpm/yum/...
② puppet describe package -s -m 可以查詢這個類型的選項
3.4.2 演示
① 創建manifest
[root@along manifest]# vim pkg.pp package{'redis': ensure => installed, provider => yum }
② 執行manifest
[root@along manifest]# puppet apply --noop -v pkg.pp [root@along manifest]# puppet apply -v pkg.pp Notice: Compiled catalog for along in environment production in 0.26 seconds Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false. (at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default') Info: Applying configuration version '1550044027' Notice: /Stage[main]/Main/Package[redis]/ensure: created Notice: Finished catalog run in 6.09 seconds [root@along manifest]# rpm -ql redis
3.5 service:Manage running services
3.5.1 類型屬性選項
① 屬性:
- ensure:running\true(開啟) 或 stopped/false(停止)
- enable:是否開機自啟:true(開機自啟)、false(不自啟)、manual(手動)
- name:服務名
- binary:若服務不是systemctl/service 啟動,則需規定啟動命令;如nginx -s start
- path:如果不是systemctl/service 這樣啟動服務,而是通過腳本啟動,指明path路徑。多個值應該由冒號分隔,或者作為數組提供。腳本的搜索路徑,默認為/etc/init.d/;
- hasrestart:是否支持restart 這個參數重啟;true/fault ;true 表示支持
- hasstatus:是否支持status 這個參數查看狀態;true/false
- start:手動定義啟動命令;
- stop:手動定義關閉命令;
- status:若hasstatus 為fals 手動定義查看信息命令;
- restart:若hasrestart 為false 手動定義reload操作
② puppet describe service -s -m 可以查詢這個類型的選項
3.5.2 演示1:開啟redis 服務
① 編寫manifest 資源清單
[root@along manifest]# vim srv1.pp service{'redis': ensure => running, enable => true, }
② 執行
[root@along manifest]# puppet apply -v --noop srv1.pp [root@along manifest]# puppet apply -v srv1.pp Notice: Compiled catalog for along in environment production in 0.08 seconds Info: Applying configuration version '1550044320' Notice: /Stage[main]/Main/Service[redis]/ensure: ensure changed 'stopped' to 'running' Info: /Stage[main]/Main/Service[redis]: Unscheduling refresh on Service[redis] Notice: Finished catalog run in 0.11 seconds [root@along manifest]# ss -nutl |grep 6379 tcp LISTEN 0 128 127.0.0.1:6379 *:*
3.5.2 演示1:下載memcached 包,且開啟服務
① 編寫manifest 資源清單
[root@along manifest]# vim srv2.pp package {'memcached': ensure => installed, } service{'memcached': ensure => running, enable => false, require => Package['memcached'] }
② 執行
[root@along manifest]# puppet apply -v --noop srv2.pp [root@along manifest]# puppet apply -v srv2.pp Notice: Compiled catalog for along in environment production in 0.35 seconds Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false. (at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default') Info: Applying configuration version '1550044434' Notice: /Stage[main]/Main/Package[memcached]/ensure: created Notice: /Stage[main]/Main/Service[memcached]/ensure: ensure changed 'stopped' to 'running' Info: /Stage[main]/Main/Service[memcached]: Unscheduling refresh on Service[memcached] Notice: Finished catalog run in 3.28 seconds [root@along manifest]# ss -nutlp |grep memcached udp UNCONN 0 0 *:11211 *:* users:(("memcached",pid=8573,fd=28))
3.6 file:管理文件,包括它們的內容、所有權和權限
3.6.1 類型屬性選項
(1)類型的屬性、選項
① 屬性
- ensure:`present`創建, `absent`刪除, `file`創建普通文件, `directory`創建目錄, link`創建軟鏈接.
- file:類型為普通文件,其內容由content屬性生成或復制由source屬性指向的文件路徑來創建;
- link:類型為符號鏈接文件,必須由target屬性指明其鏈接的目標文件;
- directory:類型為目錄,可通過source指向的路徑復制生成,recurse屬性指明是否遞歸復制;
- path:文件路徑;
- source:源文件;當復制文件內容時需要指定
- content:文件內容;直接編寫文件內容
- target:符號鏈接的目標文件;
- owner:屬主
- group:屬組
- mode:權限;
- atime/ctime/mtime:時間戳;
- access time:訪問時間,atime,讀取文件內容
- modify time: 修改時間, mtime,改變文件內容(數據)
- change time: 改變時間, ctime,元數據發生改變
② puppet describe file -s -m |tail -20
3.6.2 演示1:創建test.txt,且直接寫內容
創建test.txt,且直接寫內容
① 編寫manifest 清單
[root@along manifest]# vim file1.pp file{'/mnt/test.txt': ensure => file, content => "How are you?\nHow old are you?\n", owner => 'along1', group => 'mygrp', mode => '0400' }
② 執行
[root@along manifest]# puppet apply -v --noop file1.pp [root@along manifest]# puppet apply -v file1.pp Notice: Compiled catalog for along in environment production in 0.07 seconds Info: Applying configuration version '1550044597' Notice: /Stage[main]/Main/File[/mnt/test.txt]/ensure: defined content as '{md5}93c1208b855bf27a44bb2eb1b022b8cd' Notice: Finished catalog run in 0.04 seconds [root@along manifest]# ll /mnt/test.txt -r-------- 1 along1 mygrp 30 Feb 13 15:56 /mnt/test.txt [root@along manifest]# cat /mnt/test.txt How are you? How old are you?
3.6.3 演示2:創建一個文件,且復制另一個文件的內容;再對這個文件創建一個軟鏈接文件
① 編寫manifest 清單
[root@along manifest]# vim file2.pp file{'redis.conf': path => '/mnt/redis.conf', ensure => file, source => '/root/manifest/files/redis.conf' } file{'symlink.conf': ensure => link, path => '/mnt/symlink.conf', target => '/mnt/redis.conf', require => File['redis.conf'] }
提示:若要指定source ,最好先把源文件復制到此目錄中,因為在master-agent 模式中,不能確保agent 機器上的路徑下,一定有要復制的文件;本次操作需要在/root/manifests/files/准備好redis.con文件。
[root@along manifest]# mkdir files [root@along manifest]# cp /etc/redis.conf /root/manifest/files/
② 執行
[root@along manifest]# puppet apply -v --noop file2.pp [root@along manifest]# puppet apply -v file2.pp Notice: Compiled catalog for along in environment production in 0.07 seconds Info: Applying configuration version '1550045858' Notice: /Stage[main]/Main/File[redis.conf]/ensure: defined content as '{md5}d98629fded012cd2a25b9db0599a9251' Notice: /Stage[main]/Main/File[symlink.conf]/ensure: created Notice: Finished catalog run in 0.05 seconds [root@along manifest]# ll /mnt/redis.conf /mnt/symlink.conf -rw-r----- 1 777 root 46729 Feb 13 16:17 /mnt/redis.conf lrwxrwxrwx 1 root root 15 Feb 13 16:17 /mnt/symlink.conf -> /mnt/redis.conf
3.6.4 演示3:創建目錄,且遞歸復制另一個目錄
創建目錄,且遞歸復制另一個目錄
① 編寫manifest 清單
[root@along manifest]# vim file3.pp file{'test.dir': ensure => directory, path => '/app/test.dir', source => '/etc/httpd', recurse => true #遞歸復制 }
注意:
目錄復制目錄,是將目錄下的所有文件遞歸復制;
不要用path 為目錄,source為文件,不會將此文件復制到目錄中;只能是目錄復制目錄
② 執行
[root@along manifest]# puppet apply -v file3.pp Notice: Compiled catalog for along in environment production in 0.07 seconds Info: Applying configuration version '1550046089' Notice: /Stage[main]/Main/File[test.dir]/ensure: created Notice: /Stage[main]/Main/File[/mnt/test.dir/along]/ensure: created Notice: /Stage[main]/Main/File[/mnt/test.dir/along/.bash_logout]/ensure: defined content as '{md5}6a5bc1cc5f80a48b540bc09d082b5855' Notice: /Stage[main]/Main/File[/mnt/test.dir/symlink.conf]/ensure: created Notice: /Stage[main]/Main/File[/mnt/test.dir/along/.bash_profile]/ensure: defined content as '{md5}f939eb71a81a9da364410b799e817202' Notice: /Stage[main]/Main/File[/mnt/test.dir/redis.conf]/ensure: defined content as '{md5}d98629fded012cd2a25b9db0599a9251' Notice: /Stage[main]/Main/File[/mnt/test.dir/along/.bashrc]/ensure: defined content as '{md5}2f8222b4f275c4f18e69c34f66d2631b' Notice: /Stage[main]/Main/File[/mnt/test.dir/test.txt]/ensure: defined content as '{md5}93c1208b855bf27a44bb2eb1b022b8cd' Notice: Finished catalog run in 0.08 seconds [root@along manifest]# ll /mnt/test.dir/ total 52 drwx------ 2 along1 along1 62 Feb 13 16:21 along -rw-r----- 1 777 root 46729 Feb 13 16:21 redis.conf lrwxrwxrwx 1 root root 15 Feb 13 16:21 symlink.conf -> /mnt/redis.conf -r-------- 1 along1 mygrp 30 Feb 13 16:21 test.txt
3.6.5 演示4:下載redis 包,復制配置文件,啟動redis 服務
下載redis 包,復制配置文件,啟動redis 服務
① 編寫manifest 清單
[root@along manifest]# vim srv3.pp package{'redis': ensure => installed, } file{'/etc/redis.conf': ensure => file, source => '/root/manifest/files/redis.conf', owner => 'redis', group => 'root', mode => '0640' } service{'redis': ensure => running, enable => false } Package['redis'] -> File['/etc/redis.conf'] -> Service['redis']
注意:我事先將/root/manifest/files/redis.conf配置文件的端口修改為了6300
② 執行
[root@along manifest]# puppet apply -v --noop srv3.pp [root@along manifest]# puppet apply -v srv3.pp Notice: Compiled catalog for along in environment production in 0.46 seconds Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false. (at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default') Info: Applying configuration version '1550046351' Notice: /Stage[main]/Main/Package[redis]/ensure: created Info: /Stage[main]/Main/File[/etc/redis.conf]: Filebucketed /etc/redis.conf to puppet with sum d98629fded012cd2a25b9db0599a9251 Notice: /Stage[main]/Main/File[/etc/redis.conf]/content: content changed '{md5}d98629fded012cd2a25b9db0599a9251' to '{md5}d3fc0c22e1a90f88a895242b2a251dad' Notice: /Stage[main]/Main/Service[redis]/ensure: ensure changed 'stopped' to 'running' Info: /Stage[main]/Main/Service[redis]: Unscheduling refresh on Service[redis] Notice: Finished catalog run in 3.65 seconds [root@along manifest]# ss -nutlp |grep 6300 tcp LISTEN 0 128 127.0.0.1:6300 *:* users:(("redis-server",pid=11628,fd=4))
3.7 exec:執行外部命令
注意:exec資源中的任何命令都必須能夠多次運行而不會造成損害——也就是說,它必須具有冪等性。
3.7.1 類型屬性選項
- command:要運行的命令;
- cwd:用於運行該命令的目錄
- creates:文件路徑,僅此路徑表示的文件不存在時,command方才執行;
- user/group:運行命令的用戶身份;
- path:用於執行命令的搜索路徑。如果沒有指定路徑,則命令必須完全限定。
- onlyif:此屬性指定一個命令,此命令正常(退出碼為0)運行時,當前command才會運行;
- unless:此屬性指定一個命令,此命令非正常(退出碼為非0)運行時,當前command才會運行;
- refresh:重新執行當前command的替代命令;
- refreshonly:僅接收到訂閱的資源的通知時方才運行;
3.7.2 演示1:創建一個目錄
創建一個目錄
① 編寫manifest 清單
[root@along manifest]# vim cmd1.pp exec{'cmd': command => '[ -e /mnt/testdir ] || mkdir /mnt/testdir', path => ['/bin','sbin','/usr/bin','/usr/sbin'], # creates => '/mnt/testdir' 判斷目錄是否存在 }
分析:先判斷目錄是否存在,不存在再創建目錄,使命令具有冪等性;就算是目錄已存在,也不會有報錯
② 執行
[root@along manifest]# puppet apply -v cmd1.pp Notice: Compiled catalog for along in environment production in 0.02 seconds Info: Applying configuration version '1550047003' Notice: /Stage[main]/Main/Exec[cmd]/returns: executed successfully Notice: Finished catalog run in 0.03 seconds [root@along manifest]# ll -d /mnt/testdir/ drwxr-xr-x 2 root root 6 Feb 13 16:36 /mnt/testdir/ [root@along manifest]# puppet apply -v cmd1.pp Notice: Compiled catalog for along in environment production in 0.02 seconds Info: Applying configuration version '1550047046' Notice: /Stage[main]/Main/Exec[cmd]/returns: executed successfully Notice: Finished catalog run in 0.03 seconds
3.7.3 演示2:創建一個用戶
---編寫manifest 清單 [root@along manifest]# vim cmd2.pp exec{'user': command => 'useradd along', path => '/bin:sbin:/usr/bin:/usr/sbin', unless => 'id along' } ---執行 [root@along manifest]# puppet apply -v cmd2.pp Notice: Compiled catalog for along in environment production in 0.02 seconds Info: Applying configuration version '1550047187' Notice: Finished catalog run in 0.03 seconds [root@along manifest]# id along uid=1000(along) gid=1000(along) groups=1000(along)
3.7.4 演示3:下載,開啟redis
① 編寫manifest 清單
[root@along manifest]# vim cmd3.pp package{'redis': ensure => installed, } file{'/etc/redis.conf': ensure => file, source => '/root/manifest/files/redis.conf', owner => 'redis', group => 'root', mode => '0640' } exec{'redis': command => '/usr/bin/systemctl start redis', refresh => "/usr/bin/systemctl restart redis", user => 'redis', group => 'redis', } Package['redis'] -> File['/etc/redis.conf'] ~> Exec['redis']
注意:當配置文件修改,觸發動作,會執行refresh 命令替代command
② 執行
[root@along manifest]# vim files/redis.conf 把redis 端口修改為7777,再執行 port 7777 [root@along manifest]# puppet apply -v cmd3.pp Notice: Compiled catalog for along in environment production in 0.38 seconds Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false. (at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default') Info: Applying configuration version '1550109397' Notice: /Stage[main]/Main/Exec[redis]/returns: executed successfully Notice: Finished catalog run in 0.12 seconds [root@along manifest]# ss -nutlp |grep redis tcp LISTEN 0 128 127.0.0.1:7777 *:* users:(("redis-server",pid=4988,fd=4))
3.8 cron:安裝和管理cron作業
由Puppet創建的每個cron資源都需要一個命令和至少一個周期屬性(小時、分鍾、月、月、工作日、或特殊)
3.8.1 類型屬性選項
- command:要執行的任務;
- ensure:present/absent;
- hour:
- minute:
- monthday:
- month:
- weekday:
- user:以哪個用戶的身份運行命令
- target:添加為哪個用戶的任務
- name:cron job的名稱;
3.8.2 演示
① 編寫manifest 清單
下載ntpdate包,並制定計划任務,每隔5分鍾同步一次時間
[root@along manifest]# vim cron.pp package{'ntpdate': ensure => installed, } cron{'mysync': command => '/usr/sbin/ntpdate 192.168.10.1 &> /dec/null', ensure => present, minute => "*/5", target => 'root' }
② 執行
[root@along manifest]# puppet apply -v cron.pp Notice: Compiled catalog for along in environment production in 0.29 seconds Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false. (at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default') Info: Applying configuration version '1550109974' Notice: /Stage[main]/Main/Cron[mysync]/ensure: created Notice: /Stage[main]/Main/Package[ntpdate]/ensure: created Notice: Finished catalog run in 3.20 seconds [root@along manifest]# crontab -l # HEADER: This file was autogenerated at 2019-02-14 10:06:14 +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: mysync */5 * * * * /usr/sbin/ntpdate 192.168.10.1 &> /dec/null
3.9 notify:向代理運行時日志發送一個任意的消息
3.9.1 類型屬性選項
- message:信息內容
- name:信息名稱;
3.9.2 演示
---編寫manifest 清單 [root@along manifest]# vim notify.pp notify{'syhi': message => "hi there." } ---執行 [root@along manifest]# puppet apply -v notify.pp Notice: Compiled catalog for along in environment production in 0.01 seconds Info: Applying configuration version '1550110275' Notice: hi there. Notice: /Stage[main]/Main/Notify[syhi]/message: defined 'message' as 'hi there.' Notice: Finished catalog run in 0.04 seconds
3.10 非核心類型的常用資源:yumrepo, host
(1)yumrepo:yum源
(2)host:定義/etc/hosts 中名字解析
4、資源的特殊屬性
4.1 資源間依賴和通知關系
4.1.1 依賴關系元參數:before/require
(1)格式:3中實現方法
① A before B: B依賴於A,定義在A資源中;
{ ... before => Type['B'], ... }
② B require A: B依賴於A,定義在B資源中;
{ ... require => Type['A'], ... }
③ A -> B,B依賴於A
(2)注意:
① before、 require 和 -> 三者用其一即可
② 資源引用:Type['title']
類型的首字母必須大寫
(3)演示:創建一個用戶,需要依賴一個組
① 創建manifest
[root@along manifest]# vim user2.pp [root@along manifest]# cat user2.pp group{'redhat': ensure => present, # before => User['ilinux'], #方案1 } user{'ilinux': ensure => present, comment => "ilinux.io", groups => 'redhat', require => Group['redhat'], #方案2 } #Group['redhat'] -> User['ilinux'] #方案3
② 執行,先創建了組redhat,再創建了用戶ilinux
[root@along manifest]# puppet apply -v user2.pp Notice: Compiled catalog for along in environment production in 0.14 seconds Info: Applying configuration version '1550043297' Notice: /Stage[main]/Main/Group[redhat]/ensure: created Notice: /Stage[main]/Main/User[ilinux]/ensure: created Notice: Finished catalog run in 0.12 seconds
4.1.2 通知關系:通知相關的其它資源進行“刷新”操作
(1)格式:notify/subscribe
① notify:A notify B:B依賴於A,且A發生改變后會通知B;
{ ... notify => Type['B'], ... }
② subscribe:B subscribe A:B依賴於A,且B監控A資源的變化產生的事件;
{ ... subscribe => Type['A'], ... }
③ A ~ B ,B依賴於A縮寫版
(2)實例:下載redis 包,復制配置文件,啟動redis 服務
① 修改srv3.pp manifest 清單
[root@along manifest]# vim srv3.pp package{'redis': ensure => installed, } file{'/etc/redis.conf': ensure => file, source => '/root/manifest/files/redis.conf', owner => 'redis', group => 'root', mode => '0640', # notify => Service['redis'] } service{'redis': ensure => running, enable => false, hasrestart => true, # subscribe => File['/etc/redis.conf'] } Package['redis'] -> File['/etc/redis.conf'] ~> Service['redis']
② 執行
[root@along manifest]# puppet apply -v --noop srv3.pp [root@along manifest]# puppet apply -v srv3.pp Notice: Compiled catalog for along in environment production in 0.42 seconds Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false. (at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default') Info: Applying configuration version '1550046675' Notice: /Stage[main]/Main/Package[redis]/ensure: created Info: FileBucket got a duplicate file {md5}d98629fded012cd2a25b9db0599a9251 Info: /Stage[main]/Main/File[/etc/redis.conf]: Filebucketed /etc/redis.conf to puppet with sum d98629fded012cd2a25b9db0599a9251 Notice: /Stage[main]/Main/File[/etc/redis.conf]/content: content changed '{md5}d98629fded012cd2a25b9db0599a9251' to '{md5}d3fc0c22e1a90f88a895242b2a251dad' Info: /Stage[main]/Main/File[/etc/redis.conf]: Scheduling refresh of Service[redis] Notice: /Stage[main]/Main/Service[redis]/ensure: ensure changed 'stopped' to 'running' Info: /Stage[main]/Main/Service[redis]: Unscheduling refresh on Service[redis] Notice: Finished catalog run in 5.25 seconds [root@along manifest]# ss -nutlp |grep redis tcp LISTEN 0 128 127.0.0.1:6300 *:* users:(("redis-server",pid=12492,fd=4))
③ 修改 /root/manifest/files/redis.conf 把端口改為6000
[root@along manifest]# vim files/redis.conf port 6000 [root@along manifest]# puppet apply -v srv3.pp 再執行,因為文件發生了修改,觸發了重啟服務,端口也確實改為了6000 Notice: Compiled catalog for along in environment production in 0.44 seconds Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false. (at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default') Info: Applying configuration version '1550046726' Info: /Stage[main]/Main/File[/etc/redis.conf]: Filebucketed /etc/redis.conf to puppet with sum d3fc0c22e1a90f88a895242b2a251dad Notice: /Stage[main]/Main/File[/etc/redis.conf]/content: content changed '{md5}d3fc0c22e1a90f88a895242b2a251dad' to '{md5}46e070a908eb1aca5c908e62dd4296b9' Info: /Stage[main]/Main/File[/etc/redis.conf]: Scheduling refresh of Service[redis] Notice: /Stage[main]/Main/Service[redis]: Triggered 'refresh' from 1 events Notice: Finished catalog run in 0.23 seconds [root@along manifest]# ss -nutlp |grep redis tcp LISTEN 0 128 127.0.0.1:6000 *:* users:(("redis-server",pid=12785,fd=4))
4.2 tag 標簽
如同 anssible 一樣,puppet 也可以定義“標簽”——tag,打了標簽以后,我們在運行資源的時候就可以只運行某個打過標簽的部分,而非全部。這樣就更方便於我們的操作。
一個資源中,可以有一個tag也可以有多個。
(1)格式:
資源定義:
type{'title': ... tag => 'TAG1', } type{'title': ... tag => ['TAG1','TAG2',...], }
手動調用:
puppet apply --tags TAG1,TAG2,... FILE.PP
(2)實例:
① 創建manifest
[root@along manifest]# vim srv3.pp package{'redis': ensure => installed, } file{'/etc/redis.conf': ensure => file, source => '/root/manifests/files/redis.conf', owner => 'redis', group => 'root', mode => '0640', tag => 'conf' } service{'redis': ensure => running, enable => false, hasrestart => true } Package['redis'] -> File['/etc/redis.conf'] ~> Service['redis']
② 執行
---先修改files配置文件端口為8888 [root@along manifest]# vim files/redis.conf port 8888 ---再執行 [root@along manifest]# puppet apply -v --tags conf srv3.pp Notice: Compiled catalog for along in environment production in 0.44 seconds Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false. (at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default') Info: Applying configuration version '1550113147' Info: /Stage[main]/Main/File[/etc/redis.conf]: Filebucketed /etc/redis.conf to puppet with sum fe60391ea96c958fe489f86002679ec3 Notice: /Stage[main]/Main/File[/etc/redis.conf]/content: content changed '{md5}fe60391ea96c958fe489f86002679ec3' to '{md5}cb214aa5ead0d70454d957ca9125ad01' Info: /Stage[main]/Main/File[/etc/redis.conf]: Scheduling refresh of Service[redis] Notice: /Stage[main]/Main/Service[redis]: Triggered 'refresh' from 1 events Notice: Finished catalog run in 0.17 seconds [root@along manifest]# grep "port 8888" /etc/redis.conf port 8888
5、puppet 變量
puppet 變量以“$”開頭,賦值操作符為“=”,語法為$variable_name=value。
(1)數據類型:
- 字符型:引號可有可無;但單引號為強引用,雙引號為弱引用;支持轉義符;
- 數值型:默認均識別為字符串,僅在數值上下文才以數值對待;
- 數組:[]中以逗號分隔元素列表;
- 布爾型值:true, false;不能加引號;
- hash:{}中以逗號分隔k/v數據列表; 鍵為字符型,值為任意puppet支持的類型;{ ‘mon’ => ‘Monday’, ‘tue’ => ‘Tuesday’, };
- undef:從未被聲明的變量的值類型;
(2)正則表達式:
(?<ENABLED OPTION>:<PATTERN>) (?-<DISABLED OPTION>:<PATTERN>) OPTIONS: i:忽略字符大小寫; m:把.當換行符; x:忽略<PATTERN>中的空白字符;
注意:不能賦值給變量,僅能用在接受=~或!~操作符的位置;
(3)puppet的變量種類
puppet 種類有三種,為facts,內建變量和用戶自定義變量。
- facts:
- 由facter提供;top scope;
- 內建變量:
- master端變量:$servername, $serverip, $serverversion
- agent端變量:$clientcert, $clientversion, $environment
- parser變量:$module_name
- 用戶自定義變量
(4)變量的作用域
- 不同的變量也有其不同的作用域。我們稱之為Scope。
- 作用域有三種,top scope,node scope,class scope。
- 其生效范圍排序為:top scope > node scope > class scope
其優先級排序為:top scope < node scope < class scope