CloudWatch Logs의 로그를 Lambda를 사용하여 S3로 전송

이 페이지는 무엇입니까?



표제대로, Lambda 함수를 사용하여 CloudWatch Logs의 로그를 S3로 전송하는 메커니즘을 구현합니다.

참고로 한 URL



배경



AWS 서비스에서 파일 배포 요금이 가장 싼 것은 S3입니다.
그래서, 예를 들어 CloudWatch Logs에 저장하고 있는 로그에 대해서는 7일 보관으로 하고, S3에는 1년간 보관과 같은 구조를 만들고 싶었습니다.

구조(구성도)





작업 절차



IAM 역할(정책) 만들기



아래 IAM 정책을 생성하고 IAM 역할에 연결하여 Lambda에 연결합니다.
(Lambda가 S3 버킷에 대한 작업 권한이 필요하기 때문에)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"     # S3バケット内のリスト表示に必要(最初に接続確認をするため)
            ],
            "Resource": "arn:aws:s3:::S3バケット名"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",     # S3バケットにログを配置する前にS3バケット内のファイルの存在を確認するための権限
                "s3:PutObject"     # S3バケットにログを配置するための権限
            ],
            "Resource": "arn:aws:s3:::S3バケット名/*"
        }
    ]
}

S3 버킷 정책 설정



· 내뿜는 S3 버킷 정책에 다음 버킷 정책을 설정하십시오.
· 보충: 이 설정은 CloudWatch Logs에서 S3 버킷으로 로그를 배치하는 데 필요한 버킷 정책입니다.
(CloudWatch Logs에 IAM 역할은 연결할 수 없으므로 S3의 버킷 정책으로 제어합니다.)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.対象リージョン.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",     # CloudWatch Logsから S3バケットのアクセス(s3apiコール)制御のポリシー 
            "Resource": "arn:aws:s3:::S3バケット名"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.対象リージョン.amazonaws.com"
            },
            "Action": "s3:PutObject",     # CloudWatch Logsから S3バケットへログ配置するためのS3バケットポリシー 
            "Resource": "arn:aws:s3:::S3バケット名/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

Lambda 함수 만들기



· 사용 언어는 python3. 버전은 3.7입니다.

코드



코드는 「참고로 한 사이트」에 기재되어 있는 내용과 거의 같습니다.
코드내에 기재되어 있는 코멘트 아웃 부분을, 환경 마다 적절히 편집해 가는 형태가 됩니다.
import datetime
import time
import boto3

log_group_name = 'ロググループ名'    #CloudWatchLogsのロググループ名
s3_bucket_name = 'S3バケット名'    #保存先S3バケット名
s3_string_prefix = 'S3内のプレフィックス'    #S3内のプレフィックス(文字列)を定義
s3_date_prefix = '/%s' % (datetime.date.today() - datetime.timedelta(days = 1))    #S3内のプレフィックス(日付)を定義

def get_from_timestamp():
    today = datetime.date.today()
    yesterday = datetime.datetime.combine(today - datetime.timedelta(days = 1), datetime.time(0, 0, 0))
    timestamp = time.mktime(yesterday.timetuple())
    return int(timestamp)

def get_to_timestamp(from_ts):
    return from_ts + (60 * 60 * 24) - 1

def lambda_handler(event, context):
    from_ts = get_from_timestamp()
    to_ts = get_to_timestamp(from_ts)
    print('Timestamp: from_ts %s, to_ts %s' % (from_ts, to_ts))

    client = boto3.client('logs')
    response = client.create_export_task(
        logGroupName      = log_group_name,     #取得するCloudWatchロググループ名
        fromTime          = from_ts * 1000,
        to                = to_ts * 1000,
        destination       = s3_bucket_name,     #保存先S3バケット名
        destinationPrefix = s3_string_prefix + s3_date_prefix   #保存先S3バケット名配下の任意のサブフォルダ名(プレフィックス名)
    )
    return response

CloudWatch Event 만들기



매일 AM4:00에 이벤트 발생하는 경우, CloudWatch Event에 아래의 cron 설정을 하면 됩니다.
(시간이 UTC 형식이므로 UTC에서 +9시간을 하는 것을 잊지 마세요.)
0 19 * * ? *

고민한 일



S3에 내뿜을 때의 파일명이 「000000.gz」가 되어 버리기 때문에, 파일명을 바꾸는 방법을 조사했습니다만, boto3의 api의 사양으로 「000000」으로 토출되어 버리는 것 같습니다(파일명 다른 이름으로 저장하고 싶다면 별도의 메커니즘을 구현해야합니다).

boto3_URL

좋은 웹페이지 즐겨찾기