-
[AWS] CloudWatch 로그를 S3 로 보관하기 (Exporting CloudWatch logs to S3 Bucket)Back End/AWS 2022. 11. 7. 11:20
CloudWatch, S3 그리고 S3 Glacier 의 가격
CloudWatch 는 단순 저장말고도 Metrix 를 이용해 경보등의 서비스를 생성할 수 있으므로 당연히
CloudWatch Log 서비스의 가격이 S3 보다 비싸다.
또, S3 가 S3 Glacier 보다 가격이 비싸다. (액세스 속도 차이)
그렇다면 장애사후분석등 로그를 꼭 보관해야하는 상황에서는
Alarm 등의 서비스를 이용하기 위해 7일 정도로 CloudWatch 에 보관하고
CloudWatch 의 로그를 S3 로 옮겨 1~2달을 보관하고
이후에는 S3 Glacier 로 옮겨 Archive 하는 것이 비용적으로 가장 효율적일 것이다.
그런데 문제점은 CloudWatch -> S3 로 옮기는 버튼은 AWS 콘솔에 존재하지만
주기적으로 옮기는 UI 는 AWS 콘솔에 존재하지 않는다는 것이다.
즉, S3 Client 로 자체 어플리케이션을 만들어야한다는 것을 의미한다.
이 포스팅에서는 CloudWatch 에서 S3 로 로그를 옮기는 것 어플리케이션을 구축하는 것에 대해서만 설명합니다.
CloudWatch to S3
전체적인 개요는 아래의 이미지와 같다.
Lambda 에 어플리케이션을 등록시키고 EventBridge 를 이용해 주기적으로 Lambda 를 트리거한다.
그리고 Trigger 된 Lambda 는 지정한 CloudWatch Log Group 의 로그를 S3 버킷에 옮긴다.
https://medium.com/dnx-labs/exporting-cloudwatch-logs-automatically-to-s3-with-a-lambda-function-80e1f7ea0187
Lambda Application
AWS 를 사용한다면 모두 필요로 하는 작업이기에 이미 선구자가 있었다.
제일 유명해보이는 TerraForm 의 GitHub 코드를 참조하여 작업한다.GitHub - DNXLabs/terraform-aws-log-exporter: This module creates a lambda function that exports log groups on the AWS account an
This module creates a lambda function that exports log groups on the AWS account and region deployed. - GitHub - DNXLabs/terraform-aws-log-exporter: This module creates a lambda function that expor...
github.com
아래의 코드는 CloudWatch Log 를 S3 로 Exporting 하는 작업이며
SSM(AWS Systems Manager) 를 활용하여 해당 작업이 1일(특정기간)안에 수행이 되었는지 판단하여
수행이 되었다면 실행시키지 않는 코드이다.import boto3 import os from pprint import pprint import time logs = boto3.client('logs') ssm = boto3.client('ssm') def lambda_handler(event, context): extra_args = {} log_groups = [] log_groups_to_export = [] if 'S3_BUCKET' not in os.environ: print("Error: S3_BUCKET not defined") return print("--> S3_BUCKET=%s" % os.environ["S3_BUCKET"]) while True: response = logs.describe_log_groups(**extra_args) log_groups = log_groups + response['logGroups'] if not 'nextToken' in response: break extra_args['nextToken'] = response['nextToken'] for log_group in log_groups: response = logs.list_tags_log_group(logGroupName=log_group['logGroupName']) log_group_tags = response['tags'] if 'ExportToS3' in log_group_tags and log_group_tags['ExportToS3'] == 'true': log_groups_to_export.append(log_group['logGroupName']) for log_group_name in log_groups_to_export: ssm_parameter_name = ("/log-exporter-last-export/%s" % log_group_name).replace("//", "/") try: ssm_response = ssm.get_parameter(Name=ssm_parameter_name) ssm_value = ssm_response['Parameter']['Value'] except ssm.exceptions.ParameterNotFound: ssm_value = "0" export_to_time = int(round(time.time() * 1000)) print("--> Exporting %s to %s" % (log_group_name, os.environ['S3_BUCKET'])) if export_to_time - int(ssm_value) < (24 * 60 * 60 * 1000): # Haven't been 24hrs from the last export of this log group print(" Skipped until 24hrs from last export is completed") continue try: response = logs.create_export_task( logGroupName=log_group_name, fromTime=int(ssm_value), to=export_to_time, destination=os.environ['S3_BUCKET'], destinationPrefix=log_group_name.strip("/") ) print(" Task created: %s" % response['taskId']) time.sleep(5) except logs.exceptions.LimitExceededException: print(" Need to wait until all tasks are finished (LimitExceededException). Continuing later...") return except Exception as e: print(" Error exporting %s: %s" % (log_group_name, getattr(e, 'message', repr(e)))) continue ssm_response = ssm.put_parameter( Name=ssm_parameter_name, Type="String", Value=str(export_to_time), Overwrite=True) return ssm_response그리고 Lambda -> Configuration -> Environment Variables 탭에서
환경변수인 S3_BUCKET (S3 버킷명) 을 설정한다.
EventBridge 설정
포스팅이 방대해질 수 있으니 아래의 링크로 대체한다.
[AWS] EventBridge 에서 Lambda 를 Trigger 하기
Rule 생성 EventBrdige -> Rules 에서 Rule 생성 Schedule Job 으로 이벤트를 발생시킬 것인지, Event Pattern 으로 이벤트를 발생시킬지 선택하고 생성한다. Target 은 당연히 Lambda 로 생성하면된다. Resource Based Pol
developer-ping9.tistory.com
AWS 리소스에 대한 권한
위의 코드를 담은 Lambda 함수를 만든다해도 리소스에 대한 권한문제로 실행이 되지 않는다.
아래와 같이 설정한다.
더 아래에 이미지 설명도 같이 첨부하니 천천히 따라하시면 된다.저장할 S3 의 버킷 권한
저장할 S3 버킷을 만들고 해당 버킷에서
Permission 탭에서 Bucket Policy 부분을 아래와 같이 편집한다.{ "Version": "2012-10-17", "Statement": [ { "Sid": "GET Bucket ACL", "Effect": "Allow", "Principal": { "Service": "logs.amazonaws.com" }, "Action": "s3:GetBucketAcl", # 저장할 S3 의 ARN "Resource": "arn:aws:s3:::{$S3 버킷의 이름}" }, { "Sid": "Put Log", "Effect": "Allow", "Principal": { "Service": "logs.amazonaws.com" }, "Action": "s3:PutObject", # 저장할 S3 의 ARN의 하위리소스를 모두 허락 "Resource": "arn:aws:s3:::{$S3 버킷의 이름}/*" } ] }
실행할 Lambda 의 권한
작성된 Lambda -> Configuration -> Permssion 탭에서 Excution Role 을 클릭하여
Permission Policy 에 아래의 JSON 을 추가한다.
"Resource" 에 대한 부분은 본인리소스의 ARN 으로 채워넣는다.
아래에 이미지 설명이 있다.{ "Version": "2012-10-17", "Statement": [ { # Lambda 가 CloudWatch Logs 에 대한 수행권한 "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:DescribeLogGroups", "logs:ListTagsLogGroup", "logs:CreateExportTask" ], # CloudWatch ARN "Resource": "arn:aws:logs:us-east-1:{$계정번호}:*" }, { # Lambda 가 Systems Manger 에 대한 수행권한 (Systems Manager -> Application Management -> Parameter) "Effect": "Allow", "Action": [ "ssm:GetParameter", "ssm:PutParameter" ], # Systems Manager -> Application Management -> Parameter 의 ARN "Resource": "arn:aws:ssm:us-east-1:{$계정번호}:parameter/{$파라미터이름}" }, { # Lambda 가 자기자신의 CloudWatch LogGroup 에 대한 수행권한 "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": [ # Lambda 자기자신의 로그그룹 ARN "arn:aws:logs:us-east-1:{$계정번호}:log-group:/aws/lambda/{$람다함수이름}:*" ] }, { # Lambda 가 S3 에 대한 수행권한 "Effect": "Allow", "Action": [ "s3:*", "s3-object-lambda:*" ], "Resource": "*" } ] }CloudWatch 의 ARN 과 LogGroup 의 ARN
검정으로 칠해진 것이 AWS 계정번호이며
arn:aws:logs:us-east-1:{$계정번호}:* 는 us-east-1 리젼의 CloudWatch를 가르킨다.
arn:aws:logs:us-east-1:{$계정번호}:log-group:{$로그그룹명}:* 는 해당리젼의 로그그룹을 가르킨다.
그외 ARN 에 대해서는 위와 같은 방식으로 찾아가면 된다.
Reference
Exporting Cloudwatch Logs automatically to S3 with a Lambda function
The missing feature of Cloudwatch Logs.
medium.com
AWS: Permissions for exporting logs from Cloudwatch to Amazon S3
I am trying to export logs from one of my CloudWatch log groups into Amazon S3, using AWS console. I followed the guide from AWS documentation but with little success. My organization does not allo...
stackoverflow.com
728x90'Back End > AWS' 카테고리의 다른 글
[AWS] CloudWatch Log Insight value counts (CloudWatch Log Insight 에서 groupby count 사용하기) (0) 2022.12.17 [AWS] EventBridge 에서 Lambda 를 Trigger 하기 (0) 2022.11.13 [AWS] 서비스에 WAF 적용하기 (0) 2022.10.10 [AWS] BeanStalk(EC2) 에 wkhtmltopdf 라이브러리 설치하기 (0) 2022.09.25 [AWS] Lambda 에서 Lambda 를 호출하기 (Feat. JavaScript, Python) (0) 2022.09.17