AWS EC2 Blue/Green CI/CD, CI/CD Pipline

유정빈·2026년 5월 27일

CI/CD 소개

CI/CD(지속적 통합 및 지속적 배포)는 빠르고 신뢰할 수 있는 소프트웨어 전달을 달성하기 위해 애플리케이션의 빌드, 테스트 및 배포를 자동화하는 소프트웨어 개발 프로세스입니다.

1. 지속적 통합 (Continuous Integration, CI)

CI/CD 과정은 지속적 통합(CI)에서 시작됩니다. 개발자들은 코드를 공유 저장소에 자주 병합하며, 이러한 변경 사항은 즉시 자동화된 빌드 및 테스트 프로세스를 트리거합니다. 통합 테스트를 통해 잠재적인 문제를 조기에 발견함으로써 코드 품질을 보장합니다.

2. 지속적 배포 (Continuous Deployment, CD)

다음으로 지속적 배포(CD)는 테스트가 완료된 애플리케이션을 자동으로 운영 환경에 배포합니다. 이 자동화된 프로세스는 인적 오류를 줄이고 배포 속도를 획기적으로 높입니다. 배포 파이프라인을 통해 테스트 및 검토 후 언제든지 대상 환경에 애플리케이션을 안전하게 출시할 수 있습니다.

3. 컨테이너화와 CI/CD

현대 CI/CD 프로세스에서 컨테이너화는 매우 중요한 역할을 합니다. Docker와 같은 컨테이너 기술은 애플리케이션과 그 의존성을 격리된 환경에서 패키징하여, 서로 다른 환경에서도 일관된 작동을 보장합니다. 이는 배포 과정을 단순화할 뿐만 아니라 애플리케이션의 이동성과 확장성을 향상시킵니다.

4. 고급 배포 전략: Blue-Green 배포

Blue-Green 배포는 컨테이너 환경에 특히 적합한 전략입니다. 이 전략에서는 'Blue'와 'Green'이라는 두 개의 동일하지만 독립적인 생산 환경을 유지합니다.

  1. 새 버전은 비활성 환경(예: Green)에 배포됩니다.
  2. 테스트 및 검증이 완료되면 트래픽을 Green으로 전환합니다.
  3. 문제가 발생하면 즉시 이전 버전(Blue)으로 트래픽을 돌릴 수 있어 다운타임이 거의 없습니다.




프로젝트 컨테이너화 및 개인 이미지 저장소 설정

이 섹션에서는 Node.js 프로젝트를 컨테이너화하고, 이미지가 정상적으로 작동하는지 확인한 후 AWS ECR에 저장하는 과정을 다룹니다.

ECR(Elastic Container Registry)이란?

일관되고 가벼운 컨테이너 런타임 환경을 위해 빌드된 이미지들을 저장하는 곳이 컨테이너 이미지 레지스트리입니다. 대표적으로 '도커 허브'가 있으며, AWS에서 제공하는 관리형 OCI 표준 이미지 저장소 서비스가 바로 AWS ECR입니다.


실습 환경 준비: AWS CloudShell

AWS Workshop에서 제공하는 샘플 웹사이트 프로젝트를 사용하여 실습을 진행합니다. 개발 환경으로는 AWS CLI와 주요 도구들이 미리 구성된 AWS CloudShell을 사용합니다.

  1. AWS 콘솔 상단의 CloudShell 버튼을 클릭하여 실행합니다.
  2. 실습 프로젝트 파일(pureweb.zip)을 업로드합니다.
  3. 터미널에서 압축을 해제합니다.
unzip -qq pureweb.zip
ls

프로젝트 코드 분석 (Node.js)

00 폴더에는 기본 HTTP 서버 코드(index.js)와 의존성 목록(package.json)이 들어있습니다. 루트 경로(/) 방문 시 현재 시간을 반환하는 단순한 서버입니다.

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  return res.send(`OK - ${new Date()}`)
});

app.listen(port, () => {
  return console.log(`Example app listening on port ${port}`)
});

로컬 테스트 및 컨테이너화

1. 의존성 설치 및 실행

# Node.js 버전 확인
node --version

# 라이브러리 설치
npm install

# 서버 시작
node index.js

서버가 실행되면 Example app listening on port 3000 메시지가 출력됩니다.

2. 작동 확인

다른 탭에서 curl을 통해 응답을 확인합니다.

curl http://localhost:3000


Docker를 이용한 컨테이너화

애플리케이션을 실행하기 위해 거쳤던 과정(OS 준비, 환경 설정, 라이브러리 설치, 실행)을 하나의 이미지로 굽는 과정입니다.

1. Dockerfile 작성

01 폴더에는 위 과정을 자동화한 Dockerfile이 포함되어 있습니다.

  • Base Image: AWS 공개 ECR의 Node.js 이미지를 사용
  • Workdir: 작업 경로 정의
  • Dependency: npm install 실행
  • Port: 3000 포트 노출
  • Command: 서비스 실행 명령 정의

2. Docker 이미지 빌드

먼저 공개 ECR 이미지를 가져오기 위해 로그인을 진행한 후 빌드를 시작합니다.

# Public ECR 로그인
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws

# 이미지 빌드
docker build . -t pureweb

3. 빌드 결과 확인

docker images



##  AWS ECR에 이미지 푸시

빌드된 이미지를 AWS 개인 저장소(ECR)에 업로드하여 관리합니다. 이 과정은 AWS 콘솔에서 리포지토리를 먼저 생성한 뒤 진행합니다.

### 1. AWS 콘솔에서 ECR 리포지토리 생성
캡처 화면은 생략되었지만, 다음 순서로 간단히 생성할 수 있습니다.

1. AWS 관리 콘솔 검색창에 **ECR**을 입력하고 **Elastic Container Registry**로 이동합니다.
2. 왼쪽 메뉴에서 **Repositories**를 선택한 후, 우측 상단의 **Create repository** 버튼을 클릭합니다.
3. **General settings**에서 다음을 설정합니다:
   - **Visibility settings**: `Private` 선택
   - **Repository name**: `pureweb-repo` 입력
4. 페이지 하단의 **Create repository**를 클릭하여 생성을 완료합니다.

>  **Tip: CLI로 생성하고 싶다면?**
> 콘솔이 번거롭다면 다음 명령어로 즉시 생성할 수도 있습니다:
> `aws ecr create-repository --repository-name pureweb-repo --region ap-northeast-2`

### 2. ECR 로그인 및 이미지 태그 설정
리포지토리가 생성되었다면, 이제 CloudShell에서 이미지를 업로드할 차례입니다. 생성된 리포지토리의 **View push commands** 버튼을 누르면 나오는 명령어를 참고해도 좋습니다.

```bash
# 1. ECR 로그인 (계정 ID 확인 및 인증 토큰 가져오기)
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-2.amazonaws.com

# 2. 이미지 태그 설정 (로컬 이미지를 ECR 주소와 매칭)
docker tag pureweb:latest ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-2.amazonaws.com/pureweb-repo:latest

3. 이미지 푸시(Push) 실행

# ECR 저장소로 이미지 전송
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-2.amazonaws.com/pureweb-repo:latest

이제 ECR 리포지토리 목록에서 푸시된 이미지를 확인할 수 있습니다. 저장된 이미지는 이후 ECS 서비스의 새로운 버전으로 배포되어, 실제 Blue-Green 배포 파이프라인의 핵심 리소스로 사용됩니다.

AWS ECS 서비스 구축

컨테이너 이미지를 ECR에 안전하게 저장했다면, 이제 이 이미지를 사용하여 Amazon ECS(Elastic Container Service) 환경을 구축할 차례입니다. ECS는 작업 정의(Task Definition)를 통해 클러스터 내에서 컨테이너를 실행하고 관리합니다.

ECS 구축 단계 요약

  1. 이미지 준비: 컨테이너 이미지를 AWS ECR에 저장합니다. (완료)
  2. 작업 정의 생성: 실행할 컨테이너의 스펙(이미지 주소, CPU/메모리, 포트 등)을 정의합니다.
  3. 클러스터 생성: 인프라 리소스의 논리적 그룹을 생성합니다.
  4. 서비스 실행: 작업 정의를 바탕으로 클러스터 내에서 실제 컨테이너 작업을 실행합니다.
  5. 로드 밸런서 연결: ALB와 연결하여 외부 트래픽을 컨테이너로 유도합니다.
  6. 네트워크 흐름: 사용자는 ALB(80 포트)로 접근하고, 트래픽은 대상 그룹(Target Group)을 거쳐 ECS 컨테이너(3000 포트)로 전달됩니다.
  7. 보안 설정: IAM 역할과 보안 그룹을 적용하여 서비스 안전성을 확보합니다.

1. IAM 역할(Role) 설정

ECS와 관련 서비스들이 상호작용하기 위해 필요한 권한을 설정합니다.

ECS 작업 역할 (Task Role)

  • 용도: 실행 중인 컨테이너 애플리케이션이 다른 AWS 서비스(S3, DynamoDB 등)를 사용할 때 필요한 권한입니다.
  • 설정: IAM → 역할 만들기 → AWS 서비스 → Elastic Container ServiceElastic Container Service Task 선택.
  • 이름: role-ecs-pureweb (현재 앱은 외부 서비스를 쓰지 않으므로 정책 연결 없이 생성)

ECS 작업 실행 역할 (Task Execution Role)

  • 용도: ECS 에이전트가 ECR에서 이미지를 풀(Pull)하거나 CloudWatch로 로그를 보낼 때 필요한 권한입니다.
  • 정책: AmazonECSTaskExecutionRolePolicy 연결.
  • 이름: role-ecs-task-execution

CodeDeploy 역할

  • 용도: Blue-Green 배포 시 CodeDeploy가 ECS 서비스를 제어할 권한입니다.
  • 사용 사례: CodeDeploy - ECS 선택.
  • 이름: role-ecs-codedeploy


2. 보안 그룹(Security Group) 구성

방화벽 규칙을 통해 트래픽 흐름을 제어합니다.

ALB 보안 그룹 (sg_alb-pureweb)

  • 인바운드 규칙: HTTP (80) / Source: 0.0.0.0/0 (모든 트래픽 허용)
  • 설명: 외부 사용자의 웹 접속을 허용합니다.

ECS 보안 그룹 (sg_ecs-pureweb)

  • 인바운드 규칙: Custom TCP (3000) / Source: 0.0.0.0/0 (테스트용)
  • 설명: ALB로부터 들어오는 컨테이너 포트(3000) 트래픽을 허용합니다.


3. 애플리케이션 로드 밸런서(ALB) 및 대상 그룹 설정

Blue-Green 배포를 위해 두 개의 대상 그룹을 생성하고 ALB 리스너를 설정합니다.

대상 그룹(Target Group) 생성

Blue-Green 배포 전략을 위해 tg-pureweb-Atg-pureweb-B 두 개를 만듭니다.

  1. 유형: IP 주소
  2. 프로토콜/포트: HTTP / 3000
  3. 이름: tg-pureweb-A, tg-pureweb-B
  4. 대상 등록: 현재 실행 중인 작업이 없으므로 건너뜁니다.


ALB 생성 및 리스너 규칙 설정

  1. 이름: alb-pureweb / 방식: 인터넷 방향
  2. 네트워크: 가용 영역(AZ) 1a, 1b 선택
  3. 보안 그룹: sg_alb-pureweb 선택
  4. 리스너: 80 포트 → tg-pureweb-A로 전달

자동화된 CI/CD 블루-그린 파이프라인 구축

개요

지금까지 ECR에 이미지를 등록하고 ECS 및 ALB를 구성하여 초기 배포를 성공적으로 마쳤습니다. 이제 이 과정을 자동화하여 소스 코드가 수정될 때마다 자동으로 빌드와 블루-그린 배포가 진행되도록 CI/CD 파이프라인을 구축해 보겠습니다.

사용될 서비스와 각 단계의 역할은 다음과 같습니다:

  • AWS CodePipeline: 전체 CI/CD 프로세스를 오케스트레이션하고 시각적인 파이프라인 흐름을 제공합니다.
  • Source (소스 단계): AWS S3를 사용하여 버전 관리 시스템을 시뮬레이션합니다. 코드가 변경(업로드)되면 파이프라인을 트리거합니다.
  • Build (빌드 단계): AWS CodeBuild가 트리거되어 소스를 다운로드하고, 패키지 설치 및 Docker 이미지를 빌드하여 Amazon ECR에 푸시합니다.
  • Deploy (배포 단계): AWS CodeDeploy를 통해 ECS에 새 버전의 컨테이너를 블루-그린 방식으로 무중단 배포합니다.

1. 버전 관리용 S3 버킷 생성 (Source)

버전 관리 시스템을 대신할 S3 버킷을 만듭니다. CI/CD 트리거를 위해서는 반드시 버킷의 버전 관리가 활성화되어 있어야 합니다.

  1. AWS S3 콘솔의 왼쪽 메뉴에서 버킷 리스트 페이지로 들어갑니다.
  2. 버킷 만들기를 클릭합니다.
    • 버킷 이름: bucket-source-{본인이름}-{날짜}
    • 버킷 버전 관리: 활성화(Enable) 선택
  3. 설정을 마치고 버킷 생성을 완료합니다.

2. AWS CodePipeline 생성 및 소스 단계 설정

  1. AWS CodePipeline 콘솔에서 파이프라인 생성을 클릭합니다.
    • 카테고리: 사용자 지정 파이프라인 빌드 (Custom pipeline)
    • 파이프라인 이름: pipeline-ecs-blue-green
    • 실행 모드: 대체(Superseded)
    • 서비스 역할: '새 서비스 역할' 선택 후, 역할 이름에 role-codepipeline 입력
  2. 소스 단계 설정:
    • 소스 공급자: Amazon S3
    • 버킷: 방금 만든 bucket-source-{yourname}-{date} 버킷 선택
    • S3 객체 키: Archive.zip (이 파일은 설정이 완료된 후 나중에 업로드합니다.)
    • '스테이지 실패 시 자동 재시도 활성화'를 체크 해제하고 다음으로 넘어갑니다.

3. 빌드 단계 구성 (CodeBuild)

  1. 빌드 제공자AWS CodeBuild를 선택하고 프로젝트 생성을 클릭합니다.
  2. CodeBuild 프로젝트 설정 창이 열리면 다음과 같이 설정합니다. 이는 실제 온라인 환경에 맞게 런타임을 구성하기 위함입니다:
    • 프로젝트 이름: buildproject-pureweb-ecs
    • 추가 구성: 동시 빌드 수 제한을 1로 설정
    • 서비스 역할: '새 서비스 역할'을 선택하고 역할 이름에 role-codebuild 지정
    • 권한 승격(Privileged): Docker 이미지를 빌드해야 하므로 이 플래그를 활성화합니다.
    • Buildspec: '빌드스펙 파일 사용'을 선택
  3. 다른 설정은 기본값으로 두고 CodePipeline으로 계속을 클릭하여 파이프라인 설정 화면으로 돌아옵니다.
  4. 입력 아티팩트SourceArtifact를 선택하고 다음으로 넘어갑니다. (자동 재시도 활성화 체크 해제)

4. 테스트 및 배포 단계 일시 건너뛰기

배포(Deploy) 구성 파일이 아직 준비되지 않았으므로 먼저 파이프라인 생성을 완료합니다.
1. 테스트 단계'테스트 단계 건너뛰기'를 클릭합니다.
2. 배포 단계 또한 실패 시 자동 롤백/재시도 체크를 해제하고 '배포 단계 일시적으로 건너뛰기'를 클릭합니다.
3. 파이프라인 설정을 검토하고 파이프라인 생성을 완료합니다.

참고: 파이프라인이 생성되면 바로 실행되지만 소스 단계에서 오류가 발생하는 것이 정상입니다. S3 버킷에 아직 Archive.zip 파일을 업로드하지 않았기 때문입니다.


5. IAM 역할 권한 추가

생성한 파이프라인이 CodeDeploy와 ECS 등 다른 리소스에 접근하고 제어할 수 있도록 IAM 역할에 권한을 추가해야 합니다.

CodePipeline 역할 권한 부여 (role-codepipeline)

  1. IAM 콘솔의 역할(Roles) 메뉴에서 role-codepipeline을 찾습니다.
  2. 권한 탭 > 권한 추가 > 인라인 정책 생성을 선택하고 JSON 편집 패널에 아래 정책을 붙여넣습니다.
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "AllowCodeDeployDeploymentActions",
			"Action": [
				"codedeploy:CreateDeployment",
				"codedeploy:GetDeployment",
				"codedeploy:GetApplication",
				"codedeploy:GetApplicationRevision",
				"codedeploy:RegisterApplicationRevision",
				"codedeploy:GetDeploymentConfig",
				"ecs:RegisterTaskDefinition"
			],
			"Resource": [
				"*"
			],
			"Effect": "Allow"
		},
		{
			"Sid": "AllowPassRoleToECS",
			"Effect": "Allow",
			"Action": "iam:PassRole",
			"Resource": [
				"*"
			],
			"Condition": {
				"StringEquals": {
					"iam:PassedToService": [
						"ecs.amazonaws.com",
						"ecs-tasks.amazonaws.com"
					]
				}
			}
		}
	]
}
  1. 정책 이름으로 policy-codeploy-to-ecs를 입력하고 생성합니다.

CodeBuild 역할 권한 부여 (role-codebuild)

  1. 다시 IAM 콘솔 역할 목록에서 role-codebuild를 찾습니다.
  2. 권한 탭 > 권한 추가 > 정책 연결을 클릭하여 다음 두 가지 정책을 추가합니다:
    • AmazonEC2ContainerRegistryPowerUser
    • AmazonElasticContainerRegistryPublicPowerUser

6. 빌드 및 배포 구성 파일 준비

CodeBuild와 CodeDeploy가 참조할 환경 설정 파일을 준비합니다. 컴퓨터의 02 폴더 내 실습 파일을 다음과 같이 수정합니다.

  1. taskdef.yml (ECS 작업 정의):

    • AWS 콘솔의 ECS 작업 정의 페이지에서 기존 JSON 문서를 복사하여 02/taskdef.yml 파일 내용을 덮어씁니다.
    • containerDefinitions.image의 값(URL)을 <ImageURI> 플레이스홀더 텍스트로 교체합니다.
    • 문서 하단에 있는 tags 블록은 삭제합니다.
  2. buildspec.yml (CodeBuild 실행 스크립트):

    • 프로젝트 빌드 시 수행할 명령어가 들어있습니다. 내부의 모든 {ACCOUNT_ID} 텍스트를 사용 중인 샌드박스 계정 ID로 교체합니다.

7. 파이프라인 배포(Deploy) 단계 추가

이제 준비된 설정 파일을 바탕으로 CodePipeline에 최종 배포 단계를 추가합니다. CodePipeline 페이지로 돌아와 pipeline-ecs-blue-green편집(Edit)을 클릭합니다.

  1. 빌드 스테이지 수정:
    • 빌드 작업의 연필 모양 아이콘을 클릭합니다.
    • 출력 아티팩트에서 기존 빌드 아티팩트를 삭제하고, DefinitionArtifactImageArtifact 두 개를 새로 추가한 뒤 완료를 누릅니다.
  2. 배포 스테이지 추가:
    • 페이지 하단의 스테이지 추가를 클릭하고 이름을 Deploy로 지정합니다.
    • 액션 이름: deploy-blue-green-for-ecs
    • 액션 공급자: Amazon ECS (블루/그린)
    • 입력 아티팩트: DefinitionArtifact, ImageArtifact 추가
    • CodeDeploy 애플리케이션 및 배포 그룹: ECS 서비스 배포 시 CodeDeploy에 자동 생성된 옵션을 팝업에서 선택합니다.
    • Amazon ECS 작업 정의: DefinitionArtifact 선택, taskdef.json 입력
    • AppSpec 파일: DefinitionArtifact 선택, appspec.yaml 입력
    • 동적 업데이트 작업 정의 이미지: ImageArtifact 선택 후, 플레이스홀더 텍스트 <ImageURI>를 매핑합니다.
  3. 설정이 끝나면 창 상단으로 스크롤하여 전체 파이프라인을 저장합니다.

왜 이렇게 설정하나요?
buildspec.yml을 통해 이미지가 생성되면 CodeBuild는 이를 파이프라인을 통해 CodeDeploy(Deploy 단계)로 전달합니다. CodeDeploy는 DefinitionArtifactImageArtifact의 정보를 받아 ECS에 새로운 구성을 업데이트하며 안전하게 블루-그린 배포를 진행하게 됩니다.


8. 자동화된 CI/CD 파이프라인 검증

모든 설정이 완료되었습니다! 코드를 S3에 푸시하면 이 파이프라인이 트리거되어 새 이미지를 빌드하고 ECS 블루-그린 배포를 수행합니다. 과정의 흐름은 다음과 같습니다.

  1. 파이프라인 트리거: 수정한 02 폴더 내의 모든 파일을 압축하여 Archive.zip을 만듭니다. 이를 S3 소스 버킷에 업로드하면 Source 단계가 신호를 받고 빌드 단계로 전송합니다.
  2. 빌드(Build) 진행 모니터링: 빌드 단계를 클릭하면 가상 머신이 프로비저닝되어 buildspec.yml 스크립트를 수행하고 이미지를 컴파일하는 상세 과정을 로그를 통해 확인할 수 있습니다.
  3. 블루/그린 배포(Deploy) 관찰: 빌드가 성공적으로 완료되면 배포 단계가 시작됩니다.
    • CodeDeploy 화면으로 이동하면 새 트래픽 그룹(Green)이 할당되는 것을 볼 수 있습니다.
    • 트래픽이 새 그룹으로 안전하게 유도되며 관찰 모드(기본 1시간)에 진입합니다.
  4. 최종 배포 완료:
    • ALB 도메인 주소로 접속해 서비스가 최신 버전으로 갱신되었는지 직접 확인합니다.
    • 버전이 정상적으로 갱신되었다면 CodeDeploy 관리 화면에서 '원래 작업 세트 종료(Terminate original task set)' 버튼을 클릭하여 즉시 이전 그룹(Blue)을 삭제하고, 아무런 리스크 없이 전체 배포 과정을 완료할 수 있습니다.

마치며
단순한 코드 작성에서 끝나지 않고, ECS 컨테이너화부터 CodePipeline을 활용한 무중단 Blue-Green 배포까지 전체 CI/CD 사이클을 직접 구축해 보니 인프라 자동화가 주는 안정성과 효율성을 깊이 체감할 수 있었습니다.

0개의 댓글