1. AWS 이용한 배포 자동화
1-1. AWS CodePipeline
- 소스 코드 변경 사항을 자동으로 감지하고, 빌드 및 배포 프로세스를 자동화하여 지속적인 통합 및 배포(CI/CD)를 지원하는 서비스
- 주로 세 가지 주요 스테이지로 구성됨
- 소스 스테이지
- 애플리케이션의 소스 코드가 저장된 위치에서 코드를 가져오는 단계
- 일반적으로 GitHub, AWS CodeCommit, S3 등의 소스 리포지토리에서 소스를 가져옴
- 빌드 스테이지
- 소스 코드 컴파일 + 필요한 의존성 설치 + 애플리케이션 패키징하는 단계
- AWS CodeBuild 사용하여 이 과정을 자동화함
- 배포 스테이지
- 빌드된 애플리케이션을 실제 환경에 배포하는 단계
- 다양한 AWS 서비스(AWS Elastic Beanstalk, Amazon ECS, AWS Lambda 등)를 통해 배포 가능
- 소스 스테이지
1-2. 배포 자동화 과정
- 소스 스테이지
- 소스 리포지토리에 새로운 커밋이 발생하거나 특정 이벤트(push, PR 등)가 발생하면, CodePipeline이 해당 이벤트를 감지
- 코드 변경 시 소스 스테이지가 트리거됨 ⇒ 변경된 코드 가져옴
- 가져온 소스를 빌드 스테이지로 전달
- 빌드 스테이지
- 소스 스테이지에서 전달된 코드가 빌드됨
- AWS CodeBuild 가 Docker 이미지나 ZIP 파일 등 원하는 형식으로 애플리케이션을 패키징함
- 빌드 완료 시 빌드 아티팩트 (JAR 파일, Docker 이미지 등)가 생성됨
- 빌드 과정에서의 테스트 결과도 확인 가능
- 생성된 빌드 아티팩트를 배포 스테이지로 전달
- 배포 스테이지
- 빌드 스테이지에서 전달된 아티팩트 사용하여 배포 시작됨
- 선택된 AWS 서비스에 따라 환경 설정 이루어짐 ⇒ 새로운 버전의 애플리케이션 배포됨
- 배포 완료 시 필요에 따라 롤백 기능, 알림 기능 등을 통해 배포 상태 모니터링 가능
- 배포 후 테스트 통해 애플리케이션의 정상 작동 여부 확인
2. 배포 자동화 적용
2-0. 사전 준비
2-0-1. 스프링 프로젝트에 아래의 파일들을 상황에 맞게 수정 및 추가할 것
- buildspec.yml
- CodeBuild가 빌드할 때 참고할 buildspec 정의
version: 0.2
phases:
install:
runtime-versions:
java: corretto17
commands:
- echo "Installing dependencies..."
- sudo chmod 777 gradlew
- ./gradlew build -x test
pre_build:
commands:
- echo "Setting up environment variables..."
- echo "" > src/main/resources/application.properties
- echo "spring.datasource.url=$DB_URL" >> src/main/resources/application.yml
- echo "spring.datasource.username=$DB_USERNAME" >> src/main/resources/application.yml
- echo "spring.datasource.password=$DB_PASSWORD" >> src/main/resources/application.yml
build:
commands:
- echo "Build started on `date`"
- ./gradlew clean build -x test
- echo "Build completed on `date`"
post_build:
commands:
- echo "Post-build steps"
- ls build/libs/
- echo "Build completed. Preparing to deploy."
artifacts:
files:
- appspec.yml
- build/libs/*.jar
- scripts/*
discard-paths: yes
cache:
paths:
- ~/.gradle/caches/**
- appspec.yml
- CodeDeploy Agent가 EC2에서 파일 실행 시 필요한 사항 정의
version: 0.0
os: linux
files:
- source: .
destination: /home/ec2-user/build
overwrite: yes
permissions:
- object: /
pattern : "**"
mode : 755
owner : ec2-user
group : ec2-user
hooks:
ApplicationStart:
- location: start.sh
timeout: 300
runas: ec2-user
ApplicationStop:
- location: stop.sh
timeout: 300
runas: ec2-user
- scripts > start.sh
- 애플리케이션 실행에 필요한 셸 스크립트
#!/bin/bash
# 기존 애플리케이션 종료
PID=$(pgrep -f 'java -jar /home/ec2-user/build/프로젝트 이름-0.0.1-SNAPSHOT.jar')
if [ -n "$PID" ]; then
sudo kill -9 $PID
fi
# 새 애플리케이션 시작
nohup java -jar /home/ec2-user/build/프로젝트 이름-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &
- scripts > stop.sh
- 애플리케이션 중지에 필요한 셸 스크립트
#!/bin/bash
# 기존 애플리케이션 종료
PID=$(pgrep -f 'java -jar /home/ec2-user/build/프로젝트 이름-0.0.1-SNAPSHOT.jar')
if [ -n "$PID" ]; then
sudo kill -9 $PID
fi
- application.yml
- CodeBuild의 환경변수로부터 DB 연결 설정을 받아오도록 설정
# 아래와 같이 수정
spring:
datasource:
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
2-0-2. 스프링 프로젝트를 깃헙에 올리기
2-1. 파이프라인 생성
- AWS의 CodePipeline 검색 및 클릭
- 파이프라인 생성 클릭
- Build custom pipeline 선택
- 파이프라인 이름 설정, 나머지 설정은 기본값으로 유지
- 소스 공급자: GitHub(버전 2) 선택 → GitHub에 연결 클릭
- AWS-GitHub 간 연결 이름 설정
- AWS 연결을 위한 권한 부여
- 새 앱 설치 클릭 → 접근 레포 선택 및 Install & Authorize 클릭 → 비밀번호 입력
- 앱 설치 드롭다운에서 연결할 계정 선택 → 연결 클릭
- 연결할 레포지토리, 브랜치 선택
- 트리거 설정 → 다음 클릭
⇒ 위에 선택했던 브랜치 (master) 푸시 되면 자동으로 배포되게 설정하는 것임
- 빌드 공급자: Other build providers 선택 → AWS CodeBuild 선택 → 프로젝트 생성 클릭
- 프로젝트 생성 - 프로젝트 구성 (프로젝트 이름 작성)
- buildspec 파일 사용 선택 → buildspec.yml 입력 → (하단의) CodePipeline으로 계속 클릭
- 환경 변수 3개 추가 (아래 사진 참고) → 다음 클릭
- DB_URL : jdbc:mysql://RDS의 엔드포인트:3306/데이터베이스 이름
- DB_USERNAME : RDS 사용자 이름 (root)
- DB_PASSWORD : RDS 사용자 비밀번호
- 배포 스테이지 건너뛰기 클릭
- 검토 및 파이프라인 생성 클릭
- 파이프라인 생성 완료 확인
2-2. CodeDeploy 역할 생성
- 검색 창에 IAM 검색 → 클릭
- 왼쪽의 역할 클릭 → 역할 생성 클릭
- AWS 서비스 선택
- CodeDeploy 선택 → 다음 클릭
- AWSCodeDeployRole 확인 → 다음 클릭
- 역할 이름 작성 → 역할 생성 클릭
2-3. 배포 그룹 생성
- 검색창에 codedeploy 검색 → 클릭
- 왼쪽의 배포 → 애플리케이션 클릭 → 애플리케이션 생성 클릭
- 애플리케이션 이름 작성 → 컴퓨팅 플랫폼: EC2/온프레미스 선택 → 애플리케이션 생성 클릭
- 애플리케이션 생성 확인 → 배포 그룹 생성 클릭
- 배포 그룹 이름 작성 → 서비스 역할 (IAM에서 생성한 역할) 선택
- (환경 구성) Amazon EC2 인스턴스 선택 → 키: Name 입력 → 값: EC2 인스턴스 선택
- 로드 밸런싱 활성화 체크 해제 → 배포 그룹 생성 클릭
- 배포 그룹 생성 확인
2-4. 파이프라인에 배포 스테이지 추가
- 왼쪽의 파이프라인 → 파이프라인 선택
- 생성된 파이프라인 선택
- 편집 클릭
- 빌드 스테이지 하단의 (가장 아래의) 스테이지 추가 클릭
- 스테이지 이름 입력 → 스테이지 추가 클릭
- 작업 그룹 추가 클릭
- 작업 편집 설정 → 완료 클릭
- 작업 이름 : 원하는 이름 입력
- 작업 공급자 : AWS CodeDeploy 선택
- 리전 : 아시아 태평양 (서울) 선택
- 입력 아티팩트 : BuildArtifact 선택
- 애플리케이션 이름 : AWS CodeDeploy 에서 생성한 애플리케이션 선택
- 배포 그룹 : AWS CodeDeploy 에서 생성한 배포 그룹 선택
- 완료 클릭 → 상단의 저장 클릭
2-5. EC2 역할 설정
- IAM 진입 → 왼쪽의 역할 클릭 → 역할 생성 클릭
- 신뢰할 수 있는 엔터티 유형 : AWS Service 선택
- 서비스 또는 사용 사례, 사용 사례 : EC2 선택 → 다음 클릭
- 아래의 4개 권한 검색 후 추가 → 다음 클릭
- AmazonS3FullAccess
- AWSCodeDeployFullAccess
- AWSCodeDeployRole
- CloudWatchLogsFullAccess
- EC2 역할의 이름 설정
- 추가한 4개의 권한 정책 확인 → 역할 생성 클릭
- EC2 역할 생성 확인
- EC2 진입 → 왼쪽의 인스턴스 클릭 → 적용할 인스턴스 선택 → 작업 클릭 → 보안 클릭 → IAM 역할 수정 클릭
- 생성한 EC2 역할 선택 → IAM 역할 업데이트 클릭
- EC2 인스턴스와 생성한 역할이 연결됨을 확인
2-6. EC2 사용자 추가
- IAM 진입 → 왼쪽의 액세스 관리 → 사용자 그룹 클릭 → 그룹 생성 클릭
- 사용자 그룹 이름 입력 → 사용자 그룹 생성 클릭
- 사용자 그룹 생성 확인
- 생성된 그룹 이름 클릭
- 권한 탭 클릭 → 권한 추가 클릭 → 인라인 정책 생성 클릭
- JSON 탭 클릭 → 아래 내용 붙여넣기 → 다음 클릭
📌 IAM 정책 정의 JSON
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "autoscaling:*", "codedeploy:*", "ec2:*", "lambda:*", "elasticloadbalancing:*", "s3:*", "cloudwatch:*", "logs:*", "sns:*" ], "Resource": "*" } ] }
- Version : 정책의 버전
- “2012-10-17” : 현재 AWS에서 사용되는 최신 정책 버전
- Statement : 정책의 주요 내용을 포함하는 배열
- Effect : 정책의 효과 정의
- “Allow” : 지정된 액션을 허용함을 의미
- Action : 허용되는 AWS 서비스의 특정 작업 나열
- “autoscaling:*” → Auto Scaling 관련 모든 작업
- “codedeploy:*” → CodeDeploy 관련 모든 작업
- “ec2:*” → EC2(Elastic Compute Cloud) 관련 모든 작업
- “lambda:*” → AWS Lambda 관련 모든 작업
- “elasticloadbalancing:*” → Elastic Load Balancing 관련 모든 작업
- “s3:*” → S3(Simple Storage Service) 관련 모든 작업
- “cloudwatch:*” → CloudWatch 관련 모든 작업
- “logs:*” → CloudWatch Logs 관련 모든 작업
- “sns:*” → SNS(Simple Notification Service) 관련 모든 작업
- Resource: 정책이 적용되는 리소스 지정
- "*" : 모든 리소스에 대해 위의 작업이 허용됨을 의미
- 정책 이름 입력 → 정책 생성 클릭
- 정책 생성 확인
- 왼쪽의 사용자 클릭 → 사용자 생성 클릭
- 사용자 이름 입력 → 체크박스 체크 → IAM 사용자 생성 체크 → 다음 클릭
- 생성해 둔 사용자 그룹 선택 → 다음 클릭
- 생성 정보 검토 → 사용자 생성 클릭
- .csv 파일 다운로드 클릭 (로그인 정보 파일) → 사용자 보기 클릭
- 보안 자격 증명 탭 클릭 → 아래의 액세스 키 만들기 클릭
- Command Line Interface (CLI) 선택 → 확인 체크박스 체크 → 다음 클릭
- 설명 태그 값 입력 (선택) → 액세스 키 만들기 클릭
- .csv 파일 다운로드 (액세스 키) → 완료 클릭
⇒ 이 페이지를 벗어나면 액세스 키를 확인할 수 없으므로 꼭 .csv 파일 다운로드 해놓을 것!
2-7. EC2 환경 설정
- 터미널 접속 → EC2 접속
ssh -i [키페어 이름].pem [인스턴스의 계정 이름]@[인스턴스의 퍼블릭 IPv4 DNS]
- EC2에 aws-cli 설치
cd ~
sudo yum update -y
sudo yum install -y aws-cli
- 설치된 aws-cli 버전 확인 (설치 확인겸)
aws --version
- aws-cli 설정
sudo aws configure
# 위의 명령어를 치고 아래의 정보들을 순서대로 기입할 것
1. AWS Access Key ID : 다운받은 액세스 키 파일의 Access Key Id
2. AWS Secret Access Key : 다운받은 액세스 키 파일의 Secret access key
3. Default region name : ap-northeast-2
4. Default output format : json
- Ruby 설치 및 버전 확인
sudo yum install -y ruby
ruby --version
- CodeDeploy Agent Installer 설치
wget <https://aws-codedeploy-ap-northeast-2.s3.amazonaws.com/latest/install>
- CodeDeploy Agent Installer 실행 → CodeDeploy Agent 설치
# 실행 권한 추가
sudo chmod +x install
# install 파일 실행
sudo ./install auto
- CodeDeploy Agent 설정
# 에디터 열기
sudo vim /etc/init.d/codedeploy-startup.sh
# 아래 내용 입력
echo 'Starting codedeploy-agent'
sudo service codedeploy-agent restart
# 저장 및 나가기
esc -> :wq
# 실행 권한 추가
sudo chmod +x /etc/init.d/codedeploy-startup.sh
- build 디렉토리 생성
cd /home/ec2-user
mkdir build
- CodeDeploy Agent 실행 상태 확인
sudo service codedeploy-agent status
3. 자동 배포 결과 확인
- 위의 단계까지 진행 후 변경 사항 적용하여 깃헙 레포에 푸시
⇒ 푸시하면 Source, Build, Deploy 스테이지가 (진행중) → (성공)으로 바뀌는 모습을 볼 수 있음
2. build 디렉토리 확인하면 GitHub → EC2로 실행에 필요한 파일들이 잘 옮겨온 것을 확인 가능
3-1. 첫번째 배포 결과
// 컨트롤러의 일부
@RestController
@AllArgsConstructor
public class TestController {
@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.GET, RequestMethod.OPTIONS})
@GetMapping
public String home() {
return "첫번째 버전";
}
}
- EC2 인스턴스의 퍼블릭 IPv4DNS:8080 으로 접속한 결과
3-2. 코드 수정 후 두번째 배포 결과
// 컨트롤러의 일부
@RestController
@AllArgsConstructor
public class TestController {
@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.GET, RequestMethod.OPTIONS})
@GetMapping
public String home() {
return "두번째 버전"; // 이 부분 코드 수정함!
}
}
⇒ 수정한 코드 내용을 깃헙 레포에 푸시하여 반영!
⇒ 위와 같이 파이프라인에서 (진행중) → (성공) 으로 변화!
- EC2 인스턴스의 퍼블릭 IPv4DNS:8080 으로 접속한 결과
4. 배포 단계에서 에러가 발생한 경우 (AccessDeniedException)
- 터미널에서 로그 조회
sudo tail -f /var/log/aws/codedeploy-agent/codedeploy-agent.log
- EC2의 보안 그룹에서 인바운드 규칙에 HTTPS 규칙 추가
- build 디렉토리 제거 후 재생성
# build 디렉토리 제거
rm -rf build
# build 디렉토리 재생성
mkdir build
- CodeDeploy Agent 중지 → 배포 버전 삭제 → 시작
# CodeDeploy Agent 중지
sudo service codedeploy-agent stop
# CodeDeploy Agent 배포 버전 삭제
sudo rm -rf /opt/codedeploy-agent/deployment-root
# CodeDeploy Agnet 시작
sudo service codedeploy-agent start
# CodeDeploy Agnet 상태 확인 (실행 중인지)
sudo service codedeploy-agent statsu
- AWS의 CodePipeline 콘솔에서 실패한 작업 재시도 클릭
'DevOps > CI,CD' 카테고리의 다른 글
[CI/CD] CI/CD 파이프라인 구축 (Github Actions) + 코드 수정으로 CI/CD 확인 (1) | 2023.12.28 |
---|---|
[CI/CD] Docker로 프로젝트 배포 및 중단 (0) | 2023.12.28 |
[CI/CD] AWS EC2 인스턴스 SSH 접속 + Docker 설치 (0) | 2023.12.28 |
[CI/CD] AWS EC2 인스턴스 생성 방법 (0) | 2023.12.28 |
[CI/CD] AWS RDS 생성 방법 + MySQL 워크벤치와 연동 (0) | 2023.12.27 |