AWS-CICD

AWS Auto Scaling 환경에서 CodeDeploy + Lambda로 Rolling Update 배포 자동화하기

backend 따라쟁이 2025. 4. 18. 23:11

✨ 개요

Auto Scaling Group(ASG)은 EC2 인스턴스를 자동으로 확장/축소하고, 장애 복구를 수행할 수 있는 강력한 서비스입니다. 그러나 배포 전략이 명확하지 않으면 새로 생성되는 인스턴스가 구버전 애플리케이션을 포함한 AMI로 생성되는 문제가 발생할 수 있습니다.

이 글에서는 CodeDeploy로 EC2 인스턴스에 애플리케이션을 배포하고, 그 인스턴스를 기반으로 새로운 AMI를 자동 생성, 이를 Launch Template에 반영한 후 Rolling Update로 전체 인스턴스를 교체하는 방식을 실습 가능한 코드와 함께 소개합니다.

🧠 Auto Scaling 환경에서 배포 전략이 중요한 이유

1️⃣ 일반적인 배포 시나리오

[1] EC2 인스턴스에 CodeDeploy로 애플리케이션 배포
[2] 배포는 완료되었지만 ASG의 Launch Template은 여전히 구버전 AMI
[3] ASG가 새 인스턴스를 생성하면? → 애플리케이션이 없는 상태 😨

2️⃣ 해결 전략: AMI 기반 배포 + Rolling Update

[1] 배포 완료된 인스턴스에서 AMI 생성
[2] 해당 AMI로 Launch Template 업데이트
[3] ASG에서 Rolling Update 수행 (기존 인스턴스를 새 AMI 기반으로 교체)

🔁 Rolling Update란?

기존 Auto Scaling Group을 유지하면서, 새 AMI를 기반으로 기존 인스턴스를 하나씩 교체하는 방식입니다. 무중단 배포에 가까우며, 비용도 효율적으로 관리할 수 있습니다.


🧪 실습: CodeDeploy + Lambda로 자동 Rolling Update 구성하기

Auto Scaling Group(ASG) 환경에서 EC2 인스턴스에 CodeDeploy로 Application을 배포한 후, 배포된 인스턴스를 기반으로 AMI를 생성하고, 이 AMI를 ASG의 Launch Template에 반영하여 전체 인스턴스를 Rolling Update로 교체하는 과정을 Lambda 함수 하나로 자동화하는 것을 목표로 합니다.


🔄 전체 배포 흐름 요약

[1] CodeDeploy 배포 완료 (Success)
    ↓ (EventBridge)
[2] Lambda 함수 실행
    ├─ 1) 대표 인스턴스에서 AMI 생성
    ├─ 2) Launch Template에 새 버전 생성
    └─ 3) ASG 인스턴스를 Rolling Update로 교체

✅ 사전 준비 사항

항목설명

EC2 인스턴스 ASG에 연결된 상태이며 CodeDeploy Agent 설치됨
CodeDeploy 배포 애플리케이션 및 배포 그룹 구성
S3 appspec.yml 및 배포 스크립트 저장소
ASG 기존 Launch Template 기반으로 EC2 인스턴스 1대 이상 운영 중
IAM Lambda가 EC2, AutoScaling, CodeDeploy 작업 가능하도록 정책 부여
EventBridge CodeDeploy 배포 성공 이벤트를 Lambda로 연결

 


📝 Lambda 함수 전체 코드 (Python, Boto3)

아래 코드는 CodeDeploy 배포 성공 이벤트를 받아 자동으로 AMI 생성 → Launch Template 업데이트 → ASG 롤링 갱신까지 수행합니다.

import boto3
import time

codedeploy = boto3.client('codedeploy')
ec2 = boto3.client('ec2')
autoscaling = boto3.client('autoscaling')

LAUNCH_TEMPLATE_ID = "lt-0example123456"  # 본인의 Template ID로 교체
ASG_NAME = "my-auto-scaling-group"       # 본인의 ASG 이름으로 교체

def create_ami(instance_id):
    timestamp = time.strftime('%Y%m%d-%H%M%S')
    ami_name = f"auto-ami-{timestamp}"
    response = ec2.create_image(
        InstanceId=instance_id,
        Name=ami_name,
        Description="AMI created by Lambda after CodeDeploy success",
        NoReboot=True
    )
    return response['ImageId']

def create_launch_template_version(ami_id):
    response = ec2.create_launch_template_version(
        LaunchTemplateId=LAUNCH_TEMPLATE_ID,
        SourceVersion='$Latest',
        LaunchTemplateData={
            'ImageId': ami_id
        }
    )
    return response['LaunchTemplateVersion']['VersionNumber']

def start_instance_refresh():
    autoscaling.start_instance_refresh(
        AutoScalingGroupName=ASG_NAME,
        Strategy='Rolling',
        Preferences={
            'MinHealthyPercentage': 50,
            'InstanceWarmup': 180
        }
    )

def lambda_handler(event, context):
    print("Event received:", event)
    deployment_id = event["detail"]["deploymentId"]

    # 배포된 인스턴스 목록 조회
    instances = codedeploy.list_deployment_instances(
        deploymentId=deployment_id
    )["instancesList"]

    if not instances:
        raise Exception("No instances found for deployment")

    target_instance_id = instances[0]  # 첫 번째 인스턴스를 대표로 사용
    print(f"Using instance {target_instance_id} for AMI creation")

    ami_id = create_ami(target_instance_id)
    version = create_launch_template_version(ami_id)
    start_instance_refresh()

    return {
        'statusCode': 200,
        'body': f"Created AMI {ami_id}, updated launch template version {version}, and started ASG instance refresh"
    }

🔐 EventBridge 구성

  1. 이벤트 소스: CodeDeploy
  2. 이벤트 패턴:
{
  "source": ["aws.codedeploy"],
  "detail-type": ["CodeDeploy Deployment State-change Notification"],
  "detail": {
    "state": ["SUCCESS"]
  }
}
  1. 대상: 위 Lambda 함수 연결

🔐 Lambda IAM 권한 예시

{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": ["codedeploy:ListDeploymentInstances"], "Resource": "*" },
    { "Effect": "Allow", "Action": ["ec2:CreateImage", "ec2:CreateLaunchTemplateVersion"], "Resource": "*" },
    { "Effect": "Allow", "Action": ["autoscaling:StartInstanceRefresh"], "Resource": "*" }
  ]
}

 

[참고] CodeDeploy 성공 시 Lambda로 AMI 생성 및 ASG 롤링 업데이트 자동화

https://backend-java.tistory.com/58

 

CodeDeploy 성공 시 Lambda로 AMI 생성 및 ASG 롤링 업데이트 자동화 – 조건부 트리거 설정까지!

배포가 끝이 아니라 시작입니다. 운영 환경까지 자동으로 정비되는 DevOps 파이프라인을 구축해보세요.🧩 시나리오CI/CD 환경에서 CodeDeploy를 통해 EC2 인스턴스에 애플리케이션을 성공적으로 배포

backend-java.tistory.com

 


✅ 실습 후 점검사항

항목확인할 내용
AMI 생성 여부 EC2 → AMI 메뉴에서 확인 가능
Launch Template 버전 증가 EC2 → Launch Template에서 새 버전 확인
ASG Instance 교체 EC2 인스턴스가 순차적으로 재기동되는지 확인

 


🌟 결론

이 구성을 통해, 개발자가 직접 서버를 관리하지 않아도 배포 → AMI 생성 → 롤링 업데이트까지 전 과정을 자동화할 수 있습니다. 운영 비용과 실수는 줄이고, 배포 일관성과 안정성은 높일 수 있는 베스트 프랙티스입니다.

추가로 CloudFormation 템플릿이나 Terraform 모듈과 연동해 인프라 전체를 코드로 관리할 수도 있습니다.