當你使用虛擬機器架設好一個網站,你可能會考慮使用 GCP Load Balancer,
這其實也是整個 GCP 最核心的功能,很多大企業也是為此而選擇上雲。
以下逐步帶你確認幾個重要的問題,和設定的步驟。
一、Load Balancer 的架構規劃問題確認
(一) 你為什麼要使用 Load Balancer?
因為 LB 可以達到的效果很多,要看你的情境和預算適不適合,
例如:
1. 你有多台機器要平均分散流量。
這是 LB 的基本功能,它可以自動分流外部流量到所有的機器。
2. 你不想再自己申請 SSL 憑證,想要使用 Google 免費的憑證。
坊間有很多 SSL 憑證供應商,都要付費購買,而且並不便宜,
憑證到期還要自己申請展期,萬一錯過展期時間,
網站就會出現憑證錯誤的訊息
使用者會懷疑網站是不是有問題,影響信譽。
Google 提供免費而且自動續約的憑證,
Google 自己也是權威的憑證授權單位,
有 Google 幫你的網站背書,免費又方便。
但有一個條件,就是你的網域必須指向 LB 的 IP 位址,才能讓憑證生效,後續也會說明相關步驟。
3. 你有多個後端 (多種不同的服務),想依照網址分流到不同後端。
或是依照使用者所在的位置,或是要造訪的網站,
分流到不同機器,都可以使用 LB。
4. 你想用 Cloud Armor 保護主機,阻擋 DDoS 攻擊。
因為 Cloud Armor 必須設定在 LB 上,才能發揮作用,
為此你必須使用 LB,才能在上面套用 Cloud Armor 的防禦政策。
5. 你的網站包含大量媒體內容 (圖片或影片),想要串接 Cloud CDN 發布內容。
同上,Cloud CDN 也必須設定在 LB 上,才能發揮作用。
6. 確認費用可以接受
假如你只有一台 e2-medium 規格的虛擬機器,並且直接對外服務,
費用包含進出 LB 的資料處理費用 (每 GiB 0.008 美元),
以及轉發規則 (Forwarding Rule) 的費用 (每小時 0.025 美元),
假設你的資料處理每月 10 GiB 左右,最基本的費用
0.008 * 10 GB * 2 (資料進和出) + 0.025 * 每月730小時 = 0.08 + 18.25 = 18.41 美元
如果可以接受,就可以考慮採用。

截圖自 GCP 價格計算機
如果上述的問題,只要有一個是肯定的,就可以再往下進行。
在本文的範例中,我們就假設上述需求全部都要做到,
藉此來說明每個功能需要達成的條件和步驟。
(二) 你是否要自動擴充 (Autoscale)?
自動擴充就是當流量大的時候,
GCP 會幫你建立相同的主機來對外服務,
而分流的問題,LB 會自動幫你處理,
讓你的每台主機平均分散負載。
這樣也可以達成高可用性 (High Availibility),
如果你的其中一台機器有問題,
其他主機還是可以持續運作,LB 也可以將流量傳到正常的主機。
但是要做到 Autoscale,必須做到以下兩件事:
1. 把你的主機變成無狀態的 (Stateless)
既然你的主機要隨著流量變大時要自動擴充,
也代表流量變小時要能夠自動縮減,
就是主機會被刪除掉,那主機內的資料不就會跟著消失?
沒錯,所以你的資料庫必須要往外面放,讓你的主機變成是無狀態的。
例如你另外用一台主機專門放資料庫,或是乾脆直接用 Cloud SQL。
讓你所有的主機,都往外部存取資料庫,主機就不存放任何資料了。
除了資料庫以外,你的設定檔如果經常會變動,
或是有用戶會上傳檔案或圖片到主機上,
這些儲存位置,你都要用程式把儲存位置導向外部,
建議使用 Cloud Storage。
這代表你的系統架構要改,不可以把所有資料都放在同一台上了。
2. 建立映像檔、執行個體範本和執行個體群組
這些是什麼東西?
按照 GCP 的邏輯,你不能把現有主機直接到 Load Balancer,
Autoscaling 之所以能運作,
你要建立一個執行個體群組 (Instance Group;簡稱 IG),
因為 IG 在擴充的時候,必須要知道你的主機長什麼樣子。
所以 IG 要讀取你的執行個體範本 (Instance Template) 當中,
你所指定的映像檔 (Image),
執行個體範本也會記錄主機規格、要開在哪一個 Region 或 Zone、
哪一個 VPC 網路、Subnet、Disk 用哪一種、
對外開放的 Port 要 HTTP 或 HTTPS、要不要有外部 IP 等。
而映像檔可以想像成是燒光碟片的概念,
針對你準備好的機器的開機磁碟 (Boot Disk) 燒成光碟,
之後主機擴充都是拿這片光碟,安裝到每一台新的機器當中。
如下圖:

資料來源:自行繪製
所以總結起來,建立 GCP Load Balancer 主要步驟是這樣:
1. 對你的主機建立映像檔
2. 建立執行個體範本,指向你的映像檔
3. 建立執行個體群組,使用你的執行個體範本
4. 建立負載平衡器,連接到你的執行個體群組
5. 設定 DNS 網域解析到你 LB 的 IP 位址
接下來就介紹整個流程的詳細步驟。
二、建立 Load Balancer 的整體架構和步驟
這裡就假設你已經準備好一台「無狀態的」機器,在上面已架設好 Apache 的網頁,如下範例:

截圖自 GCP Console
你會看到我的網頁是 HTTP,沒有 SSL 憑證的狀態,這個不用擔心,
因為我會把 SSL 憑證做在 LB 的前端上面,
而流量進入到 VM,就可以不用再做 HTTPS。
沒問題的話就開始後續的動作。
(一) 建立映像檔
首先我們先把 VM 關機,然後去 Image 的頁面。
為什麼要關機呢?因為開機時 VM 還是會有對 Disk 的讀寫,
這時建立 Image 可能會有讀寫不完全的問題,
所以關機再建 Image 比較好。

截圖自 GCP Console
在命名的部分,建議加上版本號碼,
因為以後如果你的網站要改版,你會建很多個 Image,
為了方便管理,你可以使用一套命名規則來給 Image 命名。
然後指向我們剛建立的主機的 Boot Disk。
而 Location 的部分,如果你的 Image 非常重要,
建議選 Multi-Regional,
像我只是為了 Demo 就選 Regional 即可,沒問題就按下 Create。
另外因為 Google 會把所有 VM 的公開 Image
(如 Debian、Ubuntu…) 都放在同一個頁面,
所以你很難找到你剛建立的映像檔,你可以把 Project ID 複製起來,
貼到 Filter,指定欄位 Created By,再貼上 Project ID,按下 Enter,
就能快速找到你建好的 Image 如下:

截圖自 GCP Console
(二) 建立執行個體範本,指向你的映像檔
點擊 Compute Engine => Intance Template。

截圖自 GCP Console
在命名的部分,就依照你的命名原則來設定,
例如也加上版本號碼,跟 Image 對齊。
Location 指的是,你的 Template 要存在哪裡?
Template 只是一個小小的設定檔,
不是真的機器,也不會佔儲存費用。
它提醒的是,如果你存在 Global,
有可能你要用的時候,剛好別的 Region 壞掉了,
那你取得 Template 的時間會比較長,
因為要等它從其他 Region 拿過來,所以建議你選 Regional。
但如果選只台灣 Region (asia-east1) ,
萬一台灣的壞掉,就拿不到 Template 也是很麻煩,
那這樣不是選 Global 比較好?
其實不管選哪個,實際上 Template 拿不到的機率很低,
所以選哪個都可以。

截圖自 GCP Console
接下來選擇規格,我是為了 Demo 而選擇最便宜的 f1-micro。

截圖自 GCP Console
接下來 Placement Policy 的部分,是在問你在同一個 Zone (機房) 裡,
主機要不要集中在同一台實體機上。

截圖自 GCP Console
這裡分成兩種:
1. No Policy
主機「可能」會放在不同的實體機上,
因為 GCP 會因應客戶持續不斷的開機需求,
去分配機器開在哪裡,如果不指定,
主機有可能會開在同一台實體機上,
那實體機有問題,上面的主機會同時無法運作,算是風險比較高的。
2. Spread
主機「一定」會放在不同的實體機上,
這樣就不會因為某台實體機的問題,
讓你的主機同時不能運作,比較保險,那我們就選 Spread。
接下來是最重要的 Boot Disk,要指向你建立的 Image
在這裡你可以選擇用哪種 Disk,以及它的大小。
但要注意,Instance Template 是建立完成後,就不能再回來改的,
如果你設定錯誤,就必須要重新建立 Template,
所以這邊要小心設定。

截圖自 GCP Console
接下來是 Identity and API access 就照你原本 VM 的設定,
如果你原本就沒有調整,那就保持預設即可。

截圖自 GCP Console
在 Firewall 的部分,請同時把下方 Advanced options 和 Networking 展開。
在這裡,HTTP 和 HTTPS 是完全對外開放的,不限任何的 IP 來源。
但我們的主機只要允許 Load Balancer 的流量進來就好了,所以這邊不要打勾。
那下面還有一個 Allow Load Balancer Health Checks 是不是應該勾起來?
它是要幫你檢查主機是否健康的機制,它的流量會從特定的網段過來,
這裡勾起來就會自動允許那個來檢查的網段 35.191.0.0/16 和 130.211.0.0/22。
但是我建議不要勾。
我的做法是,你一定要設定專屬的網路標記 (Network Tag),
這樣你未來才方便調整套用到 IG 的防火牆規則,你想開什麼協定、哪一個 Port、從什麼網段,
你都可以在防火牆規則的頁面自由調整,例如我在這裡設定 apache-1,
我如果要調整防火牆,我就在相關的防火牆規則加上 “apache-1” 這個標記就好了,
因為你的 Template 是完全不能修改的,
防火牆設錯就必須刪除重建,毫無任何彈性,
還不如只設定專屬的網路標記,未來防火牆想怎麼改就怎麼改,方便很多!
後面設定防火牆的部分會再詳細說明。

截圖自 GCP Console
在 Networking 下方的 Network Interfaces 部分,
這邊看你是否要部署到特定的 VPC 或 Subnet ,再視情況調整,
重要的是 IP 要改成 None,為什麼不要 IP 呢?
因為 Load Balancer 會用一個 IP 專門對外服務,
所以你不需要給 Instance Group 的機器再分配外部 IP,
不然會變成,你已經有 LB 的 IP 對外,同時你的每一台主機也都有外部 IP,
這樣有人就可以繞過 LB 直接到達你的主機,是有資安疑慮的。
所以請把外部 IP 設為 None,沒問題的話再按下 Done。

截圖自 GCP Console
這裡小小補充一下,針對上述 Instance Template 的建立,
你也可以在 Management 的 Automation 當中,
使用開機指令碼 (Startup-Scripts) 設定到執行個體範本,不用 Image。
每當 IG 擴充機器時,機器會自動執行 Startup-Scripts 的指令,
自動連線到某個地方安裝應用程式或抓取程式碼。
不過每次開機器時,你必須要等它花時間抓到相關檔案,
並且安裝設定完成,才能對外服務。
萬一它連線或安裝異常,你還要「趕快」人工連進去除錯,
是「每一台擴充出來的機器」都要除錯,
因為 Load Balancer 要送流量進來了,
你不趕快調整,新的用戶就會進到有問題的機器,
反而導致你可能會手忙腳亂。
所以還是建議直接使用都安裝設定完成的 Image,
是比較好的選擇,這裡我們就不做任何設定。

截圖自 GCP Console
至於其他的進階選項,看你有沒有特殊需求,再調整即可,
不然就保持預設,點擊最下面的 Create,就建立完成了。

截圖自 GCP Console
(三) 建立執行個體群組,使用你的執行個體範本
進入執行個體群組頁面後,選擇無狀態的 (Stateless),
然後選擇你的 Instance Template。

截圖自 GCP Console
Location 請選擇 Multiple Zones,因為你既然要 Autoscale,
就是想提高可用性,
你不會把所有機器都集到同一個機房 (Zone),
在這裡你就應該選擇 Multiple Zones,
讓機器橫跨 A、B、C 三個 Zone,萬一有個 Zone 無法連線,
其他 Zone 的主機還是可以對外服務。

截圖自 GCP Console
接下來的 Target Distribution Shape 指的是,
你的機器如何分配到這些 Zone,
在可用的選項中,包含 Even 和 Balanced 兩種:
(1) Even
指的是 IG 會 100% 做到機器都平均分散三個 Zone 中,
使命必達的概念。
(2) Balanced
指的是 IG 會「儘量」做到機器都平均分散三個 Zone 中。
為什麼說「儘量」?
因為它會考慮每個 Zone 的資源可用性,
例如 CPU、記憶體和 Disk 是否足夠,
以及其他資源包含配額、硬體、成本等,
然後把機器開在相對足夠的 Zone,
所以和 Even 比起來,「比較不平均」,
但保留了一點開機器的彈性。
像是台灣 Region asia-east-1 的 Zone B,因為是預設選項,
所以經常機器被開滿,所以選擇 Balanced 是比較好的選項。

截圖自 GCP Console
至於 Allow Instance Redistribution 是什麼意思?
指的是你的主機會被 IG 主動重新分配,
就是它會自動從機器多的 Zone 刪除機器,
再增加到機器少的 Zone。
假設你有 12 台機器分布在A、B、C 三個 Zone,每個 Zone 4台。
如果你不小心刪掉了 Zone C 的 3 台,IG 會這樣調整:
(1) 從 Zone A 和 Zone B 各刪掉1台
(2) 在 Zonce C 新增 2 台
(3) 這樣每個 Zone 就又都是3台了,達到平衡。
要注意你只是刪掉 3 台機器,它又主動多刪掉你 2 台,整體運作能力會暫時下降。
因為你的機器並沒有異常,就這樣突然被刪掉,
再去另一個 Zone 開起來,反而讓你的系統不穩。
所以當你在 Target Distribution Shape 選擇 Even 時,為了保持平均,
它才會問你要不要勾 Allow Instance Redistribution,
當然我建議不用勾選,確保系統穩定比較重要。
如果你選 Balanced,預設就不會再給你選擇 Redistribution 了。

截圖自 GCP 官方文件
接下來是 Autoscaling Mode,它問你三種模式要選擇哪一種?
(1) On:自動增加也自動縮減機器
(2) Sacle out:自動增加機器,但不自動縮減
(3) Off:不要擴充也不要縮減
選 (1) 的話,流量增加會增加機器,流量減少會自動減少機器,
我們可以理解除了增加可用性,也是為了節省成本。
選 (2) 則是為了穩定性考量,怕下次流量突然爆增,
所以機器寧可增加也不要縮減。
那選 (3) 是為了什麼?
一方面是成本考量,不要多開機器,另一方面,如果機器有問題,
IG 會自動刪掉它然後重建,就是你的服務不管碰到什麼問題,
它都會一直復活,至少你不用人工進去處理,
還是節省不少你維護的時間。
所以三個選項各有考量,我們在這裡就選擇 (1),自動增加和縮減機器。

截圖自 GCP Console
Minimum/Maximum number of instances 就是你整個 IG 機器數量的上下限,我們就先設定1~3 台。

截圖自 GCP Console
Autoscaling signals 指的是觸發你擴充機器的時機,有 4 種 Signal Type 可以選擇:
(1) CPU Utilization
指的是 IG 裡所有機器的 CPU 使用率,是最基本的選項。
(2) HTTP Load Balancing Utilization
指的是 LB 的使用率,它並不是特定的效能指標,
它包含 CPU、網路流量、HTTP Session 數量、每秒請求數 (RPS) 和 Disk I/O,
由 GCP 綜合考量所計算出來的指標,
所以不會只偏重單一指標,是從整體角度來看。
(3) Cloud Pub/Sub Queue
這部分和資料處理管道 (Pileline) 有關,
例如你的主機是拿來做串流資料 (Streaming Data) 處理的,
前端資料來源都從 Load Balancer 進來,
然後分散給不同的機器來處理,
這裡就是確認每台機器收到多少消息,包含還沒處理完的訊息,
因為前端的資料量可能時大時小,
如果累積的訊息太多,機器會來不及處理,
就可使用這個指標讓它自動擴充機器來幫忙處理。
(4) Cloud Monitoring Metric
指的就是 Cloud Monitoring 的指標,都可以拿來判斷是否要擴充機器,
以前只能用 CPU 來判斷,但有些機器可能是記憶容易飆高,
這樣用 CPU 判斷就不夠精準,
你就可以選擇其他指標例如記憶體使用率 (Memory Usage),
或進來的網路流量 (Ingress Bytes) 等等。
如果你只是在測試,想要讓 Autoscale 馬上發生,可以直接調成 5%,
在此我們就先使用預設的 CPU Utilization 60%。

截圖自 GCP Console
Predictive Autoscaling 指的是透過預測來提早擴充,
它會依照你過去主機擴充的指標,
例如上面設定的 CPU 使用率,我們原本設定 60% 才擴充,
它可能 CPU 到 58% 的時候,就預測可能要超過 60% 了,
於是提前擴充機器。
這樣的好處是,你原本的機器就不會因為新的還沒擴充出來,
自己在那邊獨撐大局,造成機器不穩定的狀況。
不過它需要你的歷史資料,用來建立機器學習的模型,才方便預測。
所以你的服務至少要開 3 天以上,才有足夠資料讓它可以訓練。
在這裡我們就選擇 Off 即可,這段沒問題就可按下 Done。

截圖自 GCP Console
Autoscaling Schedules 是依照時間來自動擴充的功能,
如果你能確定流量較大的時間,
例如每天晚上八點到十點,你就可以設定此功能。
但我們現在是依照 CPU 來決定是否擴充,
這兩個功能是互斥的,所以就不能再設定它。
如下圖它呈現反灰的狀態。

截圖自 GCP Console
Initialization period 指的是新的機器擴充要等它多久,
每一台新擴充的機器,都是需要跑一遍開機過程的,
所以要預留時間等它開好。
因為開機時,機器是很忙的,CPU 一定都會飆非常高,
像我今天的 custom-vm 剛開機時,CPU 已經飆到 93%。

截圖自 GCP Console
如果這個值設太短,例如 5 秒鐘,那新的機器還在開機當中,
CPU 還是很高,追成 IG 誤判它 CPU 飆高,
所以當場又決定再擴充一台新的。
代表你新的機器還沒開好,又再開新的,
如果每一台都要開機很久,它就一直開新到直到上限開好開滿。
但是如果你時間設太長,你又要等很久才能確認總體的負載,
萬一用戶流量突然爆增,你的擴充又會來不及。
所以針對這種情況,你需要測試你的主機,從開機到準備對外服務,
差不多要多久,越精準越好,才能兼顧擴充速度並減少誤判。
在這裡我們也依照預設的 60 秒即可。

截圖自 GCP Console
Scale-in controls 就是反過來,關於機器縮減的速度控制,
你的用戶流量突然降下來,但沒多久又飆上去,
這時如果機器自動縮減了,會來不及再次擴充出來應付流量。
這裡就是為了防止機器太快縮減,設定的緩衝時間,
例如我們設定 10 分鐘內不要刪除超過 1 台機器,或 50% 的機器。

截圖自 GCP Console
VM instance Lifecycle 指的是設定主機有狀況的時候,要做哪些反應。
Default Action On Failure 指的是因為我們已經設定要 Autoscale 了,
所以主機有問題 (Fail) 的話,它固定就是會 Repair Instance。
要注意字面上是「修復」,實際上它就是把機器刪掉,再重新建立。
它沒有那麼好會去幫你 Debug 啦 XD!

截圖自 GCP Console
在 Autohealing 的部分,承上提到的 Fail,
GCP 是用它自己的標準來判斷是否 Fail。
我們通常是透過「健康狀態檢查」(Health Check) ,
明確地判斷它「健康」或「不健康」,
再決定要不要「修復」你的主機,
如果你之前還沒建立過 Health Check,可以在這裡點擊建立。

截圖自 GCP Console
當我們進入 Health Check 之後,首先給它命名。
在 Scope 部分,是依照 Load Balancer 的屬性來決定的,
我們後續是要建立 Global 的 LB,所以我們在這裡也選 Global。
而 Protocol 部分,因為我們是網頁,你可以選擇 HTTP 或 TCP,
但我們「一定要」選 HTTP,
因為它能夠檢查你的網頁回應碼是不是 “200 OK”。
如果你選 TCP,那網頁可能是 404 Error,
而檢查結果仍然是「健康」,那就是誤判,所以千萬不要選錯。
至於 Logs 的部分,就是記錄檢查成功或失敗的 Log,
你可以視情況決定要不要勾,在這裡我就勾起來。

截圖自 GCP Console
Health Criteria 就是你的判斷基準,怎樣叫健康,怎樣叫不健康。
例如預設值提到的,每 5 秒鐘檢查一次你的網頁,
然後等 5 秒鐘看有沒有回應 “200 OK”,
如果連續兩次都回應 “200 OK”,則視為「健康」;
如果連續兩次都不回應 “200 OK”,則視為「不健康」;
那如果介於兩者之間呢?
那就是繼續等它檢查結果,直到確定是否健康為止。
如果沒問題就可按下 Save。
Updates During VM Instance Repair 指的是我們的應用程式會改版,
在 IG 上就是會更換 Instance Template,
這裡是問要不要趁主機因為異常而重建的時候,順便開新版的機器。
你可以 Keep the same instance configuration 保持舊版,
或是 Update the instance configuration 順便換新版。
這要取決於你的 CI/CD 版本控管政策來決定。
在這裡我們只有一個版本,所以保持預設值即可。

截圖自 GCP Console
Port mapping 是設定 Load Balancer 進來的時候,是經過哪一個 Port,
你可以先給它取個名字,或是設定 LB 的時候再設定也可以。
我們就先設定 Name 為 http,Port 設定為 80。
如果沒問題,就可以按下 Create 了。

截圖自 GCP Console
接下來它會切到 Instance Group 的畫面如下:

截圖自 GCP Console
我們再點進去,你會看到它目前顯示 0% Healthy。
不要懷疑,這是正常的!
因為防火牆還沒開放 Health Check 的網段來存取主機的網頁。

截圖自 GCP Console
我們可以再點右邊的 Errors,查看錯誤訊息。
如果你不知道為什麼它顯示不建康,都可以從這裡查到。

截圖自 GCP Console
另一方面,我們也可以去 Cloud Logging 查看,
點擊 Instance Group,
你會看到因為 IG 檢查不到主機,所以視為「不健康」,
觸發它刪掉原有的主機,然後再重建,
結果又檢查不健康,再次刪除重建……。

截圖自 GCP Console
我們把 “healthCheckProbeResult” 這個 Log 展開,
會看到它的檢查結果,上面有註明是從哪裡來檢查的,
以及它去訪問哪一個 IP。

截圖自 GCP Console
接下來,我們就去設定防火牆,讓 Health Check 可以找到主機。
注意我們是點擊「防火牆規則」,不是「防火牆政策」喔!!
從 VPC Network => Firewall 進去防火牆設定頁面:

截圖自 GCP Console
命名通常是越清楚越好,例如命名為 “detault-allow-health-check-http”,
其中 “detault” 是每個 Project 裡第一個 VPC 的名字。
Log 可以打開,你可以確認每一次檢查主機的結果。
順序就保持預設的 1000,方向是 Ingress,
代表進入某台主機,動作就是 Allow。

截圖自 GCP Console
Target Tag 是關鍵,我們在這裡要設定跟 Instance Template 一模一樣的 Tag,
這樣規則就可以套用到這個 IG 所有主機了。
接下來設定 Health Check 的來源網段為 35.191.0.0/16 和 130.211.0.0/22。

截圖自 GCP Console
Health Check 要檢查的 Port 是 80,所以這裡就設 80,
其他 Port 不用開,然後按下 Create。

截圖自 GCP Console
防火牆生效的速度很快,過沒多久,
IG 的檢查狀態就變成 Healthy 了。

截圖自 GCP Console
我們也去 Log 看一下,它也顯示為 Healthy。

截圖自 GCP Console
我們也可以去 Compute Engine 頁面,IG 開的機器也會列在這裡,
你可以看到它的命名規則是 “IG 的名字 + 隨機英數4碼”,
如果到時有 Autoscale ,產生新機器的話,
也是用這樣的方式命名的。

截圖自 GCP Console
(四) 建立負載平衡器,接到你的執行個體群組
1. 設定精靈
我們就直接從 Network Services 進入 Load Balancing,點擊建立 LB。

截圖自 GCP Console
它會先問你,要用 Application Load Balancer 或是 Network Load Balancer,
你只要是網站使用 HTTP 或 HTTPS 協定的就用 ALB,其他協定或 Port 就選 NLB。

截圖自 GCP Console
第二個問題也很簡單,你的網站是對外就選 Public,如果是對內就選 Internal。
會有 Internal 嗎?有的,如果你的系統架構有拆前端 Web 主機和 AP 主機的話,
那 Web 主機可設定為 Public,AP 主機可設為 Internal,
這樣 AP 主機就不會直接對外,提高安全性。

截圖自 GCP Console
再來是你的服務對向是全球的,還是只針對特定區域,例如只有台灣?
如果你有國外的巿場,你可以將主機同時部署在多個 Region,
這樣 LB 可以依照用戶所在的位置,就近轉發到最近的主機,快速回應用戶。
在這個範例裡選哪一個都可以,在這裡我們就選 Global。

截圖自 GCP Console
在這裡我們要選 Global External ALB 或 Classic ALB,但兩者界面其實差不多,
只是 Global External ALB 有強調進階流量管理,可以寫語法來做到更複雜的功能,
例如依照封包標頭導向不同機器 (Header-Based Routing)、
依照權重分流 (Weight-Based Splitting) 等等。
在這個範例裡選哪一個都可以,也沒有價格差異,
我們就選 Global External ALB。

截圖自 GCP Console
接下來再次確認你的選擇有沒有錯誤,沒有就按 Congifure,開始設定 LB 的細節。

截圖自 GCP Console
2. 前端 (Front End) 設定 (包含 IP 和 SSL 憑證)
現在進入前端設定的部分,左邊給 LB 命名 “lb-1”,右邊則是對前端命名 “fe-1”,
在 Protocol 部分,我們原本的網站是 HTTP 的,因為我們要把 SSL 憑證做在 LB 上,
讓 LB 來處理 SSL 加密,所以這裡務必選擇 HTTPS。
PS. 假如你現在還沒有自己的 DNS 網域,
而且只是為了練習的話,請選擇 HTTP 就好。

截圖自 GCP Console
IP 也務必要固定下來,所以我們把 “Ephemeral” 改成 “Create IP Address”。

截圖自 GCP Console
然後我們給 IP 取名字,例如 “lb-ip”, Google 會從它的 IP Pool 中挑選一個發配出來。

截圖自 GCP Console
再來就是 SSL 憑證,我們點擊 “Create A New Certificate”。

截圖自 GCP Console
它會轉到建立憑證的視窗,我們先給憑證命名 “cert-web1”,
在建立模式檔中,如果你自己有另外購買憑證,
可以直接上傳,但憑證的展期你要自己再次上傳。
如果你用 Google 的憑證,就可以自動展期,一勞永逸。
下方要設定你的網域,在這個範例中,
我們使用 “web1.dongdonggcp.com”,然後按下 “Create”。
PS.不要輸入跟我一樣的網域喔!如果你自己沒有網域,記得前面的通訊協定選擇 HTTP 就好,
因為它後面會要求你驗證 DNS 的 TXT Record。

截圖自 GCP Console
回到原本前端的頁面,這時我們勾選 “HTTP to HTTPS Redirect”,
代表如果有人在瀏覽器輸入 “http://web1.dongdonggcp.com 的話”,
它可以自動導向 “https://web1.dongdonggcp.com”。
如果沒勾,它會打不開網頁喔!
因為兩者本來就是不同的 Port (連接埠),就像不同的碼頭,
你停錯碼頭就找不到店家,網頁就進不去。
其實像 Open Source 的 Web Server 例如 Apache、Nginx 或 IIS,
很久以前就已經有這個功能了,
而 GCP 的 LB 後來也在用戶的建議之下,
做到可以一鍵勾選,提高了方便性,設定好之後就按下 Done。

截圖自 GCP Console
它回會到 LB 的主畫面,接下來我們按下 “Beckend Configuration” 進行後端的設定。
注意這裡的「後端」是從 LB 的角度,指的是要迎接流量進來的主機群,
而不是後端 AP 主機或資料庫的意思。

截圖自 GCP Console
3. 後端設定 (包含 Cloud CDN 和 Cloud Armor)
我們展開下拉式選單,點擊 “Create A Backend Service”。

截圖自 GCP Console
它會跳出建立「後端服務」的視窗,注意一個「後端服務」,可以接多個「後端」,
「後端服務」指的是 LB 的組成部分,「後端」則是連接的 IG,這裡不要混淆喔!
在通訊協定的部分,我們原始主機就是用 HTTP,所以就選 HTTP,
注意這裡很容易選錯,選錯就不會通喔!

截圖自 GCP Console
接下來設定「後端」,我們選擇我們建好的 IG 名稱 “apache-ig-1”,
你會看到它自動帶入 Port 80,這是我們在建立 IG 時就預先設定好的。

截圖自 GCP Console
接下來是設定平衡模式,就是 LB 要怎麼分流的意思。
你可能會想,LB 不是平均分配流量到不同機器嗎?
為什麼還要設定如何分流?
要注意,同一個 IG 裡面的機器,是可以平均分配的,
這裡提到的是「不同 IG 之間的分流」,
它是說如果第一個 IG 已經達到最大利用率 (Utilization) 之後,
會再把流量送到第二個 IG,所以不同 IG 之間,收到的流量可能會不同。
而在這個範例當中,我們只有一個 IG,所以不需要特別設定,保持預設即可。
沒問題就按下 “Done”。

截圖自 GCP Console
接下來進入 Cloud CDN 的部分,我們就直接勾選 “Enable Cloud CDN”。
在 Cache Mode (快取模式) 的部分,通常我們選 “Cache Static Content” 即可,
而首頁經常會變動,所以這個選項並不會 Cache 首頁,
但我們在這個範例只有首頁這張網頁,為了要示範 Cloud CDN 的效果,
所以故意去選 “Force Cache All Content”,
這樣我們到時候就可以看到首頁被 Cache 的樣子。
下面的 Client TTL 是指內容在用戶端瀏覽器存留的時間,
瀏覽器會記錄某個內容已經存在多久,
如果超過某個時間,例如一個小時,
它就會再次向 Cloud CDN 確認內容有沒有更新,
如果有更新,就會重新抓取,
如果沒更新,瀏覽器就會再使用原來的內容。
Default TTL,指的是內容放在 Cloud CDN 上存留的時間,
如果超過某個時間,例如一個小時,
它就會再次向原本的主機確認內容有沒有更新。
在這裡我們都保持預設即可。

截圖自 GCP Console
再往下又出現一個 Health Check,
這跟我們在 IG 設定的 Health Check 有什麼不同?
這裡是要給 LB 判斷,這個後端的 IG 整體是否健康,
健康的話,才會送流量過來。
原本 IG 的 Health Check 是看主機是否健康,
不健康就會刪除重建機器。
所以同一個 Health Check,但在不同地方,發揮的效果是不同的喔!

截圖自 GCP Console
再往下問你要不要啟動 Logging 功能,
這裡是指後端服務,有被存取的話都會記錄。
它還提供 Sample Rate (取樣率),因為 Log 量可能會很大,
如果每一筆都記,資料量太大也會花很多錢,
所以它貼心地讓你設定 0~1 之間的數值,
例如 0.1 代表每 10 筆記錄 1 筆,就可以節省成本。
在這個範例只是要測試它的效果,所以我們還是設為 1。

截圖自 GCP Console
接下來這邊你可能看不出來,這是在設定什麼功能?
這其實就是 Cloud Armor,它預設就自動帶入 “Default Security Policy”,
這個 Policy 的詳細內容就是下方的 “Name” 和 “Throttle Action Settings”,
就是節流閥的意思。
預設是說, 如果一分鐘之內,
每一個 IP 如果有超過 500 個 Request 進來,超過的部分就禁存存取。
我們在這個範例想要測試它的效果,所以就乾脆不要設定 “IP Address” 了,
我們改成 “ALL”,代表不分 IP,只要整個後端服務在一分鐘之內,
只超過 500 個 Request 就開始拒絕。
接著我按下 Create。

截圖自 GCP Console
這樣我們 LB 後端就設定好了,接下來進入 Routing Rules。

截圖自 GCP Console
4.分流規則
因為我們只有一個前端和一個後端服務,
從頭到尾只有一條路,所以不用再做任何設定。
如果你有多個後端,例如有 web1.dongdonggcp.com 和 web2.dongdonggcp.com,
那我們就可以設定 LB,讓它依照用戶輸入的網址,
流向不同的後端主機。
在這裡我們可以直接點擊 “Review And Finalize”。

截圖自 GCP Console
我們可以在這裡給 LB 做最終檢查,看看有沒有設定錯誤的地方,
比較重要的地方例如:前端是 HTTP 或 HTTPS、憑證是否有設定好,
以及後端 IG 是否正確、是否使用正確的 Port 等等。
因為設錯要再改會很花時間,所以建議多看一下,沒問題我們就按下 “Create”。

截圖自 GCP Console
在等待建立過程當中,你會看到它正在轉圈圈,
大約 2 分鐘就會建立完成,但實際上還沒全部完成喔,後面還有一些步驟。

截圖自 GCP Console
現在我們看到兩個 LB 顯示為綠色勾勾,
除了我們設定的 “lb-1”,還有一個叫 “fe-1-redirect”,
就是幫我們把 HTTP 轉發到 HTTPS 的功能。
我們可以點擊 “lb-1” 進去看看。

截圖自 GCP Console
你會看到我們剛設定好的憑證,再點進去會看到 “Provisioning” 的狀態,
再往下查看網域,顯示為 “Failed_Not_Visible” 的狀態,
因為你如果使用 GCP 的免費憑證,它會要求你的網域必須解析到 LB 的 IP。
如果沒有就會呈現這個狀態,直到你去設定 DNS,讓它解析成功為止。

截圖自 GCP Console
5.設定 DNS 網域解析到你 LB 的 IP 位址
DNS 的設定界面不一定在 GCP 上喔,
這裡指的是你註冊 DNS (購買網域) 的地方,
你可能用的是 Hinet 的 DNS,或是國外的 GoDaddy 或 Namecheap 等等。
像我是在 GoDaddy 註冊 DNS 的,但是我已經轉移管理權限到 Cloud DNS 了。
我就直接從 Cloud DNS 點擊進入我的網域。

截圖自 GCP Console
在 DNS Name 的部分,輸入子網域就好了,例如 “web1”。
而 Resource Record Type,我們是要指向主機的 IP 位址,
選擇 A Record,其他保持預設。
下方則是輸入 LB 的 IP 位址,按下 Create。

截圖自 GCP Console
三、檢查 Load Balancer 各項設定
(一) SSL 憑證
當我們設定好 DNS,需要一點時間等它生效,
我們可以用 Google Admin Toolbox 檢查,
這是一個免費的工具,任何人都可以直接使用。
我們直接點擊 “Dig”。

截圖自 Google Admin Toolbox
接下來直接在 “名稱” 裡輸入網域,然後點擊 “A”,
它就會解析這個網域是否指向某個 IP 位址,
像我在輸入之後,它就解析到 LB 的 IP 位址,代表 DNS 已經生效了。

截圖自 GCP Console
我們再回去看憑證的狀態,
因為 Google 也確認我的網域有解析到正確的 IP 位址,
所以 SSL 憑證就變成 “Active” 的狀態。
你會看到它的到期日是 2024/12/1,但是不用擔心,等到那一天,
憑證會再自動展期,我們什麼事情都不用做。

截圖自 GCP Console
最後我們就可以在瀏覽器輸入網址,會看到網頁終於顯示出來了。

截圖自 GCP Console
我們可以再點擊網址左邊的圖示,再點擊「已建立安全連線」,
會展開安全性的頁面,看到「憑證有效」,
再點擊下去,就會看到完整的憑證資訊。
其中 Google Trust Services 就是 Google 成立的根憑證授權單位,
代表 Google 背書證明憑證是有效的。

截圖自 GCP Console
還可以再點擊詳細資訊,然後點「序號」,可以看到「欄位值」顯示序號。
這裡可以確認這個憑證,和我們在 LB 上憑證頁面的序號一模一樣,
證明這真的是我剛建立的憑證。

截圖自 GCP Console
(二) Cloud CDN
因為我們在後端還有勾選 Cloud CDN,
我們可以在 Chrome 瀏覽器最右邊點擊三個小點,
再點擊「更多工具」=>「開發人員工具」,來測試 CDN 的效果。

截圖自 GCP Console
你會看到右邊顯示一堆按鈕,這時我們再重新整理網頁。

截圖自 GCP Console
你會看到右邊的圖表區域產生變化,
我們再點擊 Network => Index.html => Headers 會看到詳細訊息,
例如 Status Code 為 “304 Not Modified”,平常我們看到應該是 “200 OK”,
304 則代表 Index.html 這個網頁已經被 Cloud CDN 暫存,
瀏覽器確認內容是一樣的,沒有更新,
所以就會繼續使用本機的版本。
再往下看 Cache-Control 的部分,看到 “max-age=3600”,
表示這個內容會在瀏覽器存在一個小時,
跟我們在 Cloud CDN 設定的 Client TTL 長度是相同的。

截圖自 GCP Console
我們也可以從 Cloud Logging 來看,點擊 “Application Load Balancer”,
然後展開狀態為 304 的 Log,可以看到一些關於 Cloud CDN 的內容,
例如 “CacheLookup: True” 代表 CDN 有查詢該內容是否在 CDN 節點上,
只代表有執行”查詢”動作。
而 “CacheHit: True” 則代表找到了,俗稱「快取命中」。
最下方還能看到 “StatusDetails: “Response_From_Cache””,
代表內容是從 CDN 節點回覆的。
由此可證明我們的 Cloud CDN 有設定正確,讓它能夠有效運作。
(三) Cloud Armor
我們直接使用 Cloud Shell 來做為發送流量的機器,
點擊右上角的圖示:

截圖自 GCP Console
待 Cloud Shell 視窗開啟完成後,輸入以下指令,更新套件位置,
這樣才能讓它從最新的位置自動下載並安裝軟體。
sudo apt-get update

截圖自 GCP Console
接下來安裝壓力測試軟體 Siege:
sudo apt-get install siege

截圖自 GCP Console
我們在前面後端設定中,是設定每分鐘超過 500 的 Request,超求就禁止存取。
所以我們故意設定發出 550 個 Request,讓它超過 500 次,指令如下:
siege -c 5 -r 110 https://web1.dongdonggcp.com/
c 代表同時執行多少個執行緒。
r 代表每個執行緒發出的請求。
兩者相乘總共 550 次。
由於次數不高,差不多 4 秒左右就已送出 550 個 Request 了。

截圖自 GCP Console
然後我們去看 Cloud Armor,也看到它有一個 Policy 在運作,
而且已經套用到 “bk-1” 這個後端。
接著我們再點擊 Policy 名稱:

截圖自 GCP Console
進去後看到 Logs 的頁籤,點擊該頁籤,再點擊 “View Policy Logs”:

截圖自 GCP Console
你會看到它開打 Cloud Logging 的畫面,
並且自動套用查詢和 Cloud Armor Policy 有關的 Log 語法,
看到 ALB 總共收到 550 次 Request,
其中 507 次是正確的,而另外 43 次則有 403 錯誤。

截圖自 GCP Console
我們再點開其中一筆 Log,
看到 Request 被 Cloud Armor 擋住,
它在 “EnforcedSecurityPolicy” 有相關細節,
說明現在已經觸發 “Throttle” 節流動作,
動作執行的結果是 “DENY” 拒絕 Request。
代表 Cloud Armor 的設定是有生效的,
對於超過上限的 Request 有執行阻擋動作。

截圖自 GCP Console
(四) Autoscale 功能
最後我們要確認最重要的功能,
到底 Autoscale 能不能如期擴充機器。
我們這次就不設上限,每秒 250 個 Request,
一直打到它長出新的機器為止:
siege -c 250 https://web1.dongdonggcp.com/

截圖自 GCP Console
執行之後,游標會不見,是正確的,表示現在正在發送流量。
我們可以直接去 IG 的頁面觀查,點擊 IG 的名字。

截圖自 GCP Console
我們看到 IG 一直保持在 1 台機器,
因為 CPU 使用率一直到不了 60%,大概只有 18% 左右。
所以沒有觸發 Autoscale。

截圖自 GCP Console
那我們就直接點擊 IG 的 “Edit”,
把 “Target CPU Utilization” 從 60% 改成 5%,再按下 “Save”。
讓它的 CPU 只要有一點負載,就輕易觸發 Autoscale。

截圖自 GCP Console
然後我們再持續觀察,就看到它直接從一台機器,
一口氣長到三台機器。
而每一台機器的 CPU 使用率其實沒有很高,約 18% 左右,
因為已經超過 5% 所以就觸發了 Autoscale,
三台機器的加總 CPU 使用率為 54%,
而每台機器的 Capacity 是 5%,三台上限為 15%,
所以系統提示機器數量已經到達上限,
提示你要不要再增加更多機器。

截圖自 GCP Console
我們可以點擊 IG 的 “Overview” 看到有 IG 底下有三台機器,
或是去 “VM Instances” 也會看到相同的三台機器。

截圖自 GCP Console
所以我們已經確認成功觸發了 Autoscale,
那就回到 Cloud Shell 按下 “Ctrl + C” 停止 Siege,
它也提供相關統計資料,顯示總共發出了 25 萬次的 Request,
每個 Request 平均回應時間為 1.71 秒,算是比較慢的,
因為機器規格很小,而且打的次數又快,所以回應速度變慢許多。
然後它又說成功次數和 Request 總數一模一樣,
表示所有的 Request 都有被我們的網站接住。

截圖自 GCP Console
我們也看一下 Cloud Logging,可以看到總共收到的 Request 數量,
因為我在壓力測試之前也做過其他測試,所以數量比較多。

截圖自 GCP Console
所以整個測試就完成了。
最後我們這個範例,在整個 GCP 的 LB 架構如下,
其中藍色字代表我們建立好的各項服務所提供的功能:

資料來源:自行繪製
四、逐步刪除各項資源
接下來更重要的是,把服務照順序刪除。
不要放著讓它跑啊,整個架構都會計費的!
至於要刪除也是有順序的,順序錯是會卡住無法刪除的:
(一) 刪除 Load Balancer、憑證、後端
因為不能一次刪兩個 LB,所以先選 “lb-1” 來刪除,它會順便問你要不要把憑證跟後端都刪除。
憑證跟後端放著不會產生費用,憑證是有公信力的建議留著。
而後端則是必須要刪除,要不然 IG 會無法刪除。

截圖自 GCP Console
刪完記得再刪除負責把 HTTP 轉到 HTTPS 的 “fe-1-redirect”。

截圖自 GCP Console
(二) 刪除 Cloud Armor 的 Policy
當我們進入 Policy 的頁面應該會看到 Target 的數量為 0,
如果前面 LG 還沒刪掉,Target 數量就是 1,
那 Policy 是無法刪除的,再等 1~2 分鐘等它歸 0。
要注意這部分容易忘記,因為當初我們是在 LB 後端設定的,
根本沒來過 Cloud Armor 的頁面,所以非常容易忘記。

截圖自 GCP Console
(三) 釋放靜態 IP
因為 LB 刪除了,所以原本靜態的 IP 會變成閒置狀態,
要注意,IP 分配給 LB 使用時,IP 是免費的,
但如果閒置的話,它的費用會比在 VM 上使用還貴,
這也很容易忘記喔!
另外釋放 IP 的按鈕在最旁邊,要把視窗拉開才會看到。

截圖自 GCP Console
(四) 刪除 Instance Group
再來我們要刪除 IG 了,刪除之後務必確認它是否刪除成功。

截圖自 GCP Console
像是這個例子,我看到下面這個錯誤,”apache-ig-1” 這個 IG,
被相同名字的 Autoscaler 綁住,一直處於調整機器數量的狀態,所以無法刪除。

截圖自 GCP Console
因為 IG 的 CPU Capacity 之前調整到 5%,有點太低,
偏偏開關機這件事情,耗用的 CPU 太多,
所以讓 IG 一直不斷在開機又關機,變得無法刪除。
再改回 60%,讓 Autoscale 的門檻提高,不要再動不動就 Scale。

截圖自 GCP Console
後來設定好之後,IG 就成功刪除了。
(五) 刪除 Instance Template
Instance Template 不會產生任何費用,有需要留著也沒關係。

截圖自 GCP Console
(六) 刪除 Image
Image 是會佔用一點點空間的,但是沒多少費用,要刪不刪都可以。

截圖自 GCP Console
(七) 刪除原本用來做 Image 的主機和 Disk
機器沒開是不會計費的,但它的 Disk 還是會有費用,你可以看情況要不要刪。

截圖自 GCP Console
(八) 刪除 DNS 記錄
如果你是用 Hinet、GoDaddy 或 Namecheap,
DNS 記錄不會有額外費用,
如果是 Cloud DNS,有人持續在查詢網域的話,
會依照查詢次數計費,
不過查詢一百萬次才會有 0.4 美金,費用不高。
但 DNS 記錄留在那邊容易誤會,以為你還有主機是用這個網域,
為了管理的目的,還是建議刪乾淨比較好。

截圖自 GCP Console
五、結論
我們終於完成整個 Load Balacer 的建立過程,
你會發現整個架構運作起來,有非常多要考慮的地方,
除了 Instance Group 和 Instance Template 相關的前置作業要做,
還有 Google 的 SSL 憑證、Cloud CDN 和 Cloud Armor 功能,
要搭配 LB 才能運作。
前前後後有很多互相關聯的設定,
牽一髮而動全身,設錯要改還很麻煩,
務必要弄懂所有細節,或是多做幾次才能駕輕就熟。
當你整個做完一遍,你就算是掌握了 GCP 的核心功能 – Autoscale,
以後面對高流量的服務,就可以透過 LB 和 IG 的設定,
來打造一個高可用的雲端架構。
如果對於 LB 的原理還不了解,
可以參考《超越負載壓力,提升網站效能!為什麼 GCP Load Balancing 是你最佳的選擇?》這篇文章。
本文同時刊登於思想科技官網部落格文章 【東東老師 X 思想科技】如何替網站設定 GCP Load Balancer 確認架構規劃問題?與詳細設定步驟。