【Lambda】CloudWatch 로그의 보존 기간을 자동으로 설정

소개



이전에 CloudWatch 로그를 S3로 내보내는 Lambda 만들기 했습니다.
CloudWatchLogs는 로그 그룹별로 보존 기간을 설정할 수 있기 때문에 이것을 임의의 기간으로 설정하면 CloudWatchLogs에 로그가 대량으로 축적...이라는 것은 없습니다만, 로그 그룹이 작성될 때마다 수동 설정하는 것이 상당히 번거롭게 느껴졌습니다. 그래서 이쪽도 Lambda에서 자동으로 설정되도록했습니다.

구성



이번에는 CloudWatchEvents에서 Lambda를 정기적으로 움직여 보존 기간이 다른 것은 변경하도록 했습니다.
사실은 로그 그룹이 새롭게 작성되는 이벤트를 트리거로 하고 싶었습니다만, 할 수 없을 것 같았기 때문에. . .


사전 준비



IAM 역할 만들기



Lambda에 할당할 IAM 역할을 만듭니다.

IAM 역할 정책 문서는 다음과 같습니다.

IAM 역할 정책 문서
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}


IAM 롤은 이하.
크게 나누면 두 가지 권한이 필요합니다.
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으로 매일 한 번 움직이는 설정으로 했으므로, cron식은 이하와 같이 됩니다.

매일 10시에 움직이는 cron식
0 10 * * ? * 

이상입니다. 끝까지 읽어 주셔서 감사합니다.

참고문헌



Boto 3 Documentation
Step Functions에서 CloudWatch Logs 로그 그룹을 S3로 내보내기

좋은 웹페이지 즐겨찾기