iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0

終於要開始建立 ECS service 了!今天我們的目標是讓 Laravel 成功在 ECS service 上運作~

ECS Service 簡介

ECS service 是 AWS ECS 用來執行長期運作且 stateless 的 application 的功能,我們用 Laravel 開發的 web application 就是需要長期運作的 application,不像影片轉檔之類的工作,只在需要的時候執行一次。

一個 ECS cluster 可以建立多個 ECS service,每個 ECS service 會指定一個 task definition 及希望執行的 task 數量(task desired count)。

task 的數量由ECS service scheduler 負責維持,它以我們指定的 scheduling strategy 來決定 task 要放在哪台 container instance 上(task placement)。如果有 task fail 或 stop,ECS service scheduler 會啟動新的 task 以確保 task 數量。service 的 scheduling strategy 也被稱為 service type,有 REPLICA 跟 DAEMON 兩種。

接下來我們會啟動一個 MySQL container 作為 Database,然後建立一個基本的 ECS Service 並且看到 Laravel 的歡迎畫面。

在 EC2 instance 啟動 MySQL container

跟第一天在本機跑 Laravel 的 container 一樣,Laravel 需要連一台 MySQL database。實務上可以用任何 EC2 instance 連得到的 Database,也不一定要是 MySQL,端看需求而定。這裡我們重複利用安裝 Gitlab Runner 的 EC2 instance(不是用來跑 ECS service 的 EC2 instance 喔!!)來執行 MySQL container 作為 Database。

啟動 EC2 instance 後 ssh 進去,跟在本機一樣用 docker run 來啟動 MySQL container:

$ sudo docker run -d \
  -e MYSQL_ALLOW_EMPTY_PASSWORD=true \
  -e MYSQL_DATABASE=laravel \
  -p 3306:3306 \
  --name dbserv \
  --restart=always \
  mysql:8.0

跟本機不同的是這次我們將 MySQL 使用的 port 3306 mapping 到 host 上,讓其他機器連這台 EC2 instance 的 port 3306 時會連到 container 中的 MySQL server。另外也用 --restart=always 參數讓 MySQL container 被關閉後會重新啟動,在 EC2 instance 會開開關關的時候很方便!(不然每次開機 EC2 instance 都要連進來啟動 MySQL container)

一樣要注意上述指令僅是為了實驗,一般不會容許空白密碼,Laravel 也不該用 root 連 database,應該要為這個 application 建立一個 user 並且設定適當權限。

接著就能在 Gitlab CI/CD variable 裡的 ENV 變數設定 EC2 instance 的 public IP 然後 build & push image 了!(小提示:如果沒有 push code 卻想執行 pipeline,可以進到 pipelines 頁面點右上角的 Run Pipeline。)

建立基本 ECS Service

進入之前新增的 cluster,點選 service 的 create:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671XZrjE2gHp0.png

Compute configuration 我們先用比較簡單的 Launch type,並且使用 EC2:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671ByZugUxr7G.png

來到 deployment 相關設定。我們要 deploy 的是一個會持續執行的 Laravel web service,Application type 選擇 Service。接著我們要幫這個 ECS service 指定 task definition,當然是用先前建立的 task definition 啦~版本用 LATEST(如果你有修改過,LATEST 的 revision 不會是 1)。

https://ithelp.ithome.com.tw/upload/images/20230919/20160671rqWFpSJXaG.png

ECS service type 是 service scheduler 的 strategy,前面說到有兩種:

  • REPLICA:會啟動並維持 task 在指定的數量,可額外指定 task placement strategy 跟 constraint 來自訂 task 如何分配到 container instance 上

  • DAEMON:每台 active 並且符合 task 資源要求的 container instance 都會部屬剛好一個 task

兩種 type 通常依據 application 的特性以及需求決定使用哪一個,這邊我們用 REPLICA。其他設定保持預設,點選 Create,然後我們就會在 Services 的頁面看到:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671juSWXuuVIJ.png

進到 service 看看:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671gkhkA4EXOU.png

呃,deployment 失敗。為什麼?到 service 的 Deployments 檢查底下的 Event:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671anZjwIw7vl.png

再點進一個 task:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671YkqvijjOxh.png

???

為什麼 EC2 instance 關掉了?到 auto scaling group 看發現還真的關掉了,而且 desired capacity 變成 0,why???

檢查 auto scaling group 的 Activities,會看到:

https://ithelp.ithome.com.tw/upload/images/20230919/201606710k0essHq1A.png

看起來是 cluster 的 auto scaling 被觸發,便將 auto scaling group 的 desired capacity 變回 0。這裡牽涉到 cluster 的 auto scaling 比較複雜,我們先用暴力解——把 auto scaling group 的 minimum capacity 調成 1,這樣 auto scaling 就不能把 desired capacity 設成小於 1 的數值。

再回到 ECS service…….就發現它不見了。

AWS 玩我啊???

咳……冷靜。

是這樣的,現在 AWS 新版 web console 會用 CloudFormation 來建立 ECS service,如果 ECS service 無法 deploy 成功,這個 stack 就不算建立成功,預設會被 rollback。可以在 CloudFormation 看到像這樣的 stack(如果沒有可能是 rollback 完後被刪除了):

https://ithelp.ithome.com.tw/upload/images/20230919/20160671eIpXy5fu36.png

再重複一次建立 ECS service 的步驟把 service 開回來。

然後它就不讓我建立相同名稱的 ECS service (眼神逐漸死去)

https://ithelp.ithome.com.tw/upload/images/20230919/20160671HAZ9kDGFn9.png

這時候到 CloudFormation,確認 ECS service 的 stack 的 status 是 ROLLBACK_COMPLETE 後,就可以把那個 stack 給刪除(delete),再重新建立 ECS service 終於成功了。

一樣進到 service 看看 deploy 狀況:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671d4OYakCA6E.png

還是 failed 耶!^_^

一樣點進 task 看看:

https://ithelp.ithome.com.tw/upload/images/20230919/201606712jdHZjed3C.png

錯誤不一樣,太好了!(疑?

docker run 把 image 抓下來執行看看(注意:如果 tag 用 latest 而且你的機器上已經有這個 tag 的 image 的話,最好要 docker pull 確定是用到最新版的 image)

https://ithelp.ithome.com.tw/upload/images/20230919/20160671poV6cqK3C8.png

在…這…畫…面…卡..了…好…一…陣…子……..

然後終於出現 timeout 的 error:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671qfwBBPmARb.png

這表示我們的 container 連不上 MySQL server,為什麼呢?

我們先在本機試試看用 mysql client 能不能連線,排除是 container 造成問題的可能:

$ mysql -h [MYSQL_SERVER_IP] -u root

一樣連不上:

ERROR 2002 (HY000): Can't connect to MySQL server on '13.112.194.32' (115)

為什麼咧?

這是剛開始用 AWS 非常容易踩到的問題:Security Group 沒設定好

設定 allow tcp port 3306 的 Security Group

記得我們在安裝 Gitlab Runner 時設定過 security group 嗎?依照類似的步驟,建立一個新的 security group,讓它 allow port 3306、source 是 0.0.0.0/0 ,並且 attach 到跑 MySQL container 的 EC2 instance 上。

security group 在 EC2 service 裡:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671D4CzHtXquI.png

從右上角 Create security group,選擇 VPC 與新增 inbound rule 後 create:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671PAKpRhPI7q.png

新增好 security group 後,要再到 EC2 instance 頁面在裝 MySQL database 的 instance 上按右鍵 ⇒ Security ⇒ Change security groups:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671Zebl5lQr82.png

加入剛剛建立的 security group 後 save:

https://ithelp.ithome.com.tw/upload/images/20230919/201606715nO3rulgoX.png

這樣就完成了這台 EC2 instance 的 allow MySQL 的 security group 設定,可以在 instance 的 security tab 看到它身上有的 security group:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671yUvpfYEhVY.png

設好 security group,讓我們再一次建立 ECS service……

等啊等啊等……

終於看到這個畫面!!

https://ithelp.ithome.com.tw/upload/images/20230919/20160671oJoOqo9Sz0.png

在 Events 看到 service xxx has reached a steady state. 才表示這個 service deploy 好而且穩定了!

最後我們要用瀏覽器確認 Laravel 有執行起來,連到跑 container 的機器看看有沒有出現 Laravel welcome 的畫面,先找到作為 container instance 的 IP address,從 ECS cluster 的 infrastructure 點進 container instance,可以看到 network 資訊:

https://ithelp.ithome.com.tw/upload/images/20230919/201606715NEkW75Qp1.png

我們快樂的連上 http://13.115.245.251 吧!

然後就 timeout 連不上。

好~的~又~忘記 security group 了,趕緊把 inbound rule tcp port 80 以及 source 0.0.0.0/0 加進 container instance 的 security group,再連一次~

https://ithelp.ithome.com.tw/upload/images/20230919/20160671HUmlEBwJRO.png

成功啦!

目前架構

現在的架構長這樣:

https://ithelp.ithome.com.tw/upload/images/20230919/20160671RaZ3kb2cud.png

跟昨天很像,我們建立 ECS service 並依照 task definition 啟動一個 task。ECS 會跟 container instance 裡的 ECS agent 溝通,找一台 container instance 來啟動 container。這個 container 的 image 來自 ECR repository。container instance 是在 ASG(Auto Scaling Group)內的,我們額外有開一台 EC2 instance 來跑 MySQL container 跟 Gitlab Runner。

收拾房間(?)

玩具(O)玩完了要記得收拾,不然會被收比較多費用喔~

ECS service 的 task 數量調成 0 關閉 task 們,沒有 running task 後可以到 Cloudformation 把 ECS service 的 stack 砍掉,我們明天會開新的。

現在主要會被收費的是 EC2 instance,所以要把 Auto Scaling Group 的 desired capacity 調成 0(筆者建議 minimum 跟 maximum 也調成 0),確認 instance 都關掉。還有執行 MySQL server 的 EC2 instance 也要 stop。

Reference


上一篇
Day 8 了解 Container Instance & 定義 Task Definition
下一篇
Day 10 Load Balancing
系列文
AWS ECS + Gitlab + Laravel + Terraform 從入門到摔坑30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言