- spring
- 데이터베이스
- Docker
- 1차원 배열
- 문자열
- join
- 자바
- springboot
- SSL
- PYTHON
- sql
- 프로그래머스
- nginx
- string
- spring mvc
- ORM
- 스프링부트
- @transactional
- select
- jpa
- mysql
- spring security 6
- spring boot
- java
- Django
- DI
- 스프링
- static
- AWS
- hibernate
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
개발하는 자몽
CI/CD에 블루-그린 무중단 배포 적용하기: AWS ELB, AWS Auto Scaling Groups(ASG) 본문
CI/CD에 블루-그린 무중단 배포 적용하기: AWS ELB, AWS Auto Scaling Groups(ASG)
jaamong 2025. 8. 9. 21:44꽤... 늦었는데, 지난번에 구축한 CI/CD에 블루-그린 무중단 배포를 적용해 보자.
보안 그룹
ALB 보안 그룹 생성
ALB를 생성하기 전에 보안 그룹을 만들자. EC2 > 보안 그룹으로 이동하여 보안 그룹 생성을 클릭한다.
아웃바운드 규칙은 건들지 않고 인바운드 규칙만 편집한다.
- 유형: HTTP
- 소스 유형: 사용자 지정
- 소스: 0.0.0.0/0
EC2 보안 그룹 수정
애플리케이션에 대한 요청을 ALB를 통해서만 받을 수 있도록 이전 포스트에서 생성했던 EC2 보안그룹을 수정해야 한다.
이전 포스트에서 두 개의 인바운드 규칙을 추가했었다.
- 외부에서 EC2 내부로 접속하기 위한 SSH 22번 포트에 관한 규칙
- 외부에서 EC2 내부에서 실행되고 있는 애플리케이션에게 요청을 보내기 위한 사용자 지정 TCP 8080(애플리케이션 별 다름)번 포트에 관한 규칙
이번에는 애플리케이션 실행 포트 번호에 대해서 수정해야 한다. 아래와 같이 수정하자.
- 유형: 사용자 지정 TCP
- 포트 범위: 8080 (애플리케이션이 실행되는 포트 번호)
- 소스 유형: 사용자 지정
- 소스: 앞서 생성한 ALB 보안 그룹을 선택 (ALB를 통해서만 요청을 받을 수 있게 됨)
SSH 관련 인바운드 규칙은 유지한다.
대상 그룹
보안 그룹은 말 그대로 보안을 위한, 리소스를 둘러싼 벽(방화벽, firewall)같은 거라 ALB가 받은 요청이 마법처럼 EC2에게 전달될 수 없다. 따라서 ALB와 EC2 인스턴스를 이어주는 다리가 필요하다. 이 다리 역할을 대상 그룹(Target Group)이 수행한다.
대상 그룹 생성
EC2 > 대상 그룹으로 이동하여 대상 그룹 생성을 클릭한다.
1단계: 그룹 세부 정보 지정
- 기본 구성: 인스턴스 ; ALB가 받은 트래픽을 인스턴스 단위로 전달(분산)할 것이므로
- 대상 그룹 이름: 자유롭게 입력(어떤 서비스를 위한 대상 그룹인지, 그리고 대상 그룹임을 명시하는 이름이 좋은 것 같다)
- 프로토콜: HTTP
- 포트: 8080 ; 앞서 수정한 EC2의 보안그룹의 포트와 동일해야 한다. 이 포트를 통해 ALB가 받은 트래픽이 라우팅 된다.
- VPC: 트래픽을 받을 EC2 인스턴스가 존재하는 VPC를 선택한다.
- 상태 검사: 애플리케이션에 헬스 체크 API가 별도로 있다면, 상태 검사 경로에 해당 API의 엔드포인트를 입력한다.
- 언급하지 않은 나머지 항목들은 기본값을 유지하고, 다음으로 넘어간다.
2단계: 대상 등록
- 사용 가능한 인스턴스: 트래픽을 받을 인스턴스 선택 (앞서 보안그룹을 수정한 EC2를 선택하면 된다)
- 선택한 인스턴스를 위한 포트: 8080
- 아래에 보류 중인 것으로 포함 클릭
- 대상 그룹 생성 클릭
Application Load Balancer
EC2 인스턴스 앞에서 트래픽을 받아줄 로드밸런서를 생성할 차례다. EC2 > 로드 밸런서로 이동하고, 로드 밸런서 생성을 클릭한다. 로드 밸런서 유형은 Application Load Balancer를 선택한다.
- 로드 밸런서 이름: 자유롭게 입력
- 체계(schema): 인터넷 경계(internet-facing)
- VPC: 대상 그룹과 EC2 인스턴스가 놓인 VPC와 동일해야 함
- 가용 영역 및 서브넷: 2개 이상 선택해야 한다. EC2 인스턴스와 다른 서브넷에 위치해도 상관없다.
- 이런 경우에서의 ALB 사용 사례를 잘 생각해보자. 보통 EC2 인스턴스를 프라이빗 서브넷에 놓는데(보안), 트래픽을 앞에서 먼저 받아 전달해 주는 ALB는 퍼블릭 서브넷에 놓는 편 → 둘은 다른 서브넷에 위치해도 OK.
- 보안 그룹: 처음에 ALB를 위해 생성했던 보안그룹을 선택
- 리스너 및 라우팅(다음 프로토콜 및 포트로 트래픽을 받아 대상 그룹으로 트래픽을 전달(라우팅))
- 프로토콜 - 포트: HTTP - 80
- 대상 그룹: 앞서 만들었던 대상 그룹을 선택한다.
- 언급하지 않은건 기본값으로 남겨둔다.
- 이제 요약을 잘 확인해 보고 이상이 없다면 생성을 완료한다.
AMI
AMI(Amazon Machin Image)는 인스턴스를 생성할 때 사용되는 이미지로, OS처럼 생각하면 될 것 같다. AMI가 있으면 다른 인스턴스를 생성해도 동일한 OS 및 환경을 구성할 수 있다. 우리는 이미 생성된 인스턴스가 있으므로, 그 인스턴스를 이용해 AMI를 생성할 것이다.
오토 스케일링은 인스턴스를 트래픽에 따라 자동으로 생성 및 삭제를 수행하는 기능으로, 이 기능을 사용하려면 시작 템플릿(Launch Template)이 필요하고, 이를 생성하려면 AMI가 필요하다. 우리가 새로운 인스턴스 만들 때 AMI를 선택하는 것처럼 자동으로 인스턴스 생성 시 사용될 AMI가 있어야 한다.
EC2 > 인스턴스로 이동하여 오토 스케일링을 적용할 인스턴스를 선택하고, 작업 > 이미지 및 템플릿 > 이미지 생성을 클릭한다.
- 이미지 이름: 자유롭게 입력하나, 어떤 이미지인지 잘 식별되도록 하자.
- 이미지 설명: 넘기지 말고, 어떤 목적으로 생성했는지 작성하자.
- 나머지는 기본값으로 두고 이미지 생성을 완료한다.
바로 생성이 완료되지는 않고, 몇 분 기다리다보면 사용 가능이라고 상태가 뜬다.
시작 템플릿
우리는 인스턴스를 생성할 때 AMI 선택 외에도 인스턴스에 관한 스펙(인스턴스 유형, 네트워크 설정 등)을 설정한다. 오토 스케일링으로 만들어질 인스턴스의 스펙은 시작 템플릿(Launch Template)을 통해 설정된다.
EC2 > 시작 템플릿으로 이동하여 시작 템플릿 생성을 클릭한다.
- 시작 템플릿 이름: 자유롭게 입력
- 템플릿 버전 설명: 보통 애플리케이션 이름과 함께 템플릿(Template)을 같이 적어주는 것 같다 (예시: HelloWorld Web Server Template)
- 애플리케이션 및 OS 이미지: 내 AMI > 내 소유 > 앞서 생성한 AMI 선택
- 인스턴스 유형: 애플리케이션 스펙에 맞춰서 선택하기. 연습용이거나 작은 프로젝트라면 `t3.micro`나 `t3.small`로 충분하다(docker로 서버를 띄운다면 small 권장)
- 키 페어 이름: 시작 템플릿에 포함하지 않음
- 서브넷/가용 영역: 시작 템플릿에 포함하지 않음
- 방화벽(보안 그룹): 오토 스케일링을 적용할(현재 CI/CD 되고 있는) EC2 인스턴스와 동일한 보안 그룹을 선택한다.
- 고급 세부 정보 > 사용자 데이터: 여기에 Java17 및 CodeDeploy 에이전트 설치와 애플리케이션을 실행할 디렉토리를 생성하는 명령어를 작성한다. 이 과정에서 인스턴스의 AMI는 Ubuntu라서 이 OS에 맞춰서 명령어를 사용했다. (AMI에서 하는 것이 더 적절해 보이는데 일단 여기에서)
#!/bin/bash sudo apt update -y sudo apt install -y openjdk-17-jdk sudo apt install ruby-full sudo apt install wget cd /home/ubuntu wget https://bucket-name.s3.region-identifier.amazonaws.com/latest/install chmod +x ./install sudo ./install auto mkdir -p /home/ec2-user/hello
- 언급하지 않은 나머지는 기본값으로 두고 생성을 완료한다.
오토 스케일링 그룹(ASG)
AWS ASG는 인스턴스를 그룹 단위로 관리하며, 트래픽 변화에 따라 스케일링 정책을 기반으로 자동으로 인스턴스 수를 증가시키거나 감소시킬 수 있다.
EC2 > Auto Scaling 그룹으로 이동, Auto Scaling 그룹 생성을 클릭한다.
1단계: 시작 템플릿 선택
- 이름: 자유롭게 입력
- 시작 템플릿: 앞서 생성한 템플리 선택
이후 다음 클릭
2단계: 인스턴스 시작 옵션 선택
- VPC: EC2 인스턴스와 동일한 VPC 선택
- 가용 영역 및 서브넷: 자유롭게 선택. 모두 선택해도 상관없다. 단순하게만 보자면 많이 선택할 수록 가용성이 높아진다고 생각하면 될 것 같다. 최소한의 가용성을 고려했을 때 적어도 두 개는 선택하는 게 좋다.
- 가용 영역 배포: 균형 잡힌 최선 노력
이후 다음 클릭
3단계: 다른 서비스와 통합
- 로드 밸런싱: 기존 로드 밸런서에 연결
- 기존 로드 밸런서에 연결: 로드 밸런서 대상 그룹에서 선택
- 기존 로드밸런서 대상 그룹: 앞서 만든 대상 그룹 선택
- 상태 확인: Elastic Load Balancer 상태 확인 켜기 활성화
- 로드 밸런서가 인스턴스의 상태를 확인하고, 문제가 있는 인스턴스가 있으면 오토 스케일링이 이를 확인하고 인스턴스를 교체함
4단계: 그룹 크기 및 크기 조정 구성
- 원하는 용량(Desired capacity): 1 (상황에 맞춰서 진행, 여기서는 간단히 기본값으로 진행)
- 생성 시에 만들어지는 인스턴스 개수로, ASG는 이 수를 유지하려고 한다.
- 1로 설정한 경우를 예시로 보자. 실행되고 있는 한 개의 인스턴스가 예상치 못하게 종료되면, 원하는 용량값인 1을 유지하기 위해 ASG가 한 개를 새롭게 생성한다.
- *원하는 최소 용량 ≤ 원하는 용량 ≤ 원하는 최대 용량
- 원하는 최소 용량: 1 (상황에 맞춰서 진행)
- 스케일링 정책이 설정된 경우, 그룹의 원하는 용량을 이 값보다 더 작게 감소시키지 못함
- 원하는 최대 용량: 2 (상황에 맞춰서 진행)
- 스케일링 정책이 설정된 경우, 그룹의 원하는 용량을 이 값보다 더 크게 증가시키지 못함
- Automatic scaling: 크기 조정 정책 없음
- 이 기능이 실제로 "오토 스케일링"이라고 부르는 부분이다. 지금은 정책 없음을 선택해서 ASG가 트래픽 변화에 따라 자동으로 스케일링 할 수 없다. 우리가 수동으로 원하는 용량을 변경하여 그룹 크기를 변경해야 한다. 따라서 `원하는 최소 용량`으로만 유지된다.
- 지금은 인스턴스 개수가 유지만 되도록 정책 없음을 선택했다.
- 인스턴스 유지 관리 정책: 정책 없음
나머지는 손대지 않고 다음으로 넘어간다.
5단계: 알림 추가
이 기능을 사용하려면 AWS의 다른 기능도 설정해야 해서 이 글에서는 넘어간다.
6단계: 태그 추가
이 단계도 그냥 넘어가도 된다. 태그를 설정하면 새로 생성되는 인스턴스의 이름을 지정할 수 있다. 보통 키는 `Name`을 유지하고 값에 애플리케이션/프로젝트 이름을 넣는 것 같다.
7단계: 검토
설정값들을 마지막으로 확인하고 생성을 완료한다.
ASG 생성이 완료되면 원하는 용량을 유지하기 위해 새 인스턴스를 생성한다. → 지금까지의 과정을 통해 생성된 인스턴스는 총 2개(이전 글에서 처음에 1개만 생성했다면)
CodeDeploy
CodeDeploy도 수정해야 한다. 우선 CodeDeploy의 IAM 역할부터 수정한다.
IAM 역할 - 권한 추가
IAM > 역할로 이동해서 전에 CodeDeploy를 위해 생성한 IAM 역할을 클릭한다. 이전 글에서는 `CodeDepoyServiceRoleForEC2`라는 이름으로 생성했다. 이동한 화면에서 권한 > 권한 추가 > 인라인 정책 생성을 클릭한다.
정책 편집기에서 JSON을 선택하고 아래와 같이 작성한다. (시작 템플릿으로 ASG을 생성한 경우, 다음 권한들이 필요함)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:PassRole",
"ec2:CreateTags",
"ec2:RunInstances"
],
"Resource": "*"
}
]
}
작성 후 다음으로 넘어가고, 권한 추가를 완료한다.
CodeDeploy 배포 그룹 편집
CodeDeploy > 애플리케이션 > 앞서 생성한 애플리케이션(SpringBootApp) > 앞서 생성한 배포 그룹(production)까지 이동하자. 이동한 화면에서 편집을 클릭한다.
이동하면 이전에 배포 그룹을 생성했을 때 보았던 화면이 나온다.
- 배포 유형: 블루/그린 (현재 위치 → 블루/그린)
- 환경 구성: Amazon EC2 Auto Scaling 그룹 자동 복사
- ASG 선택: 앞서 생성한 ASG 선택
- 배포 설정 - 새 배포가 생성되면 바로 트래픽을 라우팅 하고, 기존 인스턴스는 15분 후 종료되게 설정한다.
- 트래픽 재 라우팅: 즉시 트래픽 라우팅
- 배포 성공 후 원본 환경 인스턴스 종료 여부 및 종료 전 대기 시간 선택: 배포 그룹의 원본 인스턴스 종료
- 일: 0
- 시간: 0
- 분: 15
- 배포 구성: CodeDeployDefault.AllAtOnce
- 로드 밸런서 유형: Application Load Balancer 또는 Network Load Balancer 활성화
- 대상 그룹 선택: 앞서 생성한 대상 그룹 선택
변경 사항 저장을 클릭하여 편집을 완료한다.
이제 CodeDeploy를 사용하여 ASG의 EC2 인스턴스에 배포할 수 있다!
블루/그린 무중단 배포 과정 정리
새로운 버전을 배포하기 전 상태
- 인스턴스 총 개수: 직접 생성한 EC2 인스턴스 1개(A라고 지칭) + ASG로 생성된 EC2 인스턴스 1개(B라고 지칭)
- 이 둘을 Blue 그룹이라고 하자.
배포 과정(단순하게 표현함, 실제로는 더 많은 단계가 있음)
- 코드 변경 사항이 발생하여 GitHub 레포지토리에 commit/push
- GitHub Actions에서 감지(push trigger) → 배포 스크립트(.github/workflows/deploy.yml) 실행
- GitHub Actions에서 CI를 진행하고 CodeDeploy를 통해 CD 진행
- CodeDeploy를 통해 다음의 과정이 일어난다.
- Green 그룹 생성: 2개의 인스턴스를 새롭게 생성
- 이때 ASG 그룹이 하나 더 늘어나고, 인스턴스 목록도 보면 2개에서 3개로 늘어나있는 것을 볼 수 있다.
- Green 그룹에 새로운 버전의 배포를 진행
- Green 그룹으로 트래픽 라우팅
- 배포가 성공하고 15분 후에 Blue 그룹 제거
- 새로 생겼던 ASG 그룹이 유지되고, 기존 그룹은 제거된다. (그룹 수 다시 1개)
- ASG로 인해 생겼던 기존 인스턴스도 제거되고, 새로운 인스턴스가 유지된다. (인스턴스 수 다시 2개: 수동 생성했던 인스턴스 1 + 지금 새로 생긴 인스턴스 1)
- Green 그룹 생성: 2개의 인스턴스를 새롭게 생성
- 배포 완료
후기
어느 리소스를 생성하든, 그 리소스가 명시되도록 이름을 잘 짓는게 중요하다. 어떤 목적으로 리소스를 생성했는지 설명을 잘 작성하는 것도 무척 중요하다.
AWS 리소스를 생성하는 과정에서 어떤 옵션을 선택할 때 이 옵션이 무엇인지 작게 설명이 쓰여있는데, 잘 읽어보면 꽤나 도움이 된다. (사실 아리송할 때가 더 많은 것 같기도... 이때 이해 못 해서 공식 문서를 찾아봐도 궁금증이 완전히 해결되는 경우는 아직까지 많지 않은 듯)
🔖
- https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-service-role.html
- https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-enable-disable-scaling-policy.html
- https://docs.aws.amazon.com/autoscaling/ec2/userguide/asg-capacity-limits.html
- https://velog.io/@pmthk__/Github-Actions-%EA%B3%BC-AWS-CodeDeploy%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-BlueGreen-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94#codedeploy-%EC%83%9D%EC%84%B1
- https://happy-jjang-a.tistory.com/94
'Architecture & Tool > AWS' 카테고리의 다른 글
[TIL / AWS] SpringBoot 서버리스로 배포하기: ECR + Fargate(ECS) + ALB + Private Link (4) | 2025.08.07 |
---|---|
CI/CD 구축하기: GitHub Actions (OIDC) + Amazon S3 + Amazon CodeDeploy (3) | 2025.07.28 |
[AWS RDS] MySQL 파라미터 그룹 생성과 설정 - timezone, encoding (1) | 2025.01.31 |
[AWS & Docker] Docker 컨테이너 로그를 AWS CloudWatch로 보내기 (1) | 2025.01.04 |
잊기 전에 남겨두는 Amazon API Gateway 사용 이유 (0) | 2024.11.30 |