--- tags: 實作, 微服務 --- # Vagrant 手冊 本筆記參考課程:[Vagrant从入门到精通](https://www.udemy.com/course/vagrant-zh/) 虛擬化有兩種:Type 1 、Type 2 ![](https://i.imgur.com/E0FLsO4.png) Vagrant 的架構圖例: ![](https://i.imgur.com/FdzfgJ0.png) # 簡介與快速入門 Vagrant 下載位置:[Install Vagrant](https://developer.hashicorp.com/vagrant/downloads) 下載完直接安裝就好。 記得 Bios 需要開啟虛擬化功能。 ## Box 的下載與啟動 Box 想像成 Docker 的 Image 即可。 可以到以下位置去取得:[Discover Vagrant Boxes](https://app.vagrantup.com/boxes/search) 記得根據你的 Provider 去選,這裡以 VirtualBox 為例子,下載 RockyLinux9。 ```shell= 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 ```shell= # 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 指令: ```shell= 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](https://www.parallels.com/blogs/ras/hyperv-vs-virtualbox/) # Vagrantfile Vagrantfile 是用 Ruby 寫的。 ## 目錄結構蓋覽 一共有兩個位置可以知道: 1. Box 儲存位置:\<home\>/.vagrand.d 2. 虛擬機資料位置 ![](https://i.imgur.com/Ht72feu.png) ```shell= 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](https://developer.hashicorp.com/vagrant/docs/vagrantfile) 從 init 指令生成的 Vagrantfile 檔案就有一大堆的註解可以參考,但是詳細的還是去看一下文件才會知道。 ## SSH 相關設定 通常要用 SSH 指令是要先到該資料夾之下才可以使用,而且因為有設定 privateKey 了,所以不需要密碼,並且**有可能預設**就不給你用密碼登入。 ### 密碼登入 要改變可以使用密碼登入,可以先進入該虛擬機,找到以下檔案: ```shell= /etc/ssh/ssh_config ``` 找到 PasswordAuthentication 後面改成 yes,然後重新啟動即可。 ### 快速 Windows SSH 登入 vagrant ssh-config 指令得到的設定內容可以直接給 Windows 的 ssh 指令快速登入用。 ```shell= 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。 其位置在以下路徑: ```shell= <home>/vagrant.d/insecure_private_key ``` ![](https://i.imgur.com/WXRvVWb.jpg) 這個 key 預設都是不使用的,而是每一個虛擬機建立的時候,都會去建立一個自己的 Key pair。 但如果是在測試環境的時候,需要大量的虛擬機,如果每一台都不一樣的 key 會讓管理及連線非常麻煩。 故可以於 Vagrantfile 中加入以下設定來使用共用的預設 insecure_private_key。 ```shell! config.ssh.insert_key = false ``` 這個共用的 Key 當然也可以用自己生成的,這部分請參考後續章節。 ## 單一設定,多台生成 只要使用以下設定即可:define 注意一下 Global 跟區域單獨的設定位置即可。 ```ruby= 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 迴圈的寫法來改寫這一個設定: ```ruby= 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 的同步機制。 該檔案的位置如下: ```shell= C:\Users\<home>\.vagrant.d\boxes\generic-VAGRANTSLASH-rocky9\4.2.14\virtualbox\Vagrantfile ``` > rsync 的同步機制是一次性在創建虛擬機的時候複製檔案過去的,不符合人性。 這裡可以直接改設定,或者直接砍掉相關同步的設定,讓他跑預設的設定。 相關設定可參考官方文件:[ Synced Folders - Basic Usage](https://developer.hashicorp.com/vagrant/docs/synced-folders/basic_usage) 總之要達到同步效果總共有兩個要點: 1. 針對 Virtual Box 的 Box 設定移除 rSync 的同步功能設定部分,或者改設定 * 需要到該 Box 的目錄下設定 2. 安裝 virtualbox guest additions 這個外掛 * 安裝一次就可以了,不建議從 GUI 上安裝 外掛的安裝可以使用 plugin 指令來安裝: ```shell= vagrant plugin install vagrant-vbguest ``` * 可以使用 --version 指定版本 > 時間點 2023/3/24 註記: > 安裝的外掛版本是 0.31.0 > 啟動虛擬機的時候 Terminal 會顯示一些錯誤,關於你的版本 6.1.40 與 7.0.6 ( 我安裝的 VirtualBox 版本 ) 不相符 > 但是最後流程安裝好了之後還是可以正常運作。 為了要相容於其他人使用此檔案沒有裝外掛的情況,加入以下設定於 Vagrantfile 就可以在未安裝的情況下先行安裝後再執行: ```ruby= # 如果沒有安裝 Virtual Box 外掛,則先安裝: if Vagrant.has_plugin?("vagrant-vbguest") then config.vbguest.auto_update = false end ``` ### HyperV 的同步設定 其實就是改同步方式設定而已,請於設定檔中使用以下設定即可: ```ruby= config.vm.synced_folder ".", "/vagrant", type: "smb" ``` * 改成 smb 就好 ### HyperV 與 VirtualBox 混合式設定 以下的範例設定加上去之後,就可以根據 provider 去判斷,要使用哪一種同步方式: ```ruby= # 混合式同步設定,根據 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 存在。 ```shell= /home/vagrant/.ssh/authorized_keys ``` 3. 請找出虛擬機的名稱,而且其網路的設定在網卡一必須要是 NAT * 用 GUI 就可以看到名稱了 * 網路的設定也是 GUI 設定 ![](https://i.imgur.com/AIrw2Id.jpg) ![](https://i.imgur.com/iZbAdRU.jpg) 以上設定完成後,使用以下指令就可以成功製作出 box 檔案: ```shell= vagrant package --base <vmName> ``` 有了製作好的 box 檔案,再來就把該檔案增加到系統的 box list 後就能夠使用了。 ```shell= # 增加 box 至系統 vagrant box add --name <自訂名稱> --provider=virtualbox <boxFileLocation> # 啟動 vagrant init <自訂名稱> vagrant up ``` ## 上傳自建的 box 到 Vagrant Cloud 首先去 Vagrant Cloud 註冊。 創建並填寫 Box 資訊等等,非常簡單,就只是把你剛剛建立好的 Box 檔案上傳上去而已。 其中需要注意的填寫項目有一個 Checksum,這個可以透過以下指令取得: ```shell= Get-FileHash <boxFileLocation> ``` 完成後 Release 即可公開。 ## 建立 hyperV 版本的 Box 檔案 Skip,有需要再看。 # 網路設定 網路設定部分,VirtualBox 與 HyperV 的預設網卡機制是不一樣的。 1. VirtualBox:使用的是 NAT,Port 轉發 * 多個虛擬機之間不可互 ping * 虛擬機可以往外網 Ping,反之不行。 * ssh-config 可以看到轉發的 port 是多少,GUI 也可以 ![](https://i.imgur.com/XITJqGl.jpg) 2. HyperV:使用的是 Switch 的方式 * 多個虛擬機是可以互 Ping 的。 * 由於限制很多,很多設定無法於 Vagrantfile 中設定,故此節不介紹 HyperV 的設定法。 ## 轉發 Port 的設定 GUI 的設定方法參照上面的圖所示,直接加就可以。 * 虛擬機 -> 右鍵設定 -> 網路 -> 連接阜轉發 -> 新增 Vagrantfile 的設定使用以下 Code: ```ruby= 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](https://developer.hashicorp.com/vagrant/docs/networking/private_network) 這裡的針對 IP 設定有兩種:Static IP 或者 DHCP DHCP 因為 IP 會變,有可能造成開發上的不便利,故常用的開發環境是使用指定固定 IP 的方式來設定。 有設定網路的話,你會看到 Windows 的網路設定中,看到有一個新的網卡被建立。 ![](https://i.imgur.com/TCDO4r0.png) 也可以在虛擬機中查看網路卡的設定: ```shell= ip a ``` ### Static IP ```ruby= Vagrant.configure("2") do |config| config.vm.network "private_network", ip: "192.168.50.4" end ``` * 直接指定想要的固定 IP 位置 ### DHCP ```ruby= Vagrant.configure("2") do |config| config.vm.network "private_network", type: "dhcp" end ``` 在 Vagrant 中,已經有寫死預設的 DHCP 要使用的 IP 網段設定,所以每次的建立,都使用同一個預設的虛擬網卡,並不會另外建立新的。 ## Public network 官方文件可以參考:[Public Networks](https://developer.hashicorp.com/vagrant/docs/networking/public_network) 這是直接將虛擬機連接到本機實體網路卡上,並不會使用自建的虛擬網卡。 所以如果進入到 Wifi Router 裡面看的話,是會看的到這台虛擬機的出現。 ```ruby= Vagrant.configure("2") do |config| config.vm.network "public_network", use_dhcp_assigned_default_route: true end ``` # Provision 所謂 Provision 在 Vagrant 中就是創建完虛擬機後,需要做的一連串設定、安裝等等動作。 詳細可參考官方文件:[Provisioning](https://developer.hashicorp.com/vagrant/docs/provisioning) 以下介紹其中的兩種使用方法: ## Shell Provisioner 使用 ShellScript 去設定的方法有兩種: 1. inline:直接寫在 Vagrantfile 中。 2. path:另外寫一個 sh 檔案然後於 Vagrantfile 中指定該檔案位置去執行。 要令其執行,有三種指令: ```shell= # 一起動創建的時候執行 vagrant up # 當虛擬機已經創建後,可以使用更新的方式去執行。 vagrant provision vagrant reload --provision. ``` ### inline 在 init 產生出的 Vagranfile 中已經有註解了,打開來後就能使用: ```ruby= 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 ```ruby= Vagrant.configure("2") do |config| config.vm.provision "shell", path: "./start.sh" end ``` * path 相對位置是根據你的 Vagrantfile 檔案位置來看的。 ## Ansible Ansible 是一個自動化組態設定工具,本節不解釋這東西是什麼。 * 只能在 Linux 上跑 * Python 陣營的組態管理工具 ```ruby= Vagrant.configure("2") do |config| # Run Ansible from the Vagrant Host config.vm.provision "ansible" do |ansible| ansible.playbook = "playbook.yml" end end ``` * 了解過 Ansible 再回頭看教學影片。