AWS CloudWatch Logs 日誌管理分析

AWS CloudWatch Logs Management and Analysis

CloudWatch Logs 概述

Amazon CloudWatch Logs 是 AWS 提供的完全託管日誌管理服務,可讓您集中收集、監控和分析來自 AWS 服務、應用程式和本地伺服器的日誌資料。透過 CloudWatch Logs,您可以即時監控應用程式和系統日誌,設定告警,並使用 Logs Insights 進行進階查詢分析。

主要功能

  • 集中式日誌管理:統一收集來自多個來源的日誌
  • 即時監控:即時串流和檢視日誌資料
  • 進階查詢:使用 Logs Insights 進行複雜的日誌分析
  • 指標篩選器:從日誌資料中提取自訂指標
  • 訂閱篩選器:將日誌串流到其他 AWS 服務
  • 長期保存:可設定日誌保留期限,從 1 天到永久保存

核心概念

Log Group(日誌群組)

Log Group 是日誌串流的容器,用於組織和管理相關的日誌資料。通常會為每個應用程式或服務建立一個獨立的 Log Group。

1
2
3
4
5
# 列出所有日誌群組
aws logs describe-log-groups

# 列出特定前綴的日誌群組
aws logs describe-log-groups --log-group-name-prefix /aws/lambda

Log Stream(日誌串流)

Log Stream 是 Log Group 內的日誌事件序列,通常代表單一來源(如特定的 EC2 執行個體或 Lambda 函數呼叫)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 列出特定日誌群組內的日誌串流
aws logs describe-log-streams \
    --log-group-name my-application-logs \
    --order-by LastEventTime \
    --descending

# 取得特定日誌串流的日誌事件
aws logs get-log-events \
    --log-group-name my-application-logs \
    --log-stream-name web-server-01 \
    --limit 100

建立 Log Group

使用 AWS CLI 建立

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 建立日誌群組
aws logs create-log-group --log-group-name /app/my-application

# 建立帶有標籤的日誌群組
aws logs create-log-group \
    --log-group-name /app/production/web-server \
    --tags Environment=Production,Application=WebServer

# 建立日誌串流
aws logs create-log-stream \
    --log-group-name /app/my-application \
    --log-stream-name instance-001

# 手動寫入日誌事件
aws logs put-log-events \
    --log-group-name /app/my-application \
    --log-stream-name instance-001 \
    --log-events timestamp=$(date +%s000),message="Application started successfully"

使用 AWS CLI 設定 KMS 加密

1
2
3
4
# 建立具有 KMS 加密的日誌群組
aws logs create-log-group \
    --log-group-name /app/secure-logs \
    --kms-key-id arn:aws:kms:ap-northeast-1:123456789012:key/12345678-1234-1234-1234-123456789012

安裝 CloudWatch Agent

CloudWatch Agent 可收集系統層級的指標和日誌,並傳送到 CloudWatch。

在 Amazon Linux 2 / RHEL 安裝

1
2
3
4
5
6
7
8
# 下載並安裝 CloudWatch Agent
sudo yum install amazon-cloudwatch-agent -y

# 或使用 SSM 安裝
aws ssm send-command \
    --document-name "AWS-ConfigureAWSPackage" \
    --targets "Key=instanceids,Values=i-1234567890abcdef0" \
    --parameters "action=Install,name=AmazonCloudWatchAgent"

在 Ubuntu / Debian 安裝

1
2
3
4
5
# 下載 CloudWatch Agent
wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb

# 安裝
sudo dpkg -i amazon-cloudwatch-agent.deb

設定 CloudWatch Agent

建立設定檔 /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
    "agent": {
        "metrics_collection_interval": 60,
        "run_as_user": "cwagent"
    },
    "logs": {
        "logs_collected": {
            "files": {
                "collect_list": [
                    {
                        "file_path": "/var/log/syslog",
                        "log_group_name": "/ec2/syslog",
                        "log_stream_name": "{instance_id}",
                        "timezone": "UTC"
                    },
                    {
                        "file_path": "/var/log/nginx/access.log",
                        "log_group_name": "/ec2/nginx/access",
                        "log_stream_name": "{instance_id}",
                        "timezone": "UTC"
                    },
                    {
                        "file_path": "/var/log/nginx/error.log",
                        "log_group_name": "/ec2/nginx/error",
                        "log_stream_name": "{instance_id}",
                        "timezone": "UTC"
                    }
                ]
            }
        }
    }
}

啟動 CloudWatch Agent

1
2
3
4
5
6
7
8
9
# 使用設定檔啟動 Agent
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
    -a fetch-config \
    -m ec2 \
    -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json \
    -s

# 檢查 Agent 狀態
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status

Logs Insights 查詢語法

CloudWatch Logs Insights 提供專用的查詢語言,可對日誌資料進行快速互動式分析。

基本查詢語法

1
2
3
4
5
6
7
8
9
# 使用 AWS CLI 執行 Logs Insights 查詢
aws logs start-query \
    --log-group-name /app/my-application \
    --start-time $(date -d '1 hour ago' +%s) \
    --end-time $(date +%s) \
    --query-string 'fields @timestamp, @message | sort @timestamp desc | limit 20'

# 取得查詢結果
aws logs get-query-results --query-id "12345678-1234-1234-1234-123456789012"

常用查詢範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 搜尋包含 ERROR 的日誌
fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 100

# 統計每小時的錯誤數量
fields @timestamp, @message
| filter @message like /ERROR/
| stats count(*) as error_count by bin(1h)

# 分析 HTTP 狀態碼分布
fields @timestamp, @message
| parse @message /status=(?<status>\d+)/
| stats count(*) by status

# 計算平均回應時間
fields @timestamp, @message
| parse @message /response_time=(?<response_time>\d+)/
| stats avg(response_time) as avg_time, max(response_time) as max_time by bin(5m)

# 找出最慢的請求
fields @timestamp, @message
| parse @message /response_time=(?<response_time>\d+)/
| sort response_time desc
| limit 10

指標篩選器

指標篩選器可從日誌資料中提取數值並建立 CloudWatch 指標。

建立指標篩選器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 建立錯誤計數指標篩選器
aws logs put-metric-filter \
    --log-group-name /app/my-application \
    --filter-name ErrorCount \
    --filter-pattern "ERROR" \
    --metric-transformations \
        metricName=ApplicationErrors,metricNamespace=MyApplication,metricValue=1,defaultValue=0

# 建立回應時間指標篩選器
aws logs put-metric-filter \
    --log-group-name /app/my-application \
    --filter-name ResponseTime \
    --filter-pattern '[timestamp, request_id, level, response_time]' \
    --metric-transformations \
        metricName=ResponseTime,metricNamespace=MyApplication,metricValue='$response_time'

# 列出現有的指標篩選器
aws logs describe-metric-filters --log-group-name /app/my-application

為指標建立告警

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 建立錯誤數量告警
aws cloudwatch put-metric-alarm \
    --alarm-name "HighErrorRate" \
    --alarm-description "應用程式錯誤數量過高" \
    --metric-name ApplicationErrors \
    --namespace MyApplication \
    --statistic Sum \
    --period 300 \
    --threshold 10 \
    --comparison-operator GreaterThanThreshold \
    --evaluation-periods 2 \
    --alarm-actions arn:aws:sns:ap-northeast-1:123456789012:alerts

訂閱篩選器

訂閱篩選器可將符合條件的日誌即時串流到其他 AWS 服務。

串流到 Kinesis Data Firehose

1
2
3
4
5
6
7
# 建立 Kinesis Data Firehose 訂閱
aws logs put-subscription-filter \
    --log-group-name /app/my-application \
    --filter-name AllLogs \
    --filter-pattern "" \
    --destination-arn arn:aws:firehose:ap-northeast-1:123456789012:deliverystream/my-stream \
    --role-arn arn:aws:iam::123456789012:role/CWLtoKinesisRole

串流到 Lambda 函數

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 建立 Lambda 訂閱篩選器
aws logs put-subscription-filter \
    --log-group-name /app/my-application \
    --filter-name ErrorsToLambda \
    --filter-pattern "ERROR" \
    --destination-arn arn:aws:lambda:ap-northeast-1:123456789012:function:ProcessErrors

# 刪除訂閱篩選器
aws logs delete-subscription-filter \
    --log-group-name /app/my-application \
    --filter-name ErrorsToLambda

跨帳戶日誌共享

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 在目標帳戶建立日誌目的地
aws logs put-destination \
    --destination-name SharedLogDestination \
    --target-arn arn:aws:kinesis:ap-northeast-1:123456789012:stream/shared-logs \
    --role-arn arn:aws:iam::123456789012:role/CWLtoKinesisRole

# 設定目的地存取政策
aws logs put-destination-policy \
    --destination-name SharedLogDestination \
    --access-policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"111111111111"},"Action":"logs:PutSubscriptionFilter","Resource":"arn:aws:logs:ap-northeast-1:123456789012:destination:SharedLogDestination"}]}'

日誌保留設定

適當的日誌保留設定可平衡合規需求和儲存成本。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 設定日誌保留期限為 30 天
aws logs put-retention-policy \
    --log-group-name /app/my-application \
    --retention-in-days 30

# 可用的保留期限選項:
# 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1096, 1827, 2192, 2557, 2922, 3288, 3653

# 移除保留限制(永久保存)
aws logs delete-retention-policy --log-group-name /app/my-application

# 批次設定多個日誌群組的保留期限
for log_group in $(aws logs describe-log-groups --query 'logGroups[*].logGroupName' --output text); do
    aws logs put-retention-policy --log-group-name "$log_group" --retention-in-days 90
done

成本優化

CloudWatch Logs 的費用主要來自資料擷取、儲存和查詢。以下是一些成本優化策略:

1. 設定適當的保留期限

1
2
3
4
5
6
7
8
9
# 針對不同環境設定不同保留期限
# 開發環境:7 天
aws logs put-retention-policy --log-group-name /app/dev --retention-in-days 7

# 測試環境:14 天
aws logs put-retention-policy --log-group-name /app/staging --retention-in-days 14

# 生產環境:90 天
aws logs put-retention-policy --log-group-name /app/production --retention-in-days 90

2. 使用日誌類別降低成本

1
2
3
4
# 建立使用不常存取日誌類別的日誌群組
aws logs create-log-group \
    --log-group-name /app/archive-logs \
    --log-group-class INFREQUENT_ACCESS

3. 匯出日誌到 S3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 建立匯出任務到 S3
aws logs create-export-task \
    --log-group-name /app/my-application \
    --from $(date -d '30 days ago' +%s000) \
    --to $(date +%s000) \
    --destination my-log-archive-bucket \
    --destination-prefix exports/my-application

# 檢查匯出任務狀態
aws logs describe-export-tasks --task-id "task-id-here"

4. 過濾不必要的日誌

在 CloudWatch Agent 設定中排除不需要的日誌:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
    "logs": {
        "logs_collected": {
            "files": {
                "collect_list": [
                    {
                        "file_path": "/var/log/app/*.log",
                        "log_group_name": "/app/logs",
                        "log_stream_name": "{instance_id}",
                        "filters": [
                            {
                                "type": "exclude",
                                "expression": "DEBUG"
                            }
                        ]
                    }
                ]
            }
        }
    }
}

5. 監控 CloudWatch Logs 使用量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 查看日誌群組的儲存大小
aws logs describe-log-groups \
    --query 'logGroups[*].[logGroupName,storedBytes]' \
    --output table

# 建立成本告警
aws cloudwatch put-metric-alarm \
    --alarm-name "CloudWatchLogsHighIngestion" \
    --metric-name IncomingBytes \
    --namespace AWS/Logs \
    --statistic Sum \
    --period 86400 \
    --threshold 10737418240 \
    --comparison-operator GreaterThanThreshold \
    --evaluation-periods 1 \
    --alarm-actions arn:aws:sns:ap-northeast-1:123456789012:billing-alerts

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy