はじめに
Amazon Data FirehoseやLambdaを作成したときに自動で作成されるロググループの保持期間が「失効しない」になったまま「変更していない」、もしくは「変更を忘れていた」などといったご経験はないでしょうか?
Amazon CloudWatch Logsのロググループでは保存されているログの量によってコストがかかってきてしまい、ロググループの保持期間が「失効しない」に設定されていると過去のログも削除されず、コストが増加してしまいます。
そこで、今回はロググループが作成されたときに、保持期間を確認し「失効しない」に設定されている場合は自動で保持期間を「1ヵ月」に変更する仕組みを考えてみました。
考えた構成
EventBridgeルールでロググループの作成イベントを検知し、ターゲット先にLambdaを設定します。
Lambdaではロググループの保持期間(retentionInDays)を確認し、retentionInDaysが無い場合(=失効しない場合)はretentionInDaysを30に設定、
retentionInDaysが設定されている場合はそのまま終了という処理を行うような構成を考えました。
構築手順の全体像
1.Lambda実行用のIAMロールの作成
2.ロググループの保持期間を確認・変更するLambda関数の作成
3.ロググループの作成イベントを検知するEventBridge ruleの作成
Step 1. IAMロール作成
Lambda関数にアタッチするIAMロールを作成します。
| 項目 | 設定値 | 説明 |
|---|---|---|
| サービスまたはユースケース | Lambda | このロールはLambdaのみアタッチできます。他のサービスやユーザーにはアタッチできません。 |
| 許可ポリシー | AWSLambdaVPCAccessExecutionRole (AWSLambdaBasicExecutionRole)※1 | VPC内のリソースにアクセスする際にLambda関数を実行するための最低限の権限。 |
| ロール名 | 任意の名前 | - |
※1 AWSLambdaVPCAccessExecutionRoleはVPC内にLambdaを作成しない場合、設定不要で代わりに、AWSLambdaVPCAccessExecutionRoleを設定します。
IAMロールの作成が完了したら、LambdaがCloudWatch Logsのロググループの保持期間を変更できるような権限を追加します。
追加するポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:DescribeLogGroups",
"logs:PutRetentionPolicy"
],
"Resource": "*"
}
]
}
以上でIAMロールの設定は完了となります。
Step. 2 Lambda関数の作成
ロググループの保持期間を確認するLambdaを作成します。
| 項目 | 設定値 | 説明 |
|---|---|---|
| 関数名 | 任意の名前 | - |
| ランタイム | Python3.14 | - |
| アーキテクチャ | x86_64 | - |
| 実行ロール | Step.1で作成したIAMロール | Lambda実行用ロール |
| VPC | 有効 | 無効でも可なので今回は詳細な設定は省略 |
Lambda関数が作成されたらコードソースを編集します。
以下コードソースを貼り付け、Deployします。
コードソース
import json
import boto3
logs = boto3.client('logs')
def lambda_handler(event, context):
print("Event:", json.dumps(event))
log_group_name = event['detail']['requestParameters'].get('logGroupName')
if not log_group_name:
print("No log group name found.")
return
try:
response = logs.describe_log_groups(
logGroupNamePrefix=log_group_name
)
for lg in response['logGroups']:
if lg['logGroupName'] == log_group_name:
# retentionInDays が無い = 失効しない
if 'retentionInDays' not in lg:
print(f"{log_group_name} is set to Never Expire. Updating to 30 days.")
logs.put_retention_policy(
logGroupName=log_group_name,
retentionInDays=30
)
else:
print(f"{log_group_name} already has retention set.")
except Exception as e:
print("Error:", str(e))
raise e
最後に任意ではありますが、タイムアウトを30秒に設定しておくとよいでしょう。(デフォルトは3秒です。)
以上でLambdaの設定は完了となります。
Step. 3 EventBridge ruleの作成
ロググループの作成が成功した際にLambdaを呼び出すためのEventBridge ruleを作成します。
| 項目 | 設定値 | 説明 |
|---|---|---|
| ルール名 | 任意の名前 | - |
| イベントソース | その他 | - |
| イベントパターン | ※2 | ロググループの作成に成功したときのイベント。 |
| ターゲット | Lambda | イベントパターンに一致したときにLambdaを呼び出す。 |
| 関数名 | Step.2で作成した関数 | ロググループの保持期間を確認し、「失効しない」に設定されている場合は「30日」に変更する。 |
| 実行ロール | この特定のリソースについて新しいロールを作成 | 新規作成 |
| ロール名 | 任意の名前 | - |
※2 イベントパターンは以下を使用
{
"source": ["aws.logs"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["logs.amazonaws.com"],
"eventName": ["CreateLogGroup"],
"errorCode": [{
"exists": false
}]
}
}
以上でEventBridge ruleの設定は完了となります。
動作確認
テスト用のロググループを保持期間の設定「失効しない」にして作成してみます。
少し待ってから作成したロググループを確認してみると・・・
保持の設定が1ヵ月に変わっていました!
試しに「Amazon CloudWatch エラーのログ記録」を有効にして、
DateFirehoseを作成し、エラーログのロググループを確認してみても・・・
保持期間が1ヵ月に変更されていました!
おまけ
今回は自動で作成されるロググループに対しての保持期間設定の変更漏れを防ぐためだったので、ロググループ作成時のみ保持期間の変更を行うことで解決できました。
しかし、そもそも既存のロググループの保持期間で「失効しない」となっているロググループを全て「1ヵ月」に変更したかったり、現在はロググループの保持期間が「1ヵ月」になっているものの、誰かが誤って「失効しない」に変更してしまった場合「1ヵ月」に戻したいといった場合にこの仕組みは使用できません。
そういった場合はAWS Configと修復アクションを使用すれば、解決できるかと考えています。
ただし、AWSが用意しているマネージドルールにはロググループの保持期間が「失効しない」になっているかどうか監視するルールがありません。
※「cw-loggroup-retention-period-check」というロググループの保持期間が指定した日数より短い場合、「NON_COMPLIANT」とマークするルールは存在するが、保持期間が「失効しない」の場合は設定した日数が何日であっても「COMPLIANT」としてマークされてしまうため、修復アクションが使用できません。
そのため、カスタムルールを作成して保持期間が「失効しない」になっているかどうか確認する必要があります。
今回は長くなるため、やり方までは割愛させてください。
まとめ
自動で作成されるロググループの保持期間はデフォルトで「失効しない」になってしまい、過去のログが蓄積されてしまうため、「1ヵ月」など日数を設定して削除するようにしましょう。
作成時にいちいち変更するのが面倒な場合はEventBridgeとLambdaを使用して、ロググループ作成時に保持期間を自動で変更する仕組みを作成すると良いでしょう。










