過去這段時間 , 使用 Vagrant/Puppet 來實驗不同的 DevOps 相關技術 , 也著實有不少收獲 。 也許太過習慣 Vagrant 帶來的便利 , 山姆鍋都快把使用 Puppet 來配置系統視為理所當然 。 但所謂 「 魔鬼藏在細節裡 」, 不同的雲端虛擬機供應商可提供的系統映像 (VM image) 以及其它差異 , 導致從虛擬機建立到 Puppet( 或其它系統配置工具 ) 能夠接手中間出現了一些阻礙 !

使用 Vagrant/Puppet 以及雲端虛擬機的部署方式可以簡化成下列步驟 :

  1. 決定虛擬機使用的系統映像 (image)。
  2. 建立 (create) 虛擬機實例 (instance)。
  3. 根據此虛擬機的角色 (roles) 與責任 (responsibilities) 來配置系統 。

理想上 , 同一個系統的服務器使用的系統映像應該是同一個 。 系統根據當下需要的功能來配置新建立的虛擬機 , 這樣可以避免因為映像包含應用套件而導致組合爆炸的問題 。 當然系統映像還是會更換 , 但是頻率較低且間隔也較長 。 Packer 這類工具的出現 , 雖然簡化建構虛擬映像的負擔 , 但畢竟雲端虛擬機部署映像的方式每家供應商都不太相同 , 山姆鍋不傾向使用這種方式 。

問題

要知道如何解決之前 , 需要先知道雲端虛擬機供應商之間的一些差異造成的問題 :

  1. 不是所有供應商都允許客戶使用客制的系統映像 。
  2. 提供的系統映像未必有預先安裝像 Puppet/Chef 這類系統配置工具 。
  3. 就算有預裝系統配置工具 , 可能版本太舊或是與公司使用的不同 。
  4. 要如何讓剛啓動的虛擬機知道要它該負責的角色 ?

首先 , 也許您會問 :「 為什麼不使用同一家符合要求的供應商就好 ?」 這樣 , 的確是可以省掉很多麻煩 , 但這樣做不好的基本原因就在供應商套牢 (Vedor Lock-in) 的問題 。 為了選擇的彈性 , 山姆鍋通常不喜歡只有一家公司的產品或服務可以選擇 。 既然決定採用可以適用最多供應商的做法 , 我們就來看看上述這些問題該如何處理 。

關於第 1 點 , 在不使用客制的系統映像的條件下 , 我們只好選擇通用的作業系統來因應 。 「 影化身科技 」 採用 Ubuntu 12.04 LTS 64-bit 系統 , 應該所有供應商都有對應的映像可以選擇 , 所以 , 問題不大 。 由於一些通用的系統套件不能預先安裝 , 不能使用客制映像會讓系統配置需要花費較長時間 。

要處理第 2 跟第 3 點 , 雖然有點違反直覺 , 但還不至於難處理 。 利用 Shell 腳本來設定系統以及安裝 Puppet 後 , 讓 Puppet 接手後續配置的工作 。 幸好 Vagrant 支援使用 Shell 腳本來做系統配置的工作 。 雖然 cloud-init 也可以用來做系統配置的初始化工作 , 但不是所有系統映像都有內建支援它 , 所以 , 使用 Shell 腳本還是比較實際 。 因為不想針對不同的虛擬機使用不同的 Shell 腳本 , 我們還需要解決第 4 點的問題 。

有了 shell 腳本打先鋒建立一個可以用 Puppet 配置的虛擬機之後 , 要如何讓 Puppet 知道此虛擬機需要扮演的角色 ? Amazon 針對這點提供所謂 User-data 的機制 。User-data 是在虛擬機建立實例時指定的參數 , 在虛擬機執行時內部程式可以讀取這些參數 。 借由 User-data, 我們可以讓 Puppet 知道虛擬機該以何種角色配置 。 因為 ,Puppet 已經有我們提供關於不同角色的配置方法 , 所以 , 需要傳遞的 User-data 量並不多 , 基本上 , 只是虛擬機所屬的環境 ( 測試 、UAT 等等 ) 以及它要負責的角色 (web, db, etc.)。 看到這裡 , 您可能會以為問題就此解決了 ! 很不幸的是 , 同樣不是所有供應商都支援 User-data 或類似的機制 。

方案

假如您同山姆鍋一樣使用 Vagrant 來作為虛擬機整備工作 , 解決方法在上面有稍微提到 : 使用 Vagrant 的 Shell 腳本來配置 。Vagrant 提供的 Shell 腳本配置方法同時允許我們傳遞額外的參數 , 如此就可以有一個跨雲端平台 ( 供應商 ) 的方法可以讓 Puppet 知道虛擬機要扮演的角色了 !

由於只需要 SSH 服務跟 Python, 其實 Ansible 應該也可以把虛擬機整備成適合 Puppet 管理的狀態 。 不過 ,Ansible 本身算是完整的配置管理方案 , 學習上門檻比使用 shell 高些 , 況且跟 Puppet 一起使用 , 之間重疊的功能太多 。

結語

雖然很希望只使用單一個系統映像 , 建立後直接使用 Puppet 或是其它系統配置工具來做完系統整備與配置工作 。 但是 , 畢竟現實跟理想總會有些差距 , 面對現實問題 , 我們也只能想辦法解決 。