Vagrant 手冊

本筆記參考課程:Vagrant从入门到精通

虛擬化有兩種:Type 1 、Type 2

Vagrant 的架構圖例:

簡介與快速入門

Vagrant 下載位置:Install Vagrant

下載完直接安裝就好。

記得 Bios 需要開啟虛擬化功能。

Box 的下載與啟動

Box 想像成 Docker 的 Image 即可。

可以到以下位置去取得:Discover Vagrant Boxes

記得根據你的 Provider 去選,這裡以 VirtualBox 為例子,下載 RockyLinux9。

vagrant init generic/rocky9 vagrant up --provider=virtualbox vagrant status
  • 使用 init 會在目前位置創建一個 Vagrantfile 檔案,這就是用來建立虛擬機的腳本檔案
    • 請自行選擇適當的位置執行 init
  • up 指令就會根據目前位置的 Vagrantfile 來建立虛擬機
    • 記得可以手動指定 Provider,這裡指定 virtualBox
  • 最後可以使用 status 查看虛擬機狀態。

常用指令

以下指令都必須於對應的資料夾下才會有用!!!

指令 說明
vagrant up 啟動虛擬機
vagrant status 查看虛擬機狀態
vagrant ssh <name> 連線虛擬機
vagrant ssh-config 查看虛擬機 ssh 設定
vagrant suspend 暫停
vagrant resume 回復
vagrant reload 重載
vagrant halt 關機
vagrant destory <name> 刪除

以下說明 SSH 的方法:

  1. 最簡單的就是直接 vagrant ssh 就可以直接進入了。
  2. 或者直接使用 ssh 指令
    • 首先用 ssh-config 找到虛擬機的 ip 與 port
# vagrant ssh-config Host default HostName 127.0.0.1 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile D:/VirtualBox/generic_rocky9/.vagrant/machines/default/virtualbox/private_key IdentitiesOnly yes LogLevel FATAL

再來使用 ssh 指令:

ssh -i 'D:/VirtualBox/generic_rocky9/.vagrant/machines/default/virtualbox/private_key' vagrant@127.0.0.1 -p 2222
  • -i 指定 key 的位置
    • 從 IdentityFile 欄位複製就好
  • 後面接使用者名稱+@+IP位置
  • 如果 port 不是 22 就要用 -p 參數指定

登入後的使用者是 vagrant,如果要打密碼的話,也是一樣。

HyperV 與 VirtualBox 哪個效能比較好??

可以參考此篇文章:Hyper V vs VirtualBox: Understanding Their Differences

Vagrantfile

Vagrantfile 是用 Ruby 寫的。

目錄結構蓋覽

一共有兩個位置可以知道:

  1. Box 儲存位置:<home>/.vagrand.d
  2. 虛擬機資料位置

tree /F D:. │ Vagrantfile │ └─.vagrant ├─machines │ └─default # 虛擬機名稱 │ └─virtualbox # 虛擬機 Provider │ action_provision │ action_set_name │ box_meta │ creator_uid │ id │ index_uuid │ private_key # 虛擬機 SSH Key │ synced_folders │ vagrant_cwd # 虛擬機硬碟 │ └─rgloader loader.rb

基本設定指引

可以參考官方文件:Vagrantfile Documents

從 init 指令生成的 Vagrantfile 檔案就有一大堆的註解可以參考,但是詳細的還是去看一下文件才會知道。

SSH 相關設定

通常要用 SSH 指令是要先到該資料夾之下才可以使用,而且因為有設定 privateKey 了,所以不需要密碼,並且有可能預設就不給你用密碼登入。

密碼登入

要改變可以使用密碼登入,可以先進入該虛擬機,找到以下檔案:

/etc/ssh/ssh_config

找到 PasswordAuthentication 後面改成 yes,然後重新啟動即可。

快速 Windows SSH 登入

vagrant ssh-config 指令得到的設定內容可以直接給 Windows 的 ssh 指令快速登入用。

C:\VagrantNode\generic_rocky9>vagrant ssh-config Host default HostName 127.0.0.1 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile C:/VagrantNode/generic_rocky9/.vagrant/machines/default/virtualbox/private_key IdentitiesOnly yes LogLevel FATAL

將以上內容複製到 <home>/.ssh/config 的檔案內容中,如果沒有資料夾請自行創建。

把 default 改成你想要的名稱,之後只要使用『ssh <名稱>』,即可連線到該虛擬機。

不同 provider 的虛擬機,IP 位置等等可能不會是 localhost 等等,這時候需要注意需要回去更改檔案內容才可以正常。

共用 Private Key

預設的情況下,Vagrant 會有一個共用相同的 private key,是每個 Vagrant 使用者都一樣的 key。

其位置在以下路徑:

<home>/vagrant.d/insecure_private_key

這個 key 預設都是不使用的,而是每一個虛擬機建立的時候,都會去建立一個自己的 Key pair。

但如果是在測試環境的時候,需要大量的虛擬機,如果每一台都不一樣的 key 會讓管理及連線非常麻煩。

故可以於 Vagrantfile 中加入以下設定來使用共用的預設 insecure_private_key。

config.ssh.insert_key = false

這個共用的 Key 當然也可以用自己生成的,這部分請參考後續章節。

單一設定,多台生成

只要使用以下設定即可:define
注意一下 Global 跟區域單獨的設定位置即可。

Vagrant.configure("2") do |config| # Global 設定 config.vm.hostname = "custom_hostname" # 局部設定,自訂名為 myVM1 虛擬機 config.vm.define "" do |custom_vm_name| custom_vm_name.vm.hostname = "myVM1_host" end end

更好的寫法

上面的寫法,如果要多台設定的話,會要非常多行的 config.vm.define。

這一小節介紹透過 Ruby 的 Map 與 For 迴圈的寫法來改寫這一個設定:

boxes = [ { :name => "k8s-master", :eth1 => "192.168.56.10", :mem => "4096", :cpu => "2" }, { :name => "k8s-worker1", :eth1 => "192.168.56.11", :mem => "2048", :cpu => "2" }, { :name => "k8s-worker2", :eth1 => "192.168.56.12", :mem => "2048", :cpu => "2" } ] Vagrant.configure(2) do |config| # config.vm.box = "ubuntu/jammy64" config.vm.box = "ubuntu/focal64" #ubuntu 20.04 boxes.each do |opts| config.vm.define opts[:name] do |config| config.vm.hostname = opts[:name] config.vm.provider "vmware_fusion" do |v| v.vmx["memsize"] = opts[:mem] v.vmx["numvcpus"] = opts[:cpu] end config.vm.provider "virtualbox" do |v| v.customize ["modifyvm", :id, "--memory", opts[:mem]] v.customize ["modifyvm", :id, "--cpus", opts[:cpu]] end config.vm.network :private_network, ip: opts[:eth1] end end config.vm.provision "shell", privileged: true, path: "./setup.sh" end
  • 使用名為 boxes 的 map 儲存自訂設定
  • 對 boxes 使用 foreach 來逐個設定

與虛擬機同步檔案

此小節說明同步本機的檔案到虛擬機中的方法,以 VirtualBox 為例。

事實上原本的 Box 檔案下載來之後,也會有一個 Vagrantfile,裡面一樣可以做設定,有可能裡面禁用了同步功能,或者是使用了名為 rsync 的同步機制。

該檔案的位置如下:

C:\Users\<home>\.vagrant.d\boxes\generic-VAGRANTSLASH-rocky9\4.2.14\virtualbox\Vagrantfile

rsync 的同步機制是一次性在創建虛擬機的時候複製檔案過去的,不符合人性。

這裡可以直接改設定,或者直接砍掉相關同步的設定,讓他跑預設的設定。

相關設定可參考官方文件:
Synced Folders - Basic Usage

總之要達到同步效果總共有兩個要點:

  1. 針對 Virtual Box 的 Box 設定移除 rSync 的同步功能設定部分,或者改設定
    • 需要到該 Box 的目錄下設定
  2. 安裝 virtualbox guest additions 這個外掛
    • 安裝一次就可以了,不建議從 GUI 上安裝

外掛的安裝可以使用 plugin 指令來安裝:

vagrant plugin install vagrant-vbguest
  • 可以使用 version 指定版本

時間點 2023/3/24 註記:
安裝的外掛版本是 0.31.0
啟動虛擬機的時候 Terminal 會顯示一些錯誤,關於你的版本 6.1.40 與 7.0.6 ( 我安裝的 VirtualBox 版本 ) 不相符
但是最後流程安裝好了之後還是可以正常運作。

為了要相容於其他人使用此檔案沒有裝外掛的情況,加入以下設定於 Vagrantfile 就可以在未安裝的情況下先行安裝後再執行:

# 如果沒有安裝 Virtual Box 外掛,則先安裝: if Vagrant.has_plugin?("vagrant-vbguest") then config.vbguest.auto_update = false end

HyperV 的同步設定

其實就是改同步方式設定而已,請於設定檔中使用以下設定即可:

config.vm.synced_folder ".", "/vagrant", type: "smb"
  • 改成 smb 就好

HyperV 與 VirtualBox 混合式設定

以下的範例設定加上去之後,就可以根據 provider 去判斷,要使用哪一種同步方式:

# 混合式同步設定,根據 provider 切換: config.vm.provider "hyperv" do |v| config.vm.synced_folder ".", "/vagrant", type: "smb" end config.vm.provider "" do |_, override| override.vm.synced_folder ".", "/vagrant", type: "virtualbox" end

Vagrant Box

基本的指令當成 Image 來看就好:

指令 意義 可選參數
vagrant box add <boxName> 下載 Box provider、box-version
vagrant box list 列出目前系統現有的 Box
vagrant box remove <boxName> 移除 Box

自己建立 Box

一樣先以 Virtual Box 為例。

指令也很簡單,但有一些參數的數值跟條件要準備好:

  1. 虛擬機需要安裝 virtualbox guest additions
    • 參考前一小節的安裝法
  2. 要打包的虛擬機,其 SSH 用的 Key ,必須要有包含 insecure_private_key 用的公鑰在裡面才行。
    • 請查看 authorized_keys 這個檔案的內容,是否有insecure_private_key 存在。
/home/vagrant/.ssh/authorized_keys
  1. 請找出虛擬機的名稱,而且其網路的設定在網卡一必須要是 NAT
    • 用 GUI 就可以看到名稱了
    • 網路的設定也是 GUI 設定

以上設定完成後,使用以下指令就可以成功製作出 box 檔案:

vagrant package --base <vmName>

有了製作好的 box 檔案,再來就把該檔案增加到系統的 box list 後就能夠使用了。

# 增加 box 至系統 vagrant box add --name <自訂名稱> --provider=virtualbox <boxFileLocation> # 啟動 vagrant init <自訂名稱> vagrant up

上傳自建的 box 到 Vagrant Cloud

首先去 Vagrant Cloud 註冊。

創建並填寫 Box 資訊等等,非常簡單,就只是把你剛剛建立好的 Box 檔案上傳上去而已。

其中需要注意的填寫項目有一個 Checksum,這個可以透過以下指令取得:

Get-FileHash <boxFileLocation>

完成後 Release 即可公開。

建立 hyperV 版本的 Box 檔案

Skip,有需要再看。

網路設定

網路設定部分,VirtualBox 與 HyperV 的預設網卡機制是不一樣的。

  1. VirtualBox:使用的是 NAT,Port 轉發
    • 多個虛擬機之間不可互 ping
    • 虛擬機可以往外網 Ping,反之不行。
    • ssh-config 可以看到轉發的 port 是多少,GUI 也可以

  1. HyperV:使用的是 Switch 的方式
    • 多個虛擬機是可以互 Ping 的。
    • 由於限制很多,很多設定無法於 Vagrantfile 中設定,故此節不介紹 HyperV 的設定法。

轉發 Port 的設定

GUI 的設定方法參照上面的圖所示,直接加就可以。

  • 虛擬機 -> 右鍵設定 -> 網路 -> 連接阜轉發 -> 新增

Vagrantfile 的設定使用以下 Code:

Vagrant.configure("2") do |config| # Create a forwarded port mapping which allows access to a specific port # within the machine from a port on the host machine and only allow access # via 127.0.0.1 to disable public access config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" end
  • 這在 init 所生成的檔案中有註解,直接打開就可以用了。
  • guest 設定虛擬機 port,host 設定本機的 port

Private network

可以參照官方文件章節:Private Networks

這裡的針對 IP 設定有兩種:Static IP 或者 DHCP

DHCP 因為 IP 會變,有可能造成開發上的不便利,故常用的開發環境是使用指定固定 IP 的方式來設定。

有設定網路的話,你會看到 Windows 的網路設定中,看到有一個新的網卡被建立。

也可以在虛擬機中查看網路卡的設定:

ip a

Static IP

Vagrant.configure("2") do |config| config.vm.network "private_network", ip: "192.168.50.4" end
  • 直接指定想要的固定 IP 位置

DHCP

Vagrant.configure("2") do |config| config.vm.network "private_network", type: "dhcp" end

在 Vagrant 中,已經有寫死預設的 DHCP 要使用的 IP 網段設定,所以每次的建立,都使用同一個預設的虛擬網卡,並不會另外建立新的。

Public network

官方文件可以參考:Public Networks

這是直接將虛擬機連接到本機實體網路卡上,並不會使用自建的虛擬網卡。

所以如果進入到 Wifi Router 裡面看的話,是會看的到這台虛擬機的出現。

Vagrant.configure("2") do |config| config.vm.network "public_network", use_dhcp_assigned_default_route: true end

Provision

所謂 Provision 在 Vagrant 中就是創建完虛擬機後,需要做的一連串設定、安裝等等動作。

詳細可參考官方文件:Provisioning

以下介紹其中的兩種使用方法:

Shell Provisioner

使用 ShellScript 去設定的方法有兩種:

  1. inline:直接寫在 Vagrantfile 中。
  2. path:另外寫一個 sh 檔案然後於 Vagrantfile 中指定該檔案位置去執行。

要令其執行,有三種指令:

# 一起動創建的時候執行 vagrant up # 當虛擬機已經創建後,可以使用更新的方式去執行。 vagrant provision vagrant reload --provision.

inline

在 init 產生出的 Vagranfile 中已經有註解了,打開來後就能使用:

Vagrant.configure("2") do |config| # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL sudo yum install -y epel-release sudo yum install -y nginx sudo yum install -y vim sudo systemctl nginx start SHELL end
  • epel 是一個 Repository ,安裝後就可以在裡面找到常用的安裝包

path

Vagrant.configure("2") do |config| config.vm.provision "shell", path: "./start.sh" end
  • path 相對位置是根據你的 Vagrantfile 檔案位置來看的。

Ansible

Ansible 是一個自動化組態設定工具,本節不解釋這東西是什麼。

  • 只能在 Linux 上跑
  • Python 陣營的組態管理工具
Vagrant.configure("2") do |config| # Run Ansible from the Vagrant Host config.vm.provision "ansible" do |ansible| ansible.playbook = "playbook.yml" end end
  • 了解過 Ansible 再回頭看教學影片。