大綱 Infrusture as Code 挑戰賽 - Hashicorp 工具鏈全教學
Vagrant 主要是建立與管理 VM 的工具,主要希望在工作流程中提供一致的環境,例如說有新人加入開發,需要在本地端設定 Runtime 環境 / 資料庫等,這時候如果用 Vagrant 使用 $vagrant up
一鍵啟動所有需要的環境,就非常的方便,也可以避免「明明在我的電腦就沒問題」的尷尬
Vagrant 主要是 VM-based 的工具,預設使用 Virtualbox,也可以用 VMWare / AWS 等虛擬化平台
本次教學目標為部署一個 nodejs api server + mongodb
github repo 在此 vagrant-getting-started
Install
Terminology
在 Vagrant 有幾個名詞先介紹
provider
:
提供 Vagrant 虛擬化的環境,預設是 virtualbox,也可以是其他的第三方 providerbox
:
對比是 Docker 的 Image,也就是 Vagrant 虛擬化啟動的 Image,透過這個基礎再去客製化,以下用 ubuntu 示範provision
:
客製化環境的每一個步驟,可以用shell
執行 shell script、file
上傳檔案,或是搭配chef/ansible
等 provisioning 工具
Get Started!
首先建立一個檔案夾 vagrant-demo
,先拉下等等要用的 box,
|
|
可以在這邊找到你想要的 box,Discover Vagrant Boxes
接著建立 Vargrantfile
文件,裡頭寫入
|
|
首先看一下語法,Vagrant 設定檔是用 Ruby 語法,當然不會 Ruby 也可以使用,Vagrant.configure("2")
定義 Vagrant 的語法版本,接著 do |config| ... end
定義 vm 的設定,config 是我們在這個 block 中的 vm 名稱;config.vm.box
則是指定採用的 box,config.vm 底下有很多參數可以指定,請參考文件
接著執行
|
|
如果安裝正確,vagrant 會直接啟動新的 vm,如果直接開 virtuabox 會看到一個新的 vm instance$vagrant up
表示依序路徑讀取 Vagrantfile
(當前路徑 –沒有找到再往–> ../當前路徑 -> ….),並啟動新的 vm instance,啟動後會發現路徑下多了 ./.vagrant
的資料夾,這主要是記錄 vagrant 執行狀態
接著讓我們 ssh 進入 vm 看一下
|
|
ssh 用的 key 等等 vagrant 都處理好了,ssh 進入後,預設操作的 user 是 vagrant
,先看一下 /vagrant
|
|
你會意外發現 /vagrant 裡頭竟然有 Vagrantfile,主要是 vagrant 預設會把本地端 Vagrantfile 同在的資料夾一並同步到 vm 底下的 /vagrant 當中
依照共享的不同,可能是 rsync
一次性複製,也可以透過 SMB 雙向同步共享資料夾
provisioning
接著我們安裝上 nodejs,讓我們透過 shell script 安裝 nvm,並建立 server 資料夾放到 vm 中,接著透過 pm2 啟動
將 Vagrantfile 改成
|
|
每一個 config.vm.provision
代表一個步驟,我們指定了
- 執行 init.sh:主要是安裝 nvm 與 pm2
file
是用來複製檔案,將 server 路徑複製到 /home/vagrant/ 底下- start.sh 主要是啟動 nodejs server
config.vm.synced_folder
則是顯示指定我們要同步到 /vagrant 底下的資料,也可以指定到其他資料夾下,不過要小心處理檔案路徑
接著執行
|
|
注意如果這時候跑 $ vagrant up 是沒有用的,因為 vm 已經啟動了,如果是 Vagrantfile 增加 provision,記得用 $ vagrant provision
或 $ vagrant reload --provision
,如果是 Vagrantfile 其他設定檔有更動,請用 $ vagrant reload
此時 ssh 登入後可以看到 nodejs server 已經在執行了
這時候好好說一下 shell 需要注意的地方,
|
|
可以看到我在 init.sh / start.sh 要呼叫 nvm/pm2 之前都要 $source ~/.nvm/nvm.sh
而非 $source ~/.bash.sh
,主要是因為預設 vagrant 的 .bashrc 有這一段
|
|
而我們又將 nvm 的啟動 script 放在這一段之後才會導致 shell 找不到 nvm command,所以要改成$source ~/.nvm/nvm.sh
,這部分是參考 stackoverflow Why is nvm command installed as root and also not found during vagrant bootstrap.sh?
其他的 provisioning 工具搭配請參考文件
destroy
如果開發過程中有誤,建議 Vagrantfile 改完砍到 vm 重來,使用
$ vagrant destroy
,主要是每次執行 $ vagrant provision 會不斷在原本的 vm instance 操作,這樣會導致每次疊加結果而違反 immutable
network
在 Vagrant 中,網路大致有三種設定方式
Port Forward
讓 Host 環境可以用指定 port 對應 VM 中的 portPrivate Network
指定 private ip 讓內網的機器都能透過 ip 溝通Public Network
Vagrant 預設整合 Ngrok,可以用公開連結連線
此時 nodejs server 只能在 vm 內部使用,我們用 Port Forward 方式讓 host 也可以呼叫
修改 Vagrantfile
|
|
接著用 $ vagrant reload
這時候在 Host 就可以發請求到 VM 上囉 $ curl localhost:8080
小結
在 Provisioning 部分,個人覺得用 shell script 有點不太方便,例如說切換 OS 時 script 就需要修改,而且很指令式而非宣告式,如果能用其他的 provisioning tool 去管理,又或是使用 image / container 去隔離對底層 OS 的相依,這勢必會方便很多
Vagrant 有提供 AWS provider,但因為是社群開發套件就暫且不試,專注在搭建本地端的開發環境
目前是只有一台 api server,接著要配置 DB 並放在同一個 Vagrantfile 中整理
Multi machile
如果要在 Vagrantfile 中定義多個 vm instance,可以透過 config.vm.define
區隔,預設會繼承全域的所有 provision,但是個別定義中可以複寫或是客製化,如以下
|
|
如果想要指定其中一台下指令,針對名稱就好如 $vagrant ssh db
結語
個人覺得開發不推薦
用 Vagrant (那怎麼花了一個假日…),主要是社群看起來沒有很活躍,例如最多人下載的 box ubuntu/trusty64 還是在 14.04 的版本,想要直接找 Mongodb 的 box 也沒有(大多的 db 都沒有),且整個配置上沒有很方便,例如 shell script 切換 os 就要重寫,還不如用 docker + docker compose 來得快速
但如果你是一定要用 vm 那或許 Vagrant 還是個不錯的選擇
如果你有其他建議,又或是有覺得 Vagrant 有厲害獨特的應用場景再麻煩指教~