본문 바로가기
Amazon AWS/S3

S3의 불필요한 객체들을 정리하도록 Lambda 작성

by 홍띠 2023. 3. 13.

이전에 Lambda함수를 이용해서 클라우드 워치의 로그를 S3에 백업하도록 구성하였다. 

Cloudwatch의 로그 S3 백업을 자동화 하기(w/ AWS Lambda)

이때 AWS에서 제공하는 boto3 메소드를 이용했는데, 이렇게 이용하면 불필요한 파일과 디렉토리가 생성된다.

위에 첨부된 사진과 같이 aws-logs-write-test 파일이 모든 디렉토리에 생성되고,

taskId명으로 생긴 폴더 내부에 또 새로운 폴더가 생성되고 백업된 로그 파일이 생성된다.

또한, 테스트파일은 해당일자에 로그가 없어서 디렉토리 생성이 필요가 없을때에도 생성된다.

 

따라서, 이렇게 불필요한 파일과 디렉토리를 정리하는 코드를 추가하였다.

import os
import datetime
import time
import boto3
from botocore.exceptions import ClientError

'''
get environment Variables
'''
bucket = os.environ['S3_BUCKET']
s3 = boto3.resource('s3')
s3Bucket = s3.Bucket(bucket)

def move_log_and_cleanup_objects(destination_prefix,taskId,stream_prefix):
    # copy log
    try:
        for obj in s3Bucket.objects.filter(Prefix='%s/%s/%s' % (destination_prefix,taskId,stream_prefix.replace('/','-'))):
            src = {'Bucket': bucket, 'Key': obj.key}
            dst = '%s/%s' % (destination_prefix,obj.key.split('/')[-1])
            s3Bucket.Object(dst).copy(src)
        copy = True
    except ClientError as e:
        if e.response['Error']['Code'] == 'NoSuchKey':
            print(f'The object with prefix {destination_prefix} does not exist ')
        else:
        copy = False
    #clean up
    if(copy):
        s3Bucket.objects.filter(Prefix='%s/%s' % (destination_prefix,taskId)).delete()
        s3Bucket.objects.filter(Prefix='%s/aws-logs-write-test' % (destination_prefix)).delete()
        return 'Successfully moved %s and cleanup' % taskId
    return 'Fail moved %s and cleanup' % taskId

def lambda_handler(event, context):
	# eventbridge로 부터 log group 전달 받음, 버킷명과 마찬가지로 코드에 하드코딩 해도 됨!
    parameter = event['Parameters']
    logGroup = parameter['logGroup']

'''
set S3 subfolders' structure
S3에 저장될 경로 지정, 여기서는 아래 경로로 저장됨
S3://<BUCKET NAME>/<LOG GROUP>/<YEAR>/<MONTH>/<DAY>/
'''
    prefix = os.path.join(logGroup, startTime.strftime('%Y{0}%m{0}%d').format(os.path.sep))
    stream_prefix = '{0}'.format(startTime.strftime('%Y/%m/%d'))
    
    client = boto3.client('logs')
    try:
        response = client.create_export_task(
             logGroupName=logGroup,
             logStreamNamePrefix=stream_prefix,
             fromTime=fromDate,
             to=toDate,
             destination=bucket,
             destinationPrefix=prefix
            )
        taskId = response['taskId']
        print("Task created: %s" % taskId)
        status = 'RUNNING'
        while status in ['RUNNING','PENDING']:
            response_desc = logClient.describe_export_tasks(
                taskId=taskId
            )
            status = response_desc['exportTasks'][0]['status']['code']
            time.sleep(3)

        print(move_log_and_cleanup_objects(destination_prefix,taskId,stream_prefix))
    except ClientError as error:
        raise error