LoginSignup
3
2

More than 3 years have passed since last update.

【Lambda】CloudWatch ログの保存期間を自動で設定する

Last updated at Posted at 2019-08-24

はじめに

以前、CloudWatchのログをS3にエクスポートするLambdaを作成しました。
CloudWatchLogsはロググループごとに保持期間を設定できるため、これを任意の期間に設定すればCloudWatchLogsにログが大量に蓄積...ということはないのですが、ロググループが作成される度に手動で設定するのがかなり面倒に感じました。ということで、こちらもLambdaで自動で設定されるようにしました。

構成

今回は、CloudWatchEventsでLambdaを定期的に動かし保持期間が異なるものは変更するようにしました。
本当はロググループが新規に作成されるイベントをトリガーにしたかったのですが、できなさそうだったので。。。
スクリーンショット 2019-08-24 13.20.37.png

事前準備

IAMロールの作成

Lambdaに割り当てるIAMロールを作成します。

IAMロールのポリシードキュメントは、以下。

IAMロールポリシードキュメント
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

IAMロールは以下。
大きく分けると2つの権限が必要です。
1.LambdaのログをCloudwatchLogsに書き込む権限
CreateLogStream
CreateLogGroup
PutLogEvents

2.CloudWatchLogsの保存期間を変更する権限
DescribeLogGroups
PutRetentionPolicy

IAMポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:DescribeLogGroups",
                "logs:PutRetentionPolicy",
                "logs:CreateLogGroup",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

Lambdaの設定

ランタイムはPython3.7を使用、さらに以下の環境変数を設定しました。
EXCEPT_LOGGROUPS :対象外とするロググループをカンマ区切りで指定。
RETENTION_DAYS   :ログの保持期間を日数で指定。

成功すれば以下のようなログが表示されるようにしています(保持期間を14日に設定)。
successfully change /aws/lambda/cloudwatchlogs-retentionpolicy retention days : 14 days

作成したLambdaに、先ほど作成したIAMロールを割り当てます。
作成したコードは以下。

cloudwatchLogs-retentionpolicy.py
import boto3
import os

client = boto3.client('logs')
except_loggroups = os.environ.get("EXCEPT_LOGGROUPS").split(",")
retention_days = os.environ.get("RETENTION_DAYS")


def lambda_handler(event, context):
    log_group_retention_days = {}
    for log_group_des in get_log_group_des(next_token=None):
        log_group_retention_days.update(
            get_log_group_retention_days(log_group_des))
    for log_group in log_group_retention_days:
        if log_group_des['logGroupName'] not in except_loggroups and log_group_retention_days[log_group] != int(retention_days):
            response = client.put_retention_policy(
                logGroupName=log_group,
                retentionInDays=int(retention_days)
            )
            print(
                f"successfully change {log_group} retention days : {retention_days} days")


def get_log_group_des(next_token):
    if next_token is not None and next_token != '':
        response = client.describe_log_groups(
            limit=50,
            nextToken=next_token
        )
    else:
        response = client.describe_log_groups(limit=50)
    if 'logGroups' in response:
        yield from response['logGroups']
    # ロググループが多くて50件(最大)を超えるようなら再帰呼出し
    if 'nextToken' in response:
        yield from get_log_group_des(next_token=response['nextToken'])

# {ロググループ名:保持期間}を取得
def get_log_group_retention_days(log_group_des):
    try:
        log_group_retention_days = {
            log_group_des['logGroupName']: log_group_des['retentionInDays']}
    except KeyError:
        log_group_retention_days = {log_group_des['logGroupName']: 'NotExpire'}
    return log_group_retention_days

CloudWatch Eventsの設定

あとは、任意のタイミングでLambdaが動くようCloudWatchEventsの設定をしてください。
ちなみに私はcronで毎日1回動かす設定にしたので、cron式は以下のようになります。

毎日10時に動かすcron式
0 10 * * ? * 

以上です。最後までお読みいただきありがとうございます。

参考文献

Boto 3 Documentation
Step FunctionsでCloudWatch LogsのロググループをS3へエクスポートする

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2