我通過伯樂線上翻譯了一個Puppet簡明教程,一共分為四部分,這是第二部分。
原文地址:http://blog.jobbole.com/87680/
本文由 伯樂線上 - Wing 翻譯,黃利民 校稿。未經許可,禁止轉載!
英文出處:Manue Kiessling。歡迎加入翻譯組。
關於
在第一部分中,我們已經建立了兩個Linux系統虛擬機器:puppetserver 和 puppetclient。我們已經實現了一個重要的里程碑:在虛擬機器上分別安裝了Puppet伺服器和Puppet客戶端軟體,並且在Puppet伺服器端對Puppet客戶端進行了認證。接下來我們要在此基礎上,開始通過在puppetserver虛擬機器上的Puppet伺服器,來配置puppetclient虛擬機器系統。
你好,Puppet
我們以一個非常基本的示例開始。在這個示例中,我們為puppetclient虛擬機器建立一個非常簡單的配置:在puppetclient虛擬機器系統的/home/ubuntu目錄下建立一個名為helloworld.txt檔案,檔案的內容是”Hello World!”。
Puppet自帶一個功能強大的宣告式配置語言。我們使用這種語言來編寫的內容被稱為清單(manifest)。Puppet清單是一個檔案,它描述了目標系統中的某些方面應該是什麼樣的。在這個系列教程中,我們會編寫很多不同的清單:其中一些會在目標系統上建立一些檔案;一些會建立使用者賬戶;一些會安裝軟體包。
清單會被應用到目標系統上。對Puppet來說,目標系統被稱為節點(node)。我們的puppetclient虛擬機器系統就是這樣一個節點。我們已經為它做了Puppet伺服器認證,這樣可以保證Puppet伺服器來管理這個節點。但我們的伺服器還沒有任何資訊,可以用來管理這個節點。我們可以通過編寫一個清單並將其放在節點上來改變它。
為此,我們會建立一個非常簡單的清單定義,這個定義會被放在puppetserver虛擬機器系統的主清單檔案中,檔案的路徑是/etc/puppet/manifests/site.pp:
/etc/puppet/manifests/site.pp on puppetserver
1
2
3
4
5
6
7
8
9
10
|
node "puppetclient" { file { "/root/helloworld.txt" : ensure => file, owner => "root" , group => "root" , mode => 0644 } } |
我們稍後會看到,清單可以通過模組化的方式放到任意數目的不同檔案中(這樣可以幫助我們針對大型複雜的站點建立清單結構)。但是一切都還是從site.pp開始。
我們來仔細分析一下這個最簡化的清單,它包含兩部分:一個包含file定義的node,因為file部分包含在node部分中,這樣file部分的定義產生的結果會應用到名為puppetclient的節點上。
通過在puppetclient虛擬機器系統上執行Puppet代理,我們可以很容易理解上面描述的內容。
On the puppetclient VM
1
2
3
4
|
~ # sudo puppet agent --verbose --no-daemonize --onetime info: Caching catalog for puppetclientinfo: Applying configuration version '1395862307' notice: /Stage [main] //Node [puppetclient] /File [ /home/ubuntu/helloworld .txt] /ensure : created notice: Finished catalog run in 0.03 seconds |
或許這看上去沒有什麼大驚小怪:puppetclient虛擬機器上的Puppet代理聯絡到puppetserver虛擬機器上的Puppet master。然後它接收目錄,這個目標就是在master上定義的所有和這個指定客戶端有關的清單。如果你感興趣的話,這個目錄被存在一個yaml結構中,它儲存在 /var/lib/puppet/client_yaml/catalog/puppetclient.yaml 中,這不僅僅是複製了我們的.pp清單,而是通過對清單進行解析,生成的一個關於目標配置資訊的編譯版本。
接下來,Puppet代理開始採取行動——當且僅當滿足以下條件才會採取行動:Puppet代理會比較清單中期望的狀況和目標節點上清單的狀況,如果其中有一些不同(如果目標節點上找到的狀況並沒有同步到期望達到的狀況)——那麼代理就會做任何必需的操作來移除這些區別,來實現目標狀況。
在我們這個特定的示例中,代理知道在目標節點的/home/ubuntu目錄下,應該有一個名為helloworld.txt的檔案,這個檔案的所有者和所在組是ubuntu,使用者對該檔案的訪問許可權是0644。然而,當檢查本地系統時,發現並沒有發現這個檔案。代理會採取行動,來建立這個期待中的檔案。
我們可以通過再次執行代理來驗證這個行為:
On the puppetclient VM
1
2
3
4
|
~ # sudo puppet agent --verbose --no-daemonize --onetime info: Caching catalog for puppetclient info: Applying configuration version '1395862542' notice: Finished catalog run in 0.03 seconds |
如我們所見,這次代理並沒有做任何事情,這是因為目標節點的狀況已經滿足了。那如果我們修改目標節點上的狀況會怎麼樣呢?讓我們來修改這個檔案的訪問模式:
在 puppetclient VM 上
~# chmod 0640 /home/ubuntu/helloworld.txt
然後再次執行代理:
在 puppetclient VM 上
1
2
3
4
5
6
|
~# sudo puppet agent --verbose --no-daemonize --onetime info: Caching catalog for puppetclient info: Applying configuration version '1395862307' notice: /Stage[main] //Node[puppetclient]/File[/home/ubuntu/helloworld.txt]/ensure: created notice: Finished catalog run in 0.03 seconds |
代理注意到了區別,然後通過修改檔案訪問模式來移除了這個區別。
如果我們修改了檔案的內容,會發生什麼呢?
在 puppetclient VM 上
~# echo "This is a test" > /home/ubuntu/helloworld.txt
…這時執行代理?
在 puppetclient VM 上
1
2
3
4
5
|
~ # sudo puppet agent --verbose --no-daemonize --onetime info: Caching catalog for puppetclient info: Applying configuration version '1395862542' notice: Finished catalog run in 0.03 seconds |
沒有發生任何事情。為什麼?因為在清單中,我們沒有對檔案內容進行任何描述。我們所做的是讓Puppet來保證這個指定名字的檔案是存在的,並且這個檔案的一些後設資料(擁有者、使用者組、訪問模式)應該有指定設定。Puppet只會關心那些我們讓它去關心的事情。
我們在之前示例中看到的行為,正好表明了Puppet哲學的核心。在我們的清單中,我們不告訴Puppet做什麼,我們也不告訴它怎麼去做,我們只告訴Puppet最終的結果應該是什麼樣子。
這種哲學帶來了巨大的能量,因為它對配置系統所需要的繁重的工作進行了抽象。它撫平了不同的作業系統帶來的差別。考慮下面一個場景,你有一個由不同的Linux系統構成的網路:有些執行Red Hat Linux,有些在執行Ubuntu Linux。我們進一步假設你希望在所有的系統上安裝htop包。如果我們需要告訴Puppet做什麼和怎麼做,那麼我們不得不編寫一個清單,它在Ubuntu上使用apt-get,在Red Hat上使用yum。相反,我們所需要放到清單中的內容如下所示:
1
2
3
|
package { "htop" : ensure => installed } |
目標節點中的puppet代理會去搞清楚如何做,才能實現清單中描述的目標場景。Red Hat系統中的代理會使用yum來安裝包,而Ubuntu系統中的代理則會使用apt-get。
我們在稍後會回來討論包安裝,讓我們繼續之前的檔案示例。通過Puppet來建立一個空檔案,通常都不是特別有用——當然我們更喜歡部署一些帶內容的檔案。Puppet可以很容易做到:我們可以將檔案放在puppetserver虛擬機器上,然後通過Puppet將其傳輸到puppetclient虛擬機器上。
首先,我們在puppetserver虛擬機器上建立原始檔:
在 puppetserver VM 上
1
2
3
|
~ # sudo -s ~ # mkdir /etc/puppet/files ~ # echo "Hello World." > /etc/puppet/files/helloworld.txt |
然後,我們需要允許Puppet客戶端來訪問這個檔案,為此,我們需要修改puppetserver虛擬機器上的/etc/puppet/fileserver.conf檔案,新增一個allow *語句:
/etc/puppet/fileserver.conf on puppetserver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# This file consists of arbitrarily named sections/modules # defining where files are served from and to whom # Define a section 'files' # Adapt the allow/deny settings to your needs. Order # for allow/deny does not matter, allow always takes precedence # over deny [files] path /etc/puppet/files allow * # allow *.example.com # deny *.evil.example.com # allow 192.168.0.0/24 [plugins] # allow *.example.com # deny *.evil.example.com # allow 192.168.0.0/24 |
現在我們可以修改/etc/puppet/manifest/site.pp清單檔案,擴充套件其中已有的file塊:
/etc/puppet/manifests/site.pp on puppetserver
1
2
3
4
5
6
7
8
9
10
11
|
node "puppetclient" { file { "/root/helloworld.txt" : ensure => file, owner => "root" , group => "root" , mode => 0644 , source => "puppet://puppetserver/files/helloworld.txt" } } |
讓我們再次執行客戶端系統上的代理:
在 puppetclient VM 上
1
2
3
4
5
6
7
8
|
~ # sudo puppet agent --verbose --no-daemonize --onetime info: Caching catalog for puppetclient info: Applying configuration version '1395878127' info: FileBucket adding {md5}ff22941336956098ae9a564289d1bf1b info: /Stage [main] //Node [puppetclient] /File [ /home/ubuntu/helloworld .txt]: Filebucketed /home/ubuntu/helloworld .txt to puppet with sum ff22941336956098ae9a564289d1bf1b notice: /Stage [main] //Node [puppetclient] /File [ /home/ubuntu/helloworld .txt] /content : content changed '{md5}ff22941336956098ae9a564289d1bf1b' to '{md5}770b95bb61d5b0406c135b6e42260580' notice: Finished catalog run in 0.09 seconds |
現在Puppet代理的確會關心檔案的內容,它會使用從puppetserver虛擬機器上得到的檔案,來覆蓋現有檔案。
在第三部分中,我們會看一個更復雜的清單,以及如何將清單組織成不同的模組。