最近要幫客戶在 Azure 架設一台 Nginx 反向代理伺服器 (Ubuntu 20.04 LTS),我想透過 cloud-init 將整台 VM 從無到有全自動安裝設定完畢,經過幾個小時的努力,終於達成全自動化建置的目標,實在非常令人振奮。這篇文章我就來說說部署的過程與技術細節。
部署方法
以下就是我的最終成果,日後照著 SOP 就可以快速的建立出完全相同需求的 Nginx 反向代理伺服器 VM,而且只要經過一些微調,就可以應用在完全不同的情境上。
-
先準備好一份 cloud-init 設定檔 (cloud-init.yml
)
由於我是要架設「反向代理伺服器」,因此其中 proxy_pass
指向的網站要先決定好目標網址,以及 proxy_set_header Host
的標頭內容也要先依據需求設定好。
#cloud-config
apt_update: true
apt_upgrade: true
package_upgrade: true
packages:
- nginx
write_files:
- owner: www-data:www-data
path: /etc/nginx/sites-available/default
content: |
server {
listen 80;
location / {
proxy_pass https://duotify-itblog.azurewebsites.net;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
# proxy_set_header Host $host;
proxy_set_header Host duotify-itblog.azurewebsites.net;
proxy_cache_bypass $http_upgrade;
}
}
runcmd:
- service nginx restart
-
建立 Azure 資源群組 & 虛擬機器 & 開啟防火牆
執行以下命令之前,要先準備好遠端 SSH 連線所需的 SSH 公開金鑰檔 (id_rsa.pub
)!
PowerShell
az group create -n VM -l japaneast
az vm create -g VM -n FrontNode `
--image UbuntuLTS `
--size Standard_DS1_v2 `
--admin-username azureuser `
--ssh-key-values '@id_rsa.pub' `
--custom-data 'cloud-init.yml'
az vm open-port -g VM -n FrontNode --port 80 --priority 900
$IP=(az vm show -d -g VM -n FrontNode --query publicIps -o tsv)
echo "SSH Login: ssh -l azureuser $IP"
echo "Nginx URL: http://$IP"
echo "cURL Test: curl http://$IP -D -"
Bash
az group create -n VM -l japaneast
az vm create -g VM -n FrontNode \
--image UbuntuLTS \
--size Standard_DS1_v2 \
--admin-username azureuser \
--ssh-key-values @id_rsa.pub \
--custom-data cloud-init.yml
az vm open-port -g VM -n FrontNode --port 80 --priority 900
IP=$(az vm show -d -g VM -n FrontNode --query publicIps -o tsv)
echo "SSH Login: ssh -l azureuser $IP"
echo "Nginx URL: http://$IP"
echo "cURL Test: curl http://$IP -D -"
就醬,兩個步驟就輕鬆完成部署! 😎
技術細節講解: cloud-init.yml
-
該檔案第一行必須為 #cloud-config
開頭 (詳見 Cloud Config Data 文件)
#cloud-config
-
設定 VM 自動更新套件到最新版
apt_update: true
apt_upgrade: true
package_upgrade: true
-
自動安裝 nginx
套件
packages:
- nginx
-
寫入實體檔案並指定檔案擁有者
write_files:
- owner: www-data:www-data
path: /etc/nginx/sites-available/default
content: |
server {
listen 80;
location / {
proxy_pass https://duotify-itblog.azurewebsites.net;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
# proxy_set_header Host $host;
proxy_set_header Host duotify-itblog.azurewebsites.net;
proxy_cache_bypass $http_upgrade;
}
}
-
部署完成後自動執行命令
runcmd:
- service nginx restart
技術細節講解: Azure CLI
-
建立資源群組
az group create -n VM -l japaneast
-
建立 UbuntuLTS
的虛擬機器
az vm create -g VM -n FrontNode `
--image UbuntuLTS `
--size Standard_DS1_v2 `
--admin-username azureuser `
--ssh-key-values '@id_rsa.pub' `
--custom-data 'cloud-init.yml'
這裡有好幾個重要的參數:
--image
指定你要建立的 VM Image 的名稱,而 UbuntuLTS
是一個通用的 Image 名稱,他會自動找到 Ubuntu 最新 LTS 的 Image 來用。以下是查詢完整 VM Image 清單的命令:
# 列出所有 Image 的發行商 (Ubuntu 的發行商為 Canonical)
az vm image list-publishers --location japaneast --output table
# 列出 VM 發行商的提供方案 (Offers) (UbuntuLTS 來自 0001-com-ubuntu-server-focal 方案)
az vm image list-offers -l japaneast --publisher Canonical --output table
# 列出 VM 發行商的方案中所有可用的 Image 清單 (輸出結果中的 Urn 欄位,就是可以讓你用來指定建立的 Image 名稱)
az vm image list -l japaneast --offer 0001-com-ubuntu-server-focal --publisher Canonical --all --output table | grep "2019-Datacenter-with-Containers"
--size
指定你的 VM 規格,想列出完整的 VM 規格清單 (相當多),可以用以下命令查詢:
az vm list-sizes --location japaneast -o table
--admin-username
指定預設登入的使用者名稱,預設值就是 azureuser
--ssh-key-values
指定用來 SSH 遠端登入的 SSH Public Key 檔案。不過,在使用 PowerShell 執行時要特別注意 @
符號的使用,你必須在 @id_rsa.pub
的前後加上單引號,確保命令可以正確傳入參數!如果在 Bash 環境的話,就比較沒這個問題。
--custom-data
主要用來指定 cloud-init 的設定檔路徑,當 VM 部署後第一次開機,這個 Custom Data 會被自動複製到 /var/lib/waagent/
目錄中,並儲存在 ovf-env.xml
檔案裡。
-
開啟防火牆設定
以下命令主要用來開放特定 Port 可以讓 Internet 完全公開的存取:
az vm open-port -g VM -n FrontNode --priority 900 --port 80
-
取得 Azure VM 的實體 IP 地址
az vm show -d -g VM -n FrontNode --query publicIps -o tsv
常見問題解答
-
重新執行 cloud-init 自訂腳本
我剛開始在嘗試 cloud-init 的時候,遇過幾次沒有全自動部署的情況,此時如果你要將 cloud-init 的設定檔重新在已經開機的 VM 上重新執行一遍,可以在 VM 中執行以下命令:
sudo cloud-init clean
sudo cloud-init init
相關連結