[AWS] 자동화부터 재해복구까지 실전 서비스 하기

궁금하면 500원·2024년 12월 24일
0

데브옵스

목록 보기
26/36

1. AWS Backup

AWS의 주요 관리형 백업 서비스로, 다양한 AWS 리소스의 백업을 중앙에서 관리할 수 있게 해줍니다.
이 포스트에서는 AWS Backup의 기본 개념을 넘어 실제 엔터프라이즈 환경에서 활용할 수 있는 심화 내용을 다루겠습니다.

2. 백업 자동화 구현

2.1 AWS Lambda를 활용한 동적 백업 정책 관리

다음은 태그 기반으로 백업 정책을 동적으로 적용하는 Lambda 함수입니다.

import boto3
import json
from datetime import datetime

def lambda_handler(event, context):
    backup_client = boto3.client('backup')
    ec2_client = boto3.client('ec2')
    
    def get_instances_by_backup_tag():
        instances = []
        response = ec2_client.describe_instances(
            Filters=[
                {
                    'Name': 'tag:BackupPolicy',
                    'Values': ['Daily', 'Weekly', 'Monthly']
                }
            ]
        )
        
        for reservation in response['Reservations']:
            for instance in reservation['Instances']:
                instances.append({
                    'InstanceId': instance['InstanceId'],
                    'Tags': instance['Tags']
                })
        return instances
    
    def create_backup_selection(instances, plan_id):
        resources = []
        for instance in instances:
            resources.append(f"arn:aws:ec2:{boto3.session.Session().region_name}:{boto3.client('sts').get_caller_identity()['Account']}:instance/{instance['InstanceId']}")
        
        try:
            response = backup_client.create_backup_selection(
                BackupPlanId=plan_id,
                BackupSelection={
                    'SelectionName': f'DynamicSelection-{datetime.now().strftime("%Y%m%d")}',
                    'IamRoleArn': 'arn:aws:iam::YOUR_ACCOUNT_ID:role/service-role/AWSBackupDefaultServiceRole',
                    'Resources': resources,
                    'ListOfTags': [
                        {
                            'ConditionType': 'STRINGEQUALS',
                            'ConditionKey': 'BackupPolicy',
                            'ConditionValue': 'Daily'
                        }
                    ]
                }
            )
            return response
        except Exception as e:
            print(f"Error creating backup selection: {str(e)}")
            return None

    instances = get_instances_by_backup_tag()
    plan_id = 'YOUR_BACKUP_PLAN_ID'
    return create_backup_selection(instances, plan_id)

2.2 CloudWatch Events를 활용한 백업 모니터링

import boto3
import json

def lambda_handler(event, context):
    sns_client = boto3.client('sns')
    backup_client = boto3.client('backup')
    
    def check_backup_job_status():
        response = backup_client.list_backup_jobs(
            ByState='FAILED'
        )
        
        failed_jobs = []
        for job in response['BackupJobs']:
            failed_jobs.append({
                'JobId': job['BackupJobId'],
                'ResourceType': job['ResourceType'],
                'ResourceArn': job['ResourceArn'],
                'State': job['State'],
                'CreationDate': str(job['CreationDate'])
            })
        
        return failed_jobs
    
    failed_jobs = check_backup_job_status()
    
    if failed_jobs:
        message = "다음 백업 작업이 실패했습니다:\n\n"
        for job in failed_jobs:
            message += f"Job ID: {job['JobId']}\n"
            message += f"Resource: {job['ResourceType']} ({job['ResourceArn']})\n"
            message += f"생성일: {job['CreationDate']}\n\n"
        
        sns_client.publish(
            TopicArn='arn:aws:sns:REGION:ACCOUNT_ID:BackupAlerts',
            Subject='AWS Backup 작업 실패 알림',
            Message=message
        )

    return {
        'statusCode': 200,
        'body': json.dumps('백업 상태 확인 완료')
    }

3. 재해 복구 시나리오 구현

3.1 크로스 리전 복구 자동화

import boto3
import json

def lambda_handler(event, context):
    source_region = 'ap-northeast-2'  # 서울 리전
    destination_region = 'ap-northeast-1'  # 도쿄 리전
    
    source_backup = boto3.client('backup', region_name=source_region)
    destination_backup = boto3.client('backup', region_name=destination_region)
    
    def copy_backup_across_region(recovery_point_arn):
        try:
            response = source_backup.copy_into_backup_vault(
                RecoveryPointArn=recovery_point_arn,
                SourceBackupVaultName='Default',
                DestinationBackupVaultArn=f'arn:aws:backup:{destination_region}:{boto3.client("sts").get_caller_identity()["Account"]}:backup-vault:Default',
                IamRoleArn=f'arn:aws:iam::{boto3.client("sts").get_caller_identity()["Account"]}:role/service-role/AWSBackupDefaultServiceRole'
            )
            return response
        except Exception as e:
            print(f"Error copying backup: {str(e)}")
            return None
    
    def get_latest_successful_backup():
        response = source_backup.list_recovery_points_by_backup_vault(
            BackupVaultName='Default',
            ByStatus='COMPLETED',
            MaxResults=1
        )
        
        if response['RecoveryPoints']:
            return response['RecoveryPoints'][0]['RecoveryPointArn']
        return None
    
    recovery_point_arn = get_latest_successful_backup()
    if recovery_point_arn:
        return copy_backup_across_region(recovery_point_arn)
    else:
        return {
            'statusCode': 404,
            'body': json.dumps('No completed backup found')
        }

4. 비용 최적화 전략

4.1 수명 주기 정책 자동화

import boto3
from datetime import datetime, timedelta

def lambda_handler(event, context):
    backup_client = boto3.client('backup')
    
    def update_lifecycle_policy():
        try:
            response = backup_client.update_backup_plan(
                BackupPlanId='YOUR_BACKUP_PLAN_ID',
                BackupPlan={
                    'BackupPlanName': 'OptimizedBackupPlan',
                    'Rules': [
                        {
                            'RuleName': 'DailyBackups',
                            'TargetBackupVaultName': 'Default',
                            'ScheduleExpression': 'cron(0 0 * * ? *)',
                            'StartWindowMinutes': 60,
                            'CompletionWindowMinutes': 120,
                            'Lifecycle': {
                                'MoveToColdStorageAfterDays': 30,
                                'DeleteAfterDays': 90
                            }
                        }
                    ]
                }
            )
            return response
        except Exception as e:
            print(f"Error updating backup plan: {str(e)}")
            return None
    
    return update_lifecycle_policy()

5. 보안 강화 방안

5.1 Vault Lock 정책 구현

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyDeleteRecoveryPoint",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "backup:DeleteRecoveryPoint"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotLike": {
                    "aws:PrincipalArn": [
                        "arn:aws:iam::*:role/BackupAdminRole"
                    ]
                }
            }
        },
        {
            "Sid": "DenyBackupVaultDelete",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "backup:DeleteBackupVault",
                "backup:DeleteBackupVaultAccessPolicy",
                "backup:DeleteBackupVaultNotifications",
                "backup:UpdateBackupVault"
            ],
            "Resource": "*"
        }
    ]
}

6. 모니터링 및 알림 시스템

6.1 CloudWatch 대시보드 생성

import boto3
import json

def create_backup_dashboard():
    cloudwatch = boto3.client('cloudwatch')
    
    dashboard_body = {
        "widgets": [
            {
                "type": "metric",
                "properties": {
                    "metrics": [
                        ["AWS/Backup", "NumberOfBackupJobsCompleted", "BackupVaultName", "Default"],
                        [".", "NumberOfBackupJobsFailed", ".", "."]
                    ],
                    "period": 300,
                    "stat": "Sum",
                    "region": "ap-northeast-2",
                    "title": "백업 작업 상태"
                }
            },
            {
                "type": "metric",
                "properties": {
                    "metrics": [
                        ["AWS/Backup", "NumberOfRecoveryPointsCreated", "BackupVaultName", "Default"]
                    ],
                    "period": 300,
                    "stat": "Sum",
                    "region": "ap-northeast-2",
                    "title": "생성된 복구 지점"
                }
            }
        ]
    }
    
    try:
        response = cloudwatch.put_dashboard(
            DashboardName='BackupMonitoring',
            DashboardBody=json.dumps(dashboard_body)
        )
        return response
    except Exception as e:
        print(f"Error creating dashboard: {str(e)}")
        return None

def lambda_handler(event, context):
    return create_backup_dashboard()

7. 성능 최적화 팁

  • EBS 스냅샷 생성 시 인스턴스 중지 없이 백업하기 위한 VSS(Volume Shadow Copy Service) 활용
  • RDS 백업 시 읽기 복제본을 통한 백업으로 프로덕션 DB 부하 감소
  • 백업 윈도우 시간을 트래픽이 적은 시간대로 설정
  • 증분 백업을 활용한 백업 시간 최소화

결론

AWS Backup은 엔터프라이즈급 백업 솔루션으로서, 적절한 자동화와 모니터링을 통해 안정적인 백업 환경을 구축할 수 있습니다.
위에서 다룬 예제들을 기반으로 각 조직의 요구사항에 맞는 백업 전략을 수립하시기 바랍니다.

참초 관련 URL 링크

profile
꾸준히, 의미있는 사이드 프로젝트 경험과 문제해결 과정을 기록하기 위한 공간입니다.

0개의 댓글