CodeDeploy
- 클라우드 기반 배포 자동화를 위한 CD(Continuous Deploy) 도구
- AWS EC2, ECS, Lambda 및 온프레미스 서버에도 배포 가능
- S3, CodeCommit, CodePipeline, Git, ELB, Auto-Scaling 등과 통합
CodeDeploy 주요 구성 요소
- AppSpec 파일: 배포할 어플리케이션에 대한 정보를 설정(yml or json)
- 배포 구성: CodeDeploy에서 사용하는 배포규칙,배포성공/실패 조건 세트
- EC2/온프레미스 인스턴스의 최소개수지정, Lambda함수 버전으로 특정 트래픽 라우팅 방식(Canary, Linear, All-at-Once) 등 - 배포그룹: 개별 인스턴스들의 세트, 특정 태그가 지정된 인스턴스 or ASG에 포함된 EC2 등
- 배포방식: 배포를 수행하는 방식, In-Place, Blue/Green
배포 파일(AppSpec.yml )의 프로세스
배포 방식
1. In-Place 방식
- 현재 실행 중인 인스턴스 대상으로 배포 수행
- 새로운 인스턴스 생성이 불필요해서 배포가 간단하고 빠른 장점
- 롤백 시 이전 버전으로 배포 다시 진행해야 함으로 롤백 시간이 오래 걸림
2. Blue-Green 방식
- 대체 환경을 생성하여 점진적으로 트래픽을 전환하는 방식
- 로드밸런서의 설정(등록/해제) 변경으로 롤백이 빠름
- 배포 과정에서 요청량을 처리하는 인스턴스 개수가 줄지 않음
- 배포 과정에서 인스턴스의 수를 2배로 늘려야 함으로 배포준비 시간이 오래 걸림
CodeDeploy 배포하기
- 기존 CodeBuild 테스트 내용 이어서 진행(CodeBuild 참조: https://happy-jjang-a.tistory.com/92)
- 아래와 같은 항목 순서로 진행
1. CodeDeploy Role, EC2 인스턴스 Role 생성
2. Auto Scaling Group(ASG) 생성
3. appspec.yml 파일 작성
4. 기존 CodeBuild 설정 변경
5. CodeDeploy 구성(어플리케이션생성 -> 배포그룹 생성 -> 배포 생성)
1. CodeDeploy IAM Role 생성
- IAM 역할 메뉴에서 '역할 만들기' 버튼 클릭
- AWS 서비스에서 [사용 사례]에 "CodeDeploy" 검색해서 선택 후 다음
- "AWSCodeDeployRole" 선택 후 다음 클릭
- [역할 이름]에 "mytest-codedeploy-Role"로 입력하고 생성
- CodeDeploy Role 생성 확인
2. EC2 IAM Role 생성
- IAM 역할 메뉴에서 '역할 만들기' 클릭
- AWS 서비스에서 [사용 사례]에 "EC2" 선택 후 다음
- "AmazonEC2RoleforAWSCodeDeploy" 선택 체크 후 다음
- 이름은 "mytest-EC2-CodeDeploy-Role" 입력하고 생성
- EC2용 IAM Role 생성 확인
3. Auto Scaling Group 생성
- ASG는 다음 내용 참조해서 진행(https://happy-jjang-a.tistory.com/70)
- EC2메뉴에서 인스턴스 > 시작템플릿에서 '시작 템플릿 생성' 버튼 클릭
- 이름 입력, Auto Scaling 지침정보 체크
- AMI는 Amazon Linux 선택
- 인스턴스 유형 및 키페어 선택
- 서브넷은 포함하지 않고, 보안 그룹(SG)은 기존 보안그룹 선택
- (참고)위에서 선택한 보안그룹 inbound 규칙은 8080 port가 ALB SG에 Inbound OPEN 된 SG이면 됨
- [고급 세부 정보]에서 'IAM 인스턴스 프로파일'에 위에서 생성한 EC2용 Role 선택
- [고급세부정보] 제일 하단의 [사용자 데이터]에 "codedeploy-agent" 설치를 위한 스크립트 작성(AMI로 생성해놓은 것이 편하고 좋을듯 한데 '사용자데이터'도 테스트하기 위해 여기에 설정해봄)
#!/bin/bash
sudo yum -y update
sudo yum install -y ruby java-1.8.0-openjdk-devel.x86_64
cd /home/ec2-user
curl -O https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
mkdir -p /home/ec2-user/app
- 아래 같이 작성 후 생성 버튼 클릭
- 다음으로 'Auto Scaling > Auto Scaling 그룹' 에서 생성 버튼 클릭 후 이름 입력, 시작템플릿 선택 후 다음
- EC2 실행시킬 VPC 및 서브넷 선택
- "기존 로드 밸런서에 연결" 선택하고, 대상그룹 선택 후 다음
* 대상그룹 정보는 아래와 같음(인스턴스 타입으로 8080 port로 간단히 생성 후 ALB 연결 함)
- 일단 디폴트값 그대로 두고 다음 후 알림,태그 등도 그냥 없음해서 넘기고 생성
- 생성 확인
4. appspec.yml 및 script 작성
- 소스 Root에 "appspec.yml"파일과 scripts폴더 생성 후 하위에 "restart.sh" 파일 생성
- "appspec.yml"파일 내용
version: 0.0 # CodeDeploy 버전
os: linux
files:
- source: / # CodeDeploy에서 전달해 준 파일 중 destination으로 이동시킬 대상을 루트로 지정(전체파일)
destination: /home/ec2-user/app # source에서 지정된 파일을 받을 위치
overwrite: yes
permissions: # CodeDeploy에서 EC2서버로 넘겨준 파일들은 모두 ec2-user권한을 갖도록 설정
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
mode: 755
hooks:
AfterInstall: # 배포를 완료한 후 실행되는 스크립트
- location: restart.sh
timeout: 60
runas: ec2-user
[appspec.yml 파일의 hooks 시점]
1. BeforeInstall: destination 경로에 파일들을 옮기기 전에 실행(압축 해제 등 실행)
2. AfterInstall: destination 경로에 파일들을 옮긴 후 실행
3. ApplicationStart: 어플리케이션 시작 시
4. ValidateService: 서비스 재시작 후 실행
* 각 단계의 스크립트에서 exit 코드 0을 주거나 없는 경우 성공, 0이 아닌 다른 코드는 실패로 간주 함(ex. exit 1)
- "restart.sh" 파일 내용 작성 후 모두 Push
#!/bin/bash
BUILD_WAR=$(ls /home/ec2-user/app/*.war)
WAR_NAME=$(basename $BUILD_WAR)
echo "## build 파일명: $WAR_NAME"
echo "## build 파일 복사"
DEPLOY_PATH=/home/ec2-user/
cp $BUILD_WAR $DEPLOY_PATH
CURRENT_PID=$(pgrep -f $WAR_NAME)
echo "## 현재 실행중인 애플리케이션 pid: $CURRENT_PID"
if [ -z $CURRENT_PID ]
then
echo "## 현재 구동중인 애플리케이션 없음"
else
echo "## kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
DEPLOY_WAR=$DEPLOY_PATH$WAR_NAME
echo "## DEPLOY_WAR: $DEPLOY_WAR"
nohup java -jar $DEPLOY_WAR > $DEPLOY_PATH/nohup.out 2>&1 &
* 마지막 줄(nohup)에 처음에는
nohup java -jar $DEPLOY_WAR & > /dev/null 로 줬는데 CodeDeploy "Script at specified location: restart.sh failed to close STDOUT" 에러가 나서 실패했다. 좀 찾아보니
nohup 실행 시 CodeDeploy는 무한 대기(nohup이 끝나기 전까지 CodeDeploy도 끝나지 않음)하고, 이를 해결하기 위해 nohup.out 파일을 표준 입출력용으로 별도로 사용이 필요하다 함
출처: https://velog.io/@tigger/%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94-%EA%B5%AC%EC%84%B1
5. 기존 CodeBuild 수정
- CodeBuild 설정 참조: https://happy-jjang-a.tistory.com/92
- 소스의 "buildspec.yml" 수정 및 Push
...
artifacts:
files:
- target/spring-boot-jsp-0.0.1-SNAPSHOT.war # 업로드 할 파일들
- appspec.yml # CodeDeploy 추가
- scripts/** # CodeDeploy 추가
...
- CodeBuild의 [편집 > 아티팩트]에서 아티팩트 패키징을 Zip으로 수정(war외에 appspec.yml, scripts폴더 추가 됐음으로)
- 빌드 후 S3 확인 및 다운로드 확인(zip파일로 잘 올라갔고, 다운로드 후 zip압축풀면 war, appspec.yml, sh파일 잘 있음)
5. CodeDeploy 설정
- CodeDeploy메뉴에서 시작하기의 "애플리케이션 생성" 버튼 클릭
- 이름 입력하고, [컴퓨팅 플랫폼]에 "EC2/온프레미스" 선택 후 생성
- "배포그룹" 생성 버튼 클릭
배포 그룹은 보통 개발환경, 운영환경 등 환경별로 분리
- [배포그룹이름] 입력, [서비스 역할]에 위에서 생성한 "mytest-codedeploy-Role" 선택, [배포유형]은 현재위치(In-Place) 선택
- [환경구성]에서 배포대상으로 'Amazon EC2 Auto Scaling 그룹' 선택하고, 위에서 생성한 ASG선택. [배포설정]은 일단 AllAtOnce 디폴트로 둠
* 배포설정 가이드 참조:https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/deployment-configurations.html
- [로드 밸런서]에서 '로드 밸런싱 활성화' 체크하고, 대상 그룹 선택 후 생성
- '배포생성' 버튼 클릭
- [개정 유형]에서 S3 선택하고, [개정 위치]는 zip파일이 올라간 S3의 'S3 URI' 복사해서 입력, [개정 파일 형식]은 '.zip' 선택 후 나머지 하위의 것들은 디폴트로 두고 '배포 만들기' 버튼 클릭
- 배포 상태 확인, 하단의 "View events" 클릭해서 진행 내용 확인도 가능
CodeDeploy-Agent 로그 확인 : EC2의 /var/log/aws/codedeploy-agent/codedeploy-agent.log 파일
배포 스크립트 로그: EC2의 /opt/codedeploy-agent/depolyment-root/deployment-logs/codedeploy-agent-deployment.log
- 배포 성공 확인
- 어플리케이션 ALB 접속 테스트 완료
댓글