在 EC2 上用 CloudWatch Logs 收集 Container Logs
這篇把我在實物上設定 EC2 container log遇到的問題及做法完整記下來
為什麼要用 CloudWatch Logs
以前要看 container logs 必須 SSH 進 EC2 跑 docker logs,但當環境變多(staging + prod)後就很難管理。CloudWatch Logs 可以讓你直接在 AWS Console 或 CLI 看日誌,不需要每次 SSH。
整體架構
|
|
要讓這件事成立,需要三個東西:
- CloudWatch 有 log group 接收(Terraform 建)
- EC2 有權限寫入 CloudWatch(IAM role + instance profile)
- Docker containers 知道要送去哪(docker-compose 設定 awslogs driver)
查看 Logs
|
|
Local dev 不走 CloudWatch,直接用 docker compose logs。
IAM 概念
IAM Role — 門禁卡
IAM Role 就像一張門禁卡,上面寫著:
- 誰可以戴這張卡(Trust Policy / Assume Role Policy)
- 戴了這張卡可以進哪些房間(Permission Policy)
|
|
Instance Profile — 名牌夾
EC2 不能直接掛 IAM Role,必須透過 Instance Profile 這個「容器」間接掛。這是 AWS 的設計限制:
|
|
Terraform 範例:
|
|
注意:對已存在的 EC2 補上 iam_instance_profile 會觸發 instance 重建(AWS 限制)。
PassRole — 交出門禁卡的權限
GitHub Actions 透過 Terraform 幫 EC2 掛 IAM Role。AWS 會要求執行者具備「把門禁卡交出去」的權限:iam:PassRole。
如果沒有這個限制,任何有 IAM 權限的人都能把超級管理員 role 掛到任意 EC2。
|
|
最佳實務是把 PassRole 獨立成一個 statement,跟其他 IAM 操作(CreateRole 等)分開。
AWS 權限結構
每條 IAM Statement 由三個部分組成:
|
|
為什麼有些權限要用 Resource = "*"
像 logs:DeleteLogGroup 這種操作是針對特定 log group,可以做資源限制:
|
|
但 logs:DescribeLogGroups 是列表操作,AWS 不會用你指定的 resource pattern 來比對,必須用 *。這是唯讀操作,安全性可接受。
| 權限類型 | Resource 可以限定嗎? | 原因 |
|---|---|---|
| 增刪改操作(CreateLogGroup, DeleteLogGroup 等) | 可以,限定到 /side-project/* |
操作針對具體資源 |
| 列表操作(DescribeLogGroups) | 不行,必須用 * |
AWS 不支援列表 API 的資源限定 |
舊 API vs 新 API
AWS 會更名 API,以下兩組功能相同:
| 功能 | 舊 API | 新 API |
|---|---|---|
| 對 log group 加 tag | logs:TagLogGroup |
logs:TagResource |
| 列出 log group 的 tags | logs:ListTagsLogGroup |
logs:ListTagsForResource |
Terraform AWS provider 已改用新 API,但為了相容我會兩組都寫。
Bootstrap vs Main Terraform
| Bootstrap | Main Terraform | |
|---|---|---|
| 在哪裡跑 | 本地(手動) | GitHub Actions(CI/CD) |
| 管什麼 | GitHub Actions 的 IAM 權限、S3 state bucket | EC2、Security Group、EIP、IAM Role、CloudWatch |
| 為什麼分開 | CI/CD 不能自己幫自己加權限(雞生蛋) | 需要先有權限才能 apply |
| 多久跑一次 | 很少,只有改 CI/CD 權限時 | 每次 push 到 main |
流程:
|
|
Docker awslogs Driver
|
|
driver: awslogs:Docker 不存 logs 在本機,改送到 CloudWatch${APP_ENV}/${AWS_REGION}:從.env讀取tag:在 CloudWatch 裡辨識 log stream
Conclusion
把容器日誌集中到 CloudWatch 後,排錯速度大幅提升,而且 multi-env 管理也更乾淨。這套做法不只適用 Side-Project,任何 EC2 + Docker 的部署都能直接套用。