開發環境的虛擬化


iThome 網站首載:開發環境的虛擬化

程式為什麼不會動?程式人告訴你的為什麼中,第一名始終是「在我的機器明明就可以動啊!」機器是指什麼呢?實體設備?作業系統?執行環境?開發環境?環境變數?外部資源?其實都有可能,問題看來似乎只有一個,想辦法讓每個開發者的環境都相同,實際上,卻有著各種不同的考量與作法。

傳統的開發環境建立

為了有一致的環境,有些傳統方式使用像是多重開機、還原卡甚至抽換硬碟(USB行動碟)等,每個人會擁有完全獨立的實體機器、相同的作業系統、應用程式設定等初始環境是這些方式的優點,因而至今仍特別容易出現在一些教育訓練場合,然而,這類方式需要實體機器、專人部署整個環境,如果弄髒了環境,無論是重灌(重新部署)或回復至還原點都很麻煩等缺點也是顯而易見,對於今日複雜的開發環境需求來說已不適用。

有些語言本身的開發工具箱提供了機制,可以達到一定程度的開發環境隔離,比方說,Python可以設定各種環境變數,建立各自獨立的程式庫相依環境,為了方便建立這類環境,也有Virtualenv這類工具可以使用,使用Pythonbrew則可以協助安裝多個Python版本並迅速切換;Java的話,JVM提供了Java專有的虛擬環境,一個啟動的JVM本身就是一個隔離環境,整合開發環境也可以提供不同的JDK版本或CLASSPATH配置。雖然這類語言提供一定程度的隔離機制,不過,實際上開發除了語言本身環境之外,還牽涉到不少外部資源管理問題,這方面語言開發工具箱本身就無法著墨了。

這個時代電腦的運算能力,其實往往超過使用者實際的需求,多數情況下,開發者需要的是獨立、隔離的運算資源,而不是實體機器。虛擬機器可以提供一個抽象層,讓客端作業系統以為自己擁有整台實體機器,開發者可以自行在各個虛擬機器中安裝、設定各自獨立的開發環境,也可在其中安裝完整的外部資源,另一開發者只要拿到映象檔,就可擁有相同環境,環境弄髒了只要重新設定原有的虛擬映像檔等是其優點,因而開發者對於使用VirtualBox、VMWare等虛擬機器軟體並不陌生。雲端運算概念下實際也提供虛擬機器服務,不過虛擬機器本身肥大,在虛擬機器中各自針對不同時期或不同需求,配置各自完整的開發環境是個很沉重的負擔。

這些傳統開發環境建立的方式,各有其優缺點,也有些相對較新的工具可以取而代之,在這之前,先觀察使用這些傳統開發環境建立的目的,可以知道,一致的開發環境需求其實主要有獨立性(隔離性)、易於組態、易於部署、可攜(Portable)、可版本控制、輕量等需求。

輕量級虛擬機工具Vagrant

對於致力於開發與營運(Development and Operations, DevOps)間溝通、協調整合的公司來說,其下的開發者對於Vagrant應不陌生,從Vagrant創建者Mitchell Hashimoto在〈The Hardest, Most Rewarding Job I've Ever Had〉這篇談到Vagrant誕生的故事,可以知道Vagrant的主要訴求,由於他當時受雇於一間使用Ruby的公司,每6到8周就可能產生新的專案,要為每個新專案設定新開發環境,而每個新環境與先前專案只有些微不同,使得Hashimoto逐漸對這個過程感到洩氣,為了維護一個舊專案,又得將環境回復至某個狀態更令人生氣,那簡直是一場惡夢。

就表面來看,Vagrant以VirtualBox為基礎(現在也支援VMWare),也是啟動了虛擬機器,開發者可以在其中安裝設定開發環境,如果沒有Box的概念,確實Vagrant跟虛擬機器軟體就沒什麼不同了,開發者可以將開發環境包裝為Box,放在官方或第三方Box伺服器供人下載,Box是虛擬機器映像檔基礎,你在虛擬機器中做的變更不會影響Box,可以獨立地讓虛擬機器關機、休眠或銷毀虛擬機器,可以為不同的開發環境需求包裝不同的Box,搭配一個文字檔案Vagrantfile管理使用的Box,以及配置虛擬機器的資源(記憶體、連接埠、IP等),常見到的做法是Vagrantfile所在目錄就是專案目錄,可以連同Vagrantfile一同做版本控制,讓專案與環境有著一致的版本控制記錄。

作為一名開發者,有時頭痛的並不是怎麼安裝開發工具箱、程式庫、整合開發環境,而是資料庫、Web伺服器等各種外部資源,畢竟不是每個開發者都能熟悉各種外部資源如何正確地安裝,由於Vagrant實際上啟動了虛擬機器,每個虛擬機器就是獨立的,實際上就可以管理這些外部資源,在ingramchen的〈導入Vagrant做開發配置〉中,就談到了為何Java生態圈不需要虛擬機器來做開發環境隔離,以及如何使用Vagrant與Ansible自動化工具來管理外部資源。

提供執行環境的Docker

在虛擬化方面,近來頻頻躍上新聞版本的就是Dockcer,2013年3月Docker初次釋出的15個月之後,2014年6月就釋出1.0版本,這期間吸引了眾多使用者的注意,Google也宣布擁抱Docker,發表容器(Container)管理工具Kubernetes,並宣布微軟、紅帽、IBM等廠商也將加入該專案,使得Docker從6月以來不斷成為鎂光燈追逐焦點。

虛擬機器透過抽象層而以為擁有整個實體機器,安裝了整個作業系統,因而運行時使用的是各個客端作業系統核心;Docker不是虛擬機器,它只提供應用程式執行時應有的相關資源,映像檔不需要包括整個作業系統,只需要包括小部份系統元件,不同的環境需求可以基於既有映像檔疊加,Docker從映像檔建立容器(應用程式所需環境),每個容器使用主作業系統的核心,因此,無論是映像檔或是容器,相較於虛擬機器來說,都極為輕量級。

容器技術上來說,就是一個行程(Process),容器的變更不影響映像檔,容器的狀態可以提交(Commit)成為映像檔,可以搭配Dockerfile自動建構與提交,映像檔可以公開在Docker hub供人下載,可以形成自給自足的資源,這使得Docker就像將應用程式必要的資源封裝為一個個軟體貨櫃,便於快速部署。

因此,就開發環境的需求來說,Docker與Vagrant在隔離性、易於組態與部署、可攜、版本控制等方面,功能上有些重疊,這使得兩者經常被視為競爭對象而加以討論,Vagrant普遍被談及的缺點是不夠輕量級,Docker經常被提及的問題是,lxc只能運行在Linux上,因此在Windows上還是得透過虛擬機器才能使用,像是boot2docker,或者是透過Vagrant來安裝Docker,在穩定與成熟度上,相對來說較新的Docker也是被檢討的重點。

重視自己的開發環境需求

對實際去思考過自身開發環境需求,以及Vagrant與Docker兩者差異性的人來說,有不少人其實也將Vagrant與Docker搭配在一起使用,不過,Vagrant與Docker在功能上有重疊是無庸置疑的,兩者間勢必存在競爭關係,就像stackoverflow上〈Should I use Vagrant or Docker.io for creating an isolated environment?〉的發問,分別引來了Vagrant與Docker創建者Solomon Hykes的回答,兩人的回答實際上仍存在針峰相對的味道。

無論原創建者的想法是如何,是存在競爭還是互補關係,使用者最終會決定生態圈,身為使用者應思考的重點並不在於最後選哪邊站,而在於是否有實際想過,面對現有開發環境的管理,有哪些實際需求,因而才能進一步且有依據地尋找與評估適用的工具,若真如此,就算最後只是選擇傳統的虛擬機器也不為過,怕的是只會一而再、再而三像在做手工藝般地與開發環境奮戰,然後持續地洩氣、沮喪而後對現狀呈現麻木狀態。