昨天介紹了 ECS Cluster Auto Scaling,今天還看看 ECS service 的 auto scaling。(本日程式碼)
ECS cluster auto scaling 透過 auto scaling group 控制 container instance 的數量來滿足 task 的需求。ECS 會把 CPU 跟 Memory 使用資訊傳給 Cloudwatch,ECS service auto scaling 則是利用這些 loading 資訊自動增減 task 數量,loading 高便增加 task 數量來提供服務,loading 低則減少 task 以節省資源。ECS 是使用 Application Auto Scaling 的功能來做 service 的 auto scaling。
ECS auto scaling 有以下三種 scaling 的方式:
Target tracking scaling policy:針對某個 metric 設定一個目標值(target),scaling 會試圖讓 metric 維持在目標值。
Step scaling policy:可以幫 metric 設定多個範圍,當 loading 到達不同範圍時會發生不同的 scaling 調整。
Scheduled scaling:依據時間進行 scaling。
來設定 target tracking scaling 吧~
先新增個 aws_appautoscaling_traget
:
resource "aws_appautoscaling_target" "target" {
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.cluster.name}/${aws_ecs_service.service.name}"
max_capacity = var.ecs_task_max_count
min_capacity = var.ecs_task_min_count
scalable_dimension = "ecs:service:DesiredCount"
}
我們是在 ECS 加 auto scaling,service_namespace
設 ecs
,resource_id
指定要加上 auto scaling 的 ECS service。透過 max_capacity
跟 min_capacity
設定ECS service 的 task 數量上下限,跟 auto scaling group 的 max 跟 min capacity 概念一樣。最後 scalable_dimension
是 ECS service 的 desired count(ECS 也只有這個可以設定)。詳細參數說明可參考 application auto scaling 的文件。
接著要定義 aws_appautoscaling_policy
,這邊就會指定要用什麼 metric、目標值(target value)要是多少。我們訂兩個 policy,分別針對 CPU 跟 Memory 的使用量:
resource "aws_appautoscaling_policy" "cpu" {
name = "cpu-utilization"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.target.resource_id
scalable_dimension = aws_appautoscaling_target.target.scalable_dimension
service_namespace = aws_appautoscaling_target.target.service_namespace
target_tracking_scaling_policy_configuration {
target_value = 50
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
}
}
resource "aws_appautoscaling_policy" "memory" {
name = "memory-utilization"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.target.resource_id
scalable_dimension = aws_appautoscaling_target.target.scalable_dimension
service_namespace = aws_appautoscaling_target.target.service_namespace
target_tracking_scaling_policy_configuration {
target_value = 50
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageMemoryUtilization"
}
}
}
設定 policy_type
為 TargetTrackingScaling
來使用 target tracking scaling 的 policy,在 target_tracking_scaling_policy_configuration
block 指定 target value 是 50,兩個 policy 分別看的 metric 是 ECS service 的 CPU 平均使用量跟 Memory 平均使用量。
建立 ECS service auto scaling 後,每個 policy 會在 cloudwatch 開兩個 alarm,一個是 upper bound、一個是 lower bound,藉由這兩個 alarm 來讓 metric 的值盡量接近 target value。
這兩個 alarm 是 ECS 依據設置的 target value 產生的,不要手動調整或刪除。policy 修改的時候,舊的 alarm 會被刪掉然後建立新的,手動調整的話很容易東西就不見了~
ECS service 設置 auto scaling 後,task desired count 會被 auto scaling 控制,很容易跟 terraform 裡設定的不同在 terraform 操作上造成沒必要的 changes,可以在 aws_ecs_service.service
加上 lifecycle
block 忽略 desired count 的變動:
lifecycle {ignore_changes = ["desired_count"]}
這樣 Terraform 就不會去管 task desired count 的 change 了~
最後,我們可以從 ECS service 的 health and metrics tab 觀察 service 的 CPU 跟 Memory 的使用量,從 cloudwatch 看 alarm 的狀態,然後觀察 ECS service task 數量的變化。各位可以嘗試修改 Laravel 程式碼,讓 CPU 或 Memory 的使用量超過 50% 或者都低於 45%,看看 ECS service 會有什麼反應。
所有東西都玩(O)夠、不需要這些 resource 的時候,記得下 destroy 指令把所有 resource 刪掉:
$ terraform destroy
如果有些東西想留著、不想被 terraform 刪掉,可以先 terraform state rm [RESOURCE]
把想保留的 resource 從 terraform 的管理中移除,之後再 destroy 就不會砍到它們了~
今天是鐵人賽最後一天~回顧一下這 30 天經歷(?)了些什麼~
一開始我們在本機上用 Docker 製作 Laravel 的 image、啟動 container 然後 push 上 ECR repository。接著開始使用 EC2 instance、建立 Gitlab Pipeline 自動 deploy,然後進到 ECS 的世界,再用 CodePipeline 把整個流程串起來。
手動設置成功之後,我們改用 IaC 工具 Terraform,經過漫長又無聊的 import 後終於寫好 Terraform 的 configuration。之後開始改良 infrastructure,把 Terraform state 改放到 Gitlab 上、讓 container log 出現在 web console 上方便 debug、改成 high availability 架構以及加上 CDN,最後到 ECS 的 auto scaling。
希望各位這 30 天玩得愉快,可以基於這些基礎在 Devops 的路上繼續 摔坑 前進~ 🙂