用 Puppet 搭建易管理的伺服器基礎架構(4)

Wing發表於2015-08-12

在 《用 Puppet 搭建易管理的伺服器基礎架構(3)》中,我們建立了第一個可重用的、真實的Puppet模組:apache2。在第四部分以及之後的章節中,我們會停止使用示例,轉而開始構建一個具有完整特性基礎架構,包括使用者和許可權管理、Nagios監控、檔案伺服器、負載均衡、web伺服器、資料庫、VPN以及開發系統等等。

通過Puppet管理使用者和組賬號

在我工作的公司,我會在使用Puppet來管理我以及和我一起在Linux機器上工作的同事的Unix使用者賬號。由於只有幾個人需要使用shell或者ssh的方式來訪問系統,因此這種方式可以很好得工作。萬一你需要支援大量的使用者,每個使用者都在機器上有他/她自己的賬號,那麼一個類似LDAP的解決方案可能更加合適。

但如果你像我一樣,只有少數的軟體開發人員和系統管理員需要訪問系統,並且一個集中式的目錄服務會過於複雜,那麼通過Puppet來管理這些使用者賬號就非常簡單可行。

對於通過Puppet進行管理的每一臺機器上的清單來說,使用者和使用者組管理所使用的清單是一個很典型的示例。這種方式下每個使用者都可以預期他/她會在每一臺機器上都有自己可用的賬號(當然在每個系統裡面可能會有不同的許可權)。你沒有必要在多個使用者之間分享root或者其他任何Unix賬號——sudo會去為每個賬號分配合適的許可權。

使用集中式的配置管理會在這裡顯示它的威力:我們無論何時向基礎設施中新增一個新機器,每個使用者都可以預期他/她在新機器中的賬號已經建立,包括一些個人配置,諸如Bash設定等等。同樣,SSH金鑰的管理也會從一件麻煩事變得小菜一碟。

在你的基礎設施中,為使用者ID和使用者組ID定義一個簡單但嚴格的規則集,是很有意義的。

在我的示例中,規則集看起來就像這樣:

  • 內部系統管理員:UID/GID在1000到1999之間
  • 外部系統管理員:UID/GID在2000到2999之間
  • SFTP賬號:UID/GID在3000到3999之間

在我們的Ubuntu系統中,Ubuntu在安裝過程中會建立使用者ubuntu,它已經使用了UID/GID 1000,但如我們在後面所見,我們總可以通過Puppet來管理它。

如我之前所說,我假設你有一個基礎設施,只有很少的使用者會需要Unix賬號來訪問你的機器。在這種情況下,為每個使用者建立一個Puppet模組是有意義的(和將所有使用者清單放到一個模組相比)。通過這種方式,你可以建立簡單或者複雜的賬號模組,這些模組可以很好的共存,而不會最終變成一個混亂的模組。並且,你還可以在必要的時候在節點上“混合”不同的賬號。例如Bob和Mary都需要訪問你的web伺服器,但只有Mary需要訪問資料庫,那麼我們可以通過簡單的將節點對映到模組的方式,來實現這一特性。如果你有一個包含10個使用者的使用者組,它需要訪問所有的機器,我們不需要將每個賬號對映到每個節點上,而只需要將這10個使用者模組放到一個類中即可,我們會在後面對此進行詳細說明。

第一個使用者模組

那麼,這在實際中看起來是什麼樣子呢?讓我們針對已經存在的ubuntu賬號,建立第一個使用者模組。為了讓模組容易被識別,我們應該在所有的使用者模組的名字新增“user-”字首——因此,我們需要為模組建立如下所示的目錄結構:

使用者賬號和它所在的使用者組可以通過兩個專門的塊進行維護:user和group。我們可以像這樣使用它們:

/etc/puppet/modules/user-ubuntu/manifests/init.pp on puppetserver

如你所見,這基本上反應了使用者的建立過程,就好像它已經在系統中存在一樣。請注意密碼雜湊碼是放在單引號裡面,而不是像其它引數那樣放在雙引號裡面——這是因為對於Puppet來說,雙引號中的$符號有特殊的含義。

像以前一樣,為了應用這個新的清單(確切得說,是我們建立的新模組),我們需要在節點中宣告這個新模組:

/etc/puppet/manifests/site.pp on puppetserver

我們從輸出可以看出,這並沒有改變任何事情(好吧,在你看來,這可能不是真的——密碼可能已經生成了不同的雜湊碼,而且它會更新——儘管如此,最終你還是會有一個名為ubuntu的使用者,它的密碼也是ubuntu)。

使用Puppet管理SSH金鑰

對於一個非常初級的使用者管理來說,user塊可以很好的工作,但我們肯定想要更多。Puppet可以用來管理SSH金鑰,從而真正消除大量的“管理痛點”。讓我在puppetserver系統上為root使用者建立一個新的私有/公有SSH金鑰對,然後將公有金鑰新增到puppetclient系統的ubuntu使用者的authorized_keys 檔案中。

為此,我們首先生成一個新的金鑰對,並將公有金鑰輸出到控制檯上:

On the puppetserver VM

(當然,在生成你自己系統的金鑰時,最終你會得到一個不同的金鑰對)。

Puppet還有一些程式碼用來管理使用者的已經授權的SSH金鑰,我們按照如下方式使用,來對新生成的金鑰進行授權:

/etc/puppet/modules/user-ubuntu/manifests/init.pp on puppetserver

正如我們期望的那樣,這會在puppetclient系統上為ubuntu使用者生成如下的authorized_keys檔案:

/home/ubuntu/.ssh/authorized_keys on puppetclient

使用巨集來避免重複

現在,雖然所有的一切都非常好,但如果檢視最終的清單檔案,我們會發現大量的重複資訊:

/etc/puppet/modules/user-ubuntu/manifests/init.pp on puppetserver

在建立使用者時,真正需要的資訊包括使用者名稱、UID、密碼雜湊碼、使用者組以及SSH金鑰。但是在我們的清單中,我們需要提供使用者名稱6次、UID 3次。現在假設一下你要通過這種方式管理20個使用者。幸運的是,我們有更好的解決方案。

Puppet允許我們定義自己的引數化巨集(被稱為defines),它可以讓我們通過提供不同值的方式來多次重用清單檔案,而無需一遍又一遍的重複寫出整個清單檔案。

我們首先來建立一個新模組來儲存我們的巨集:

/etc/puppet/modules/macro-useradd/manifests/init.pp on puppetserver

上述清單程式碼中,除了“$username=$title”這一行外,其他內容可能都是自解釋的。在Puppet中的每一個塊總會有一個標題——它是一個跟在大括號後面的一個字串,並在結束後會有一個冒號:

我們用標題來唯一標識一個塊語句的。對於一個給定的節點,你不可以有多個指定型別的塊帶有相同的標題——也就是說,你不可以為/foo/bar檔案宣告兩個file塊。並且,正如你在這些示例中所看到的的那樣,當塊被執行時,標題經常被用作執行時所需要的一個值——例如,在file塊中,標題被設定成塊應該處理的檔案的路徑。

我們在自己的巨集中也進行同樣的處理:對於傳入define的標題,我們期望它是一個Unix使用者名稱,並且在我們的巨集的塊語句中,也將其作為對應的使用者名稱進行使用。

請注意在我們的巨集中,在處理引數時是如何使用引號的:對於數字型別的值,例如uid和gid,以及陣列型別的值,例如groups,不需要引號,但對於字串型別的值,例如comment和key,是需要引號的。我們在上面提過密碼雜湊碼由於包含了$字元,因此需要將其放在單引號中,來防止對引數開頭的$進行解析。我們稍後會看到,當呼叫巨集的時候,情況依然如此。在巨集中,我們需要再次使用雙引號——這會導致$password引數會被解析,但引數中的內容(包含$字元的密碼雜湊碼)就不會再被解析了。

既然我們已經定義了巨集,接下來我們需要重寫user-ubuntu清單,並在清單內使用巨集:

/etc/puppet/modules/user-ubuntu/manifests/init.pp on puppetserver

我們需要再次執行sudo puppet agent –verbose –no-daemonize –onetime,但在目標機器上不會有任何變化,這是因為我們僅僅重構了清單,並沒有改變它的邏輯。

增加更多使用者

我們的重構生成了一個非常簡潔的user-ubuntu清單,如果使用巨集,那麼新增大量使用者就會變得非常直接。在下面的示例中,我們會新增兩個使用者:Mary和Bob。在這裡我會直接重用ubuntu使用者的密碼雜湊碼和SSH金鑰:

/etc/puppet/modules/user-mary/manifests/init.pp on puppetserver

/etc/puppet/modules/user-bob/manifests/init.pp on puppetserver

管理使用者許可權

Puppet不僅能處理使用者賬戶,而且還能處理賬號的超級使用者許可權,讓我們使用上面建立的兩個賬號來演示這一點。目標是能夠集中定義哪個使用者在哪臺機器上有哪些許可權。

正如你在使用者清單中所見,Mary是sudo使用者組中的成員,但Bob並不是。這已經表明Mary有能力以超級使用者的許可權在機器上執行任何一個命令。然而,我們並不像給Bob超級使用者許可權——我們只是想將他的超級使用者許可權限制在puppetclient虛擬機器系統上,在其它機器上,只需要為其設定普通使用者許可權。單獨的組關係並不能解決這個問題——為此,我們需要一個模組來處理所有機器上的sudoers檔案。

首先,我們建立這個模組所需的目錄結構:

On the puppetserver VM

然後,我們為模組建立清單檔案:

/etc/puppet/modules/sudo/manifests/init.pp on puppetserver

我們需要將清單所管理的檔案/etc/sudoers新增到模組的file資料夾下:

/etc/puppet/modules/sudo/files/etc/sudoers on puppetserver

在這裡,我們的想法是在我們的基礎設施的所有機器上只保留一份sudoers檔案。這樣我們可以通過集中的方式進行許可權管理,即使每臺機器都使用它本地的/etc/sudoers副本來檢查使用者許可權。

在我們部署這些改動之前,我們需要將新的清單檔案對映到節點上。我們會把所有的user模組和sudo模組放到一個新的類中,這樣一旦我們向Puppet基礎設施中新增更多的節點時,可以避免一些重複工作:

/etc/puppet/manifests/site.pp on puppetserver

現在,我們終於可以應用這些改變:

On the puppetclient VM

總結

在這一部分中,我們演示瞭如何在不使用集中式目錄服務的前提下,通過Puppet來部署一個集中式的使用者和許可權管理解決方案。我們還學習瞭如果使用巨集來簡化那些複雜的、需要被使用多次的Puppet模組。

在接下來的第五部分中,我們會去檢視Puppet如何整合Nagios,並演示一個通過Puppet構建的可管理的伺服器基礎設施如何在不增加額外管理負擔的情況下,對伺服器進行監控。

(伯樂線上注:本系列的第四篇,原作者完成於2014年3月,雖然說了會有第五部分,不過目前還沒有在他部落格看到有。)

打賞支援我翻譯更多好文章,謝謝!

打賞譯者

打賞支援我翻譯更多好文章,謝謝!

任選一種支付方式

用 Puppet 搭建易管理的伺服器基礎架構(4) 用 Puppet 搭建易管理的伺服器基礎架構(4)

相關文章