2012年11月10日星期六

自動化部署本機網絡測試環境

雖然我並非一位專職的網絡應用開發者,間中都要寫一點網絡應用,又或者會動手試檢不同技術的利與弊,基於很討厭在自己的Ubuntu做代碼安裝以及改動太多設定,所以通常都會在VM裹進行。

完成後都會寫一篇筆記,經驗告訢我,日後再依這篇筆記執行的成功率遠低於50%,可能有遺漏,可能軟件有修改,又或者要求根本不同了,幸好這總比重新RTFM快許多。

為了減省筆記上的錯漏,一直都想把文字script化,概可說明步驟,也可以日後依樣執行。可是若沒有好的framework配合,弄出來的script只會更加難懂…… 其實我想要的script跟自動化部署(auto deployment)系統很相似,大可直接拿來用。

花了點時間,利用ubuntu-vm-builder,fabric及puppet總算做到了這個要求。現在可以把建立測試環境及測試的程式全都放在VCS裹管理,只需要把幾個指令就可以把程式抄去VM後執行。



例子 - 建立一台VM執行Nodeload(node.js)的測試程式

指令
  1. fab create #建立VM
  2. fab setup #設定VM,例如下載node.js及其node.js模組
  3. fab deploy #把測試程式拷到VM執行
  4. fab view #開啟Browser查看結果


準備工作

首先你要有一台Ubuntu,然後安裝以下軟件
sudo apt-get fabric ubuntu-vm-builder #你不一定需要裝Puppet,也不需要安裝Node.js,請看下文。 
如果沒有建立自己的ssh key,請先用ssh-keygen建立。

測試的環境是12.04,12.10相信也沒有問題,若然是11.10則要調整建立VM的參數,基於12.04是LTS版本,所以建議使用。

在接下來的例子中,會利用Nodeload建立一台Node.js的測試伺服器,即使上面的指令沒有安裝node.js也不用補回,因為將會執行的是VM而不是host/桌面機。


Fabric及Puppet的簡介

這二個軟件都可以歸類為自動化部署系統,例如可以把設定及執行檔安裝至複數的伺服器上,但二者之間的運作原理卻非常之不同。

Puppet採用Agent/Master架構,複數Agent自動向Master取得新的設定,這是一種叫做pull機制。

而Fabric則是採取相反的Push機制,由本機把設定通過ssh推至複數的伺服器上。

單純就自動化部署系統這一範疇來說,Puppet發展迅速,不過Pull的機制對開發人員來說卻有所不便,因為要先設定多一台Master變相令建立測試環境的過程變得複雜,Push的形式比較簡單,所以我採用了混合的做法:

使用Fabric把設定檔推至VM,再執行Puppet把設定更新。


建立VM

在這個例子中我不打算使用VMWare或者VirtualBox這類方案,而是使用Kernel-based Virtual Machine(KVM)配合QEMU+libvirt,介面上當然比不過前二者,不過勝在可以透過ubuntu-vm-builder輕易地建立可執行的Ubuntu影像,並自動執行初始化設定。

第一步是建立fabfile.py,內容如下:

from __future__ import with_statement
from fabric.api import local, settings, abort, run, cd , put
from fabric.contrib.console import confirm
from fabric.api import env
from fabric.context_managers import prefix
 
machine = "nodejs" # Name of the testing machine
 
def create():
    # Create a testing machine
   
    # Remarks: You should not permit root logins via SSH in a networking
    # environment, because this is a big and unnecessary security risk.
    #
    # It is enabled here for simplify the tasks required to build
    # a testing machine. Never do it in production and even on
    # a machine within your office network.
   
    dist = "precise"
    mem = 128
   
    packages = ["openssh-server" , "puppet" , "nodejs" ,"npm"]
    package = " ".join([ "--addpkg %s"  % x for x in packages]);
   
    options = ["--libvirt qemu:///system", # Add to libvirt
                "--lang=C",  
                "--ssh-key ~/.ssh/id_dsa.pub",
                "-d /var/lib/libvirt/images/%s" % machine,
                "--hostname %s" % machine,
                "--mem=%s" % mem,
                "--name=%s" % machine ]
    option = " ".join(options);
 
    command = "sudo ubuntu-vm-builder kvm %s qemu:///system %s %s" % (dist , package,option)
    local(command)

上例中有一個叫做create()的函數,可以通過指令`fab create`執行,

完成後可以用指令`sudo virsh start nodejs`來起動VM。

註1:我把自己的SSH key放入VM的root中,使得可以經ssh登入root而不需要密碼,對於測試環境來說是相當之方便,但千萬不能在網絡環境中卻是採用,那是非常之壞的習慣。
註2:Ubuntu-vm-builder大概已經不會再有大的發展,之後的開發核心看來是lxc/juju,之所以沒有採用後者是因為還未學會使用。另外你喜歡使用VirtualBox的話,則可以選擇Vagrant。


執行Puppet

開動VM後下一步是進行系統設定,這部驟由Puppet進行。在VCS中有二個.pp檔,那是Puppet的設定檔,用以宣告資源,當中記錄了要安裝的軟件,但因為要使用到apt、gems、npm三種不同的套件管理程式,所以並不能用幾行描述完成。

像Fabric般使用script方式來進行設定是相當之直觀的方法,Puppet的描述語言則相對迂迴,但以configration management的角度看,追蹤修改比較容易。另外統一的資源/模型描述方法,使不同軟件之間的設定的差異化減少,有便於管理。(詳情)

要進行這部驟的指令是`fab setup`,代碼:

def setup():
    # Setup the testing machine using puppet
    put("setup*.pp" ,"/tmp")
    run("puppet apply /tmp/setup-phase1.pp")
    run("puppet apply /tmp/setup-phase2.pp")


Fabric在這裏的作用只是把.pp檔拷到VM後執行`puppet apply`而已。


進行測試

最後一步是把測試程式放入VM執行,指令是`fab deploy`,然後在另一個Terminal中輸入`fab view`就會自動打開browser查看實際結果.


$ fab deploy
[192.168.122.118] Executing task 'deploy'
[192.168.122.118] put: ../src/nodeload-server.js -> /tmp/nodeload-server.js
[192.168.122.118] run: killall -9 node;echo
[192.168.122.118] out: node: no process found


[192.168.122.118] run: node /tmp/nodeload-server.js 
[192.168.122.118] out: Started test server.
[192.168.122.118] out: Started HTTP server on localhost:8000.


執行結果



總結

如果只為一次測試寫上以上的程式,老實說我也覺得小題大造,但如果考慮到日後可以重覆使用,這一切就會變得物超所值。這刻只有建立node.js的.pp,日後可以加入MongoDB、Redis、MySQL,Nginx、Memcache、ZooKeeper..... 你想怎樣配搭都可以,當你不需要時只需把VM關掉,會佔用的僅是硬碟空間。

要是對這種測試方法有興趣,又想尋找更多的use-case,可以參考 Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation


沒有留言:

Creative Commons License
本網誌Ben Lau製作,以共享創意署名-非商業性-相同方式共享 3.0 香港 授權條款釋出。