完成後都會寫一篇筆記,經驗告訢我,日後再依這篇筆記執行的成功率遠低於50%,可能有遺漏,可能軟件有修改,又或者要求根本不同了,幸好這總比重新RTFM快許多。
為了減省筆記上的錯漏,一直都想把文字script化,概可說明步驟,也可以日後依樣執行。可是若沒有好的framework配合,弄出來的script只會更加難懂…… 其實我想要的script跟自動化部署(auto deployment)系統很相似,大可直接拿來用。
花了點時間,利用ubuntu-vm-builder,fabric及puppet總算做到了這個要求。現在可以把建立測試環境及測試的程式全都放在VCS裹管理,只需要把幾個指令就可以把程式抄去VM後執行。
例子 - 建立一台VM執行Nodeload(node.js)的測試程式
指令
- fab create #建立VM
- fab setup #設定VM,例如下載node.js及其node.js模組
- fab deploy #把測試程式拷到VM執行
- 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
沒有留言:
發佈留言