前面我們建立了 ECS cluster 跟 service,並且用一台 EC2 instance 作為 container instance 來執行 task,最後用 EC2 instance 的 public IP address 連到 Laravel。
等等,如果只是要這樣,直接開台 EC2 instance 把 web server、php、database 裝一裝就好了吧?幹麻搞得那麼複雜?
沒錯,前面先了解如何建立 ECS cluster 跟 service,接下來我們要讓 ECS service 可以執行多個 task,並且以 load balancer 進行負載平衡、將 request 分散到多個 container 上。這麼一來,只要連到 load balancer 就能連到我們的 application 了。
今天我們先來玩玩 load balancer~
load balancer 負責接收外部進來的流量,並將流量分配給不同的 target 處理。利用 load balancer 讓 loading 分散到多個 target 上,可以避免單一 target loading 過高造成反應慢等等問題,再配合 auto scaling 則能夠依據進入流量的大小跟 loading 等等增減後方 target 的數量。
AWS 的 load balancing 功能是 Elastic Load Balancing,它提供四種 load balancer:Application Load Balancers、Network Load Balancers、Gateway Load Balancers 以及 Classic Load Balancer。在 AWS 的產品比較表中有比較四種 load balancer 的特性及功能可以參考,我們要建立 Laravel 的 web service,會使用 application layer(layer 7)的 application load balancer(簡稱 ALB)。
我們先來了解一下 ALB 的主要元件跟結構~
ALB 由三個主要元件組成:
Load Balancer
Listener
Target Group
它們的結構如下圖,最外面是 Load Balancer 負責接收 request,接著 request 會經過 Listener 檢查並決定導到哪個 Target Group,最後由 Target Group 決定這個 request 要交給哪個 Target 來處理。Target 可以是在不同 AZ 的 EC2 instance,也可以是 container,就是個有能力處理 request 的東西。
(from Application Load Balancer components)
Target Group 也負責確保 Target 們都是正常的(healthy),它會對 target 們做 health check。如果有 target 沒有反應或者回應錯誤,這個 target 會變成 unhealthy,然後被移出 target group,避免有 request 被送到壞掉的 target 而無法有 response 回給 client。
有了大致概念後,我們一邊設定一邊進行更細的說明吧~(這樣比較有 fu 啦~)
要建立 ALB 至少要有兩個分別在不同 AZ 的 subnet,所以我們要在另一個 AZ 建立一個 public subnet。步驟跟前面一樣,要注意 subnet 的 IPv4 CIDR block 不能跟已有的 subnet 重疊,不確定 block 的 IP 範圍可以用 計算機 唷!
public subnet 之所以是 public 當然不是因為名字這麼叫,是因為它 associate 到的 route table 有通往 internet gateway 的 route,所以把新的 public associate 到對應的 route table:
先守護一下大家的荷包:ALB 是要收錢的,費用說明在這裡 (記得選對 region)。
Load Balancer 是 EC2 下的功能:
Create load balancer,load balancer type 當然選擇 Application Load Balancer 囉~
一樣給 ALB 一個名字。我們要可以從 internet 連進 web application,所以用 Internet-facing 的 schema。IP address 兩種都可以,這邊我們用 IPv4。
接著決定 ALB 在哪個 VPC 裡,並且可以把流量導到哪些 AZ 裡的 target。基於 high availability 的要求(不會一個 AZ 掛了導致 ALB 提供的 service 整個掛了),ALB 至少要設定兩個 AZ 而且每個 AZ 要有一個 subnet。選擇我們兩個 public subnet:
再來選擇套用在 ALB 上的 security group,也就是允許 ALB 有哪些 inbound / outbound network traffic。
我們要讓 ALB 可以透過 HTTP 來 access,所以有個 allow-http-from-internet
security group,它擁有 source 為 0.0.0.0/0
、TCP port 80 的 inbound rule——TCP port 80 接受來自所有地方的 inbound traffic。(如果沒有這個 security group 參考昨天的文章建立!)
往下到 Listeners and routing 區塊。ALB 收到的 request 會經過 Listener 判斷,決定送到哪個 target group。target group 是由一群可以處理 load balancer 送來的流量的 target 組成,裡面可能是一堆 EC2 instance、地端機器或者 lambda function 等等。
這邊我們要設定 listener 就必須要有 target group,我們從 Create target group 連結出去建立:
首先選擇 target type,target type 表示我們要 register 到 target group 裡的 target 的種類。我們預計要把流量導到跑在 EC2 instance 上的 container,所以 target type 用 Instances。
接下來一樣指定個名稱。
接著設定 target group 用來將 request 導到 target 的 protocol 與 port,像這裡設定 HTTP 與 port 80 表示 target group 會把 request 以 HTTP protocol 送到 target 的 port 80。這個 port 只是預設值,target register 進 target group 時可以修改使用的 port、以其他 port 來接收 request。
VPC 指定我們要作為 target 的 EC2 instance 所在的 VPC。最後是使用 HTTP 1 的 protocol version,如果有不同的 protocol version 需求要對應修改,這邊我們先用簡單的~
往下到 Health checks 區塊,health check 是 target group 確認 target 是否正常活著的機制。它每隔一段時間就會用指定的 protocol access 一下 (俗稱戳一下) health check path,如果得到正常 200 回應,就認為這個 target 是健康(healthy)、可以正常提供服務的。
我們在這裡直接指定 /
也就是 Laravel 的首頁:
下一步會到 Register targets,先不做任何設定直接 Create target group。
回到建立 ALB 按 Default action 右邊的 refresh 按鈕後,選擇剛剛建立的 target group:
Listener 會接收指定的 protocol 跟 port 的 request,接著檢查自己身上的 rule,看 request 符合哪一條 rule 就做那條 rule 的 action,如果都沒有符合的 rule 就做 default action。像這邊我們設定 Listener 要收 protocol 是 HTTP、port 80 的 request,default action 是把 request forward 到 target group tg-my-app
。
剩下其他設定不變,Create load balancer。
建立 ALB 後,要等它的 status 從 Provisioning 變成 Active 才能使用,在 Load balancers 清單可以看到所有的 load balancer 跟他們的資訊:
Listeners and rules tab 裡可以看 ALB 的 listener 跟 rule,我們可以設多個 Listener 來收不同 protocol 跟 port 的 request。
每個 Listener 可以有多個 rule,每個 rule 會些條件跟 action。新增 Listener 時會先設定 default action,也就是不符合其他所有 rule 的時候會做的 action。
action 有三種:
forward to target groups:把 request 導到指定的 target groups。target group 可以有多個、用 weight 來決定 target group 各自會收到多少百分比的流量。
redirect to url:轉到指定的網址
return fixed response:回應固定的 response
除了 default action 外,其他 rule 會有條件,像是 HTTP header、網址的 path、HTTP method 等等,Listener 會比對 request packet 跟 rule 的條件,符合的話就會做那個 rule 指定的 action。如果所有 rule 都不符合,就會執行 default action。
再到 target group 看一下,現在還沒有 registered target ,看起來有點寂寞(?
Health checks 的 tab 裡有前面提到的 health check 的詳細設定:
這邊是會對 target 的 /
發 http request,request 超過 timeout 5 秒沒有收到 status code 200 的 response 就算這個 health check request 是 failed。target group 會以大約 30 秒的間距發 health check request 給 target,如果一個 unhealthy target 連續 5 個 health check 都有正常回應,就會被認為它 healthy 了。如果一個 target 連續 2 個 health check 都 failed,則會被當作是 unhealthy target。
target group 會持續不斷的對所有 registered target 進行 health check,發現 unhealthy target 就不會把 request 再送給它並且一直都 unhealthy 的話會把那個 target 移除,藉此確保 target 們都能正常服務。
至於這些參數要怎麼設, 就是個藝術, 呃不是啦,要依據 application 的反應速度跟處理能力、希望 healthy 跟 unhealthy 的反應速度多快(多快發現一個死掉的 target 是 unhealthy 等等)還跟後面 deploy ECS 的時間也有關係,總之是需要慢慢 tune 的參數。