前言
為什麼要使用 Load Balancer?
- 可以分攤流量, 利用多台機器跑多個服務
- 當一台機器掛了,你還有另外一台
- 當負載到達一定程度,可以啟動 auto scaling (本篇不會使用到)
- 配合適當的 CI / CD, 以及健康檢查,可達到
rolling upgrade
的效果
本篇重點
- 本篇分享最簡單易設的 unmanaged Load Balancer
- 為避免混淆,本篇對於有意義的元件術語,將維持原文,不會特別翻譯
- 詳解每個元件行為
簡單的概念圖如下 (圖片來源: Google ):
- IPv4 以及 IPv6 的使用者,對我們的服務發請求
- 我們設定的
IPv4 以及 IPv6 Forwading rules
,會將使用者導向我們設定好的HTTP(S) proxy
- 到了
HTTP(S) proxy
的 request, 會根據我們設定好的url-map
規則,導向相對應的backend-service
, 例如說, 透過 domain name 為 ‘test1’ 的 request, 導向backend-service 1
, 而 ‘test2’ 的 request 導向backend-service 2
backend-service
由instance group
組成,舉例來說,我們可以指定,backend-service A
導向instance group A
的 port 8000 , 而backend-service B
導向instance group B
的 port 6000instance group
, 顧名思義,由instance
所組成,當我們在instance group
中設定好特定的 port, 並且設定好backend-service
, 那麼 request 將會經由backend-service
, 再到instance group
指定的 port, 最後到依照instance
本身的負載狀況, 將 request 導向適合服務的instance
- 每個
backend-service
都可以設定一個health-check
,health-check
會根據指定的頻率向指定的 port 探測並取得回應,如果回應的速度低於我們設立的門檻,那麼該instance
就會被判定為不健康。 request 不會導向已被判定為不健康的instance
- 如果有 SSL 需求,可建立
SSL certificate
, 並且掛在 HTTPS proxy - 以下我們就開始來實作吧!
安裝 Google Cloud SDK
本篇所有的指令都會使用到 Google Cloud SDK
的指令, 所有在我們開始之前,先安裝它哦!
根據你的作業系統的不同,安裝方法也不一樣哦,請參考官方文件
建立 instance
- 建立兩個 instances
gcloud compute instances create test-01 \ |
gcloud compute instances create test-02 \ |
- 建立二台機器, 叫做 test-01, test-02
- 開機碟的空間為 30GB
- 從
ubuntu-os-cloud
, 來 pull 我們需要的image
- 我們使用
ubuntu-1804-lts
的image
版本, 這會自動使用這個版本的最新版 - 硬碟類型為
pd-standard
, 不知道類型可以跑gcloud compute disk-types list
來看看 - 機器型號為
f1-micro
, 不知道類型可以跑gcloud compute machine-types list
來看看 tags
用來當作該 instance 的一個識別,等等開防火牆的時候會用到zone
指定該 instance 的地區, 有些資源只有相同zone
或者region
可以取用,要注意- 可參考官方文件
instance 環境建置
以下為 instance
上的環境建置範例,與本篇主題較無關係,可跳過
apt-get update -y && apt-get install curl -y && curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash && export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" && nvm install yourNodeVersion && apt-get install npm -y && npm install pm2 -g && pm2 update && apt-get install git -y && apt-get install build-essential |
開啟防火牆
看服務跑在哪一個 port, 我們需要將防火牆打開,這樣 instance group
才能將 request 從 Load Balancer
經由 backend-service
導向相對應的 port, 可參考官方文件
gcloud compute firewall-rules create test-01 --allow tcp:123,tcp:456,tcp:789 --target-tags test-01 |
gcloud compute firewall-rules create test-02 --allow tcp:123,tcp:456,tcp:789 --target-tags test-02 |
外部靜態 IP
這邊建立一個 IPv4 的靜態 IP , 之後會用到, 可參考官方文件
gcloud compute addresses create lb-test \ |
Instance group
Instance group
可由多個 instance
所組成,為組成 backend-service
的主體, 可參考官方文件
- 建立
instance group
, 之後Load Balancer
可以用它來建立不同的backend-service
gcloud compute instance-groups unmanaged create test --description 'run test project' --zone asia-east1-c |
- 設定 named port, 所以不同的
backend-service
可以指定要用哪一個 port
gcloud compute instance-groups unmanaged set-named-ports test --named-ports port1:3000,port2:6000,port3:9000,port4:12000,port5:15000 --zone asia-east1-c |
- 將現有的
instance
加到instance group
gcloud compute instance-groups unmanaged add-instances test \ |
Health check
health-check
, 可根據我們指定的頻率,探測指定的 port, 如果該 port 無回應, health-check
將判定這個 port 不健康, backend-service
不會將 request 送往不健康的 instance
可參考官方文件
gcloud compute health-checks create tcp test-tcp-3000 \ |
gcloud compute health-checks create tcp test-tcp-6000 \ |
gcloud compute health-checks create tcp test-tcp-9000 \ |
gcloud compute health-checks create tcp test-tcp-12000 \ |
gcloud compute health-checks create tcp test-tcp-15000 \ |
Backend service
這邊的 --port-name
, 就是上面我們在 instance-group
中,建立的 port, 在此範例中,不同的 backend-service
會將 request 導向不同的 port, 這邊看起來沒有提到 instance group
? 別緊張,下一步我們就會把 instance group
加到 backend-service
當中。
同理, health-check
也是掛在 backend-service
上的, 因為 backend-service
將決定要將 request 導向哪一個 instance
。可參考官方文件
- 建立後端服務
gcloud compute backend-services create backend-service-port1 \ |
gcloud compute backend-services create backend-service-port2 \ |
gcloud compute backend-services create backend-service-port3 \ |
gcloud compute backend-services create backend-service-port4 \ |
gcloud compute backend-services create backend-service-port5 \ |
接下來,我們將 instance group
加到我們剛剛建立的 backend-service
, 因為我們在建立 backend-service
時就已指定了 port, 所以 backend-service
會將 request 導向所屬的 instance group
中已指定的 port, 嗯, 聽起來有點饒舌, 不過的確是這樣。
除了設定導向的 port 之外,這邊也會設定 instance
的負載門檻。 設定 UTILIZATION
表示使用率,當使用到 80 % 時, backend-service
便會停止將 request 導向這個 instance
capacity-scaler
表示, 1 * 0.8
, 所以說,如果你有多個 backend-service
使用這個 instance-group
, 那你希望多保留一些 instance-group
的可使用率,給其他 backend-service
使用,那就可以將 capacity-scaler
調低,如此一來,當這個 backend-service
已使用了 capacity-scaler * max-utilization
的 CPU 時,來自於該 backend-service
的請求就不會導向該 instance-group
, 可以很大程度地保留該 instance-group
服務其他 backend-service
的可用性。
下面範例,可參考官方文件
- 將 instance group 加到 backend-service
gcloud compute backend-services add-backend backend-service-port1 \ |
gcloud compute backend-services add-backend backend-service-port2 \ |
gcloud compute backend-services add-backend backend-service-port3 \ |
gcloud compute backend-services add-backend backend-service-port4 \ |
gcloud compute backend-services add-backend backend-service-port5 \ |
URL map
前面介紹完了 backend-service
, 那這個 url-map
, 就是將 request 導向 backend-service
的元件。
首先,我們要先建立一個 url-map
, 並且給予一個默認的 backend-service
, 意思就是說,如果沒有特別指定的話,收到的 request 要導向哪一個 backend-service
下面範例,可參考官方文件
- 建立 URL-map
gcloud compute url-maps create web-map \ |
上面建立了 url-map
, 並且指定了一個默認的 backend-service
, 現在我們可以定義怎麼樣的 request 該導向哪一個 backend-service
。
路徑的指定,我們需要使用 path-matcher
, 範例如下:
path-matcher
: 建立一個 path-matcher
, 並給予指定的路徑規則
new-hosts
: 當 request 是對 host sunday.com.tw
發請求時,會套用此規則
所以就是說, 當 request 的 host 為 sunday.com.tw
時,會導向 backend-service-port1
以下為範例,可參考官方文件
- 新增 path-matcher
gcloud compute url-maps add-path-matcher web-map \ |
這邊可以看到比上面多了一個新的元件,叫做 path-rules
當 request 的 host 為 monday.com.tw
, 默認路徑如 /
會導向 backend-service-port2
當 request 的路徑為 happy
, 如 monday.com.tw/happy
, 會導向 backend-service-port1
當 request 的路徑為 unhappy
, 如 monday.com.tw/unhappy
, 會導向 backend-service-port2
當 request 的路徑為 sad
, 如 monday.com.tw/sad
, 會導向 backend-service-port3
gcloud compute url-maps add-path-matcher web-map \ |
以下範例同上,當 request 為 tuesday.com.tw
時,導向 backend-service-port3
gcloud compute url-maps add-path-matcher web-map \ |
建立 SSL 憑證
要讓我們的服務支援 HTTPS
, 我們需要建立 ssl-certificates
, ssl-certificates
分成 self-managed
, 以及 google-managed
。
self-managed
顧名思義就是你提供你自己的 ssl 簽證,以下範例採用 google-managed
可參考官方文件
gcloud beta compute ssl-certificates create www-ssl-cert \ |
HTTP proxy
所有來自 HTTP 的請求,都會先到這裡,再經由我們剛剛建立的 url-map
導向指定的 backend-service
可參考官方文件
- 建立 HTTP proxy
gcloud compute target-http-proxies create http-lb-proxy \ |
HTTPS proxy
所有來自 HTTPS 的請求,都會先到這裡,再經由我們剛剛建立的 url-map
導向指定的 backend-service
並且,我們剛剛建立的 ssl-certificates
也要掛在這, 這樣 target-https-proxies
才能支援 HTTPS
可參考官方文件
- 建立 HTTPS proxy
gcloud compute target-https-proxies create https-lb-proxy \ |
查看外部靜態 IP 清單
列出我們一開始建立的 addresses
可參考官方文件
gcloud compute addresses list |
轉發規則
當 request 的 address 以及 port 符合 forwarding-rules
, 導向指定的 target-http-proxy
下面範例的 [LB_IP_ADDRESS]
請替換為上面建立的靜態 IP
可參考官方文件
- 建立 HTTP
forwarding-rules
gcloud compute forwarding-rules create http-content-rule \ |
當 request 的 address 以及 port 符合 forwarding-rules
, 導向指定的 target-https-proxy
下面範例的 [LB_IP_ADDRESS]
請替換為上面建立的靜態 IP
可參考官方文件
- 建立 HTTPS
forwarding-rules
gcloud compute forwarding-rules create https-content-rule \ |
總結
以上便是 GCP Load Balancer
的 gcloud 各元件順序流程,順序如下:request
=> forwarding-rules
=> target-http(s)-proxy
=> url-map
=> backend-service
=> instance-group
=> instance
照著以上範例跑完之後,只要在 instance 跑服務,並且跑在範例上指定的 port 號,那 request 應會照著上面的順序到達我們的服務。
我花了不少時間來寫這篇文章,希望有幫到需要的人,如果你已經看到這裡,很感謝你把它看完了!
最後,如果你覺得這篇文章有幫到你,或者你覺得寫得不錯,你的掌聲將是對我最大的鼓勵!
如果有發現任何錯誤,還請不吝指教哦!
留言