시작 전에 yml 파일 작성할 때 들여쓰기 항상 조심하자 !
CI & CD
CI : 지속적 통합
코드 버전 관리를 하는 VCS 시스템에 상호작용 (Merge, Push, etc)이 일어나면 자동으로 테스트와 빌드가 수행되어 안정적인 배포 파일을 만드는 과정
- 모든 소스 코드가 살아 있고 누구든 현재의 소스에 접근할 수 있는 단일 지점을 유지할 것
- 빌드 프로세스를 자동화해서 누구든 소스로부터 시스템을 빌드하는 단일 명령어를 사용할 수 있게 할 것
- 테스팅을 자동화해서 단일 명령어로 언제든지 시스템에 대한 건전한 테스트 수트를 실행할 수 있게 할 것
- 누구나 현재 실행 파일을 얻으면 지금까지 가장 완전한 실행 파일을 얻었다는 확신을 하게 할 것
CD : 지속적인 배포
위의 빌드 결과를 자동으로 운영 서버에 무중단 배포까지 진행되는 과정
Travis CI 연동하기
- [https://travis-ci.org] 접속 후 회원 가입
- 프로필 클릭 후 settings 접속
- 원하는 Repository 활성화
Travis CI 를 위한 프로젝트 설정
Spring boot 프로젝트에 build.gradle과 같은 위치에 .travis.yml 파일 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
language: java
jdk:
- openjdk8
branches:
only:
- main
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
before_install:
- chmod +x gradlew
script: "./gradlew clean build"
notifications:
email:
recipients: 연락 받을 이메일
Travis CI & AWS S3 연동하기
War 파일을 전달하기 위해 S3 (파일 저장소)와 연동을 한다.
- AWS 에서 IAM 서비스 접속
- 왼쪽 사이드바에서 사용자 -> 사용자 추가
- 이름 - 원하는 이름 입력
- 엑세스 유형 - 프로그래밍 방식 엑세스
- 사용자 권한 - 기존 정책 직접 연결
- AmazonS3FullAccess, AWSCodeDeployFull 체크
- 태그는 자유롭게
- 검토 후 생성
- 엑세스 키, 비밀 엑세스 키 확인 (현재만 보여준다. 다른 페이지 넘어가면 다시 확인할 수 없으니 본인이 기록)
Travis Key 등록
- 프로필 클릭 후 settings
- Environment Variables 에 키 등록
- Name : AWS_ACCESS_KEY, Value : 위에서 확인한 엑세스 키
- Name : AWS_SECRET_KEY, Value : 위에서 확인한 비밀 엑세스 키
이를 통해 yml 파일에서 해당 Name 으로 사용할 수 있게 됐다.
S3 만드는 과정은 생략
.travis.yml 수정
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
32
33
34
35
36
37
38
39
40
41
42
43
language: java
jdk:
- openjdk8
branches:
only:
- main
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.gradle'
before_install:
- chmod +x gradlew
script: "./gradlew clean build"
before_deploy:
- mkdir -p before-deploy
- cp script/*.sh before-deploy/
- cp appspec.yml before-deploy/
- cp build/libs/*.war before-deploy/
- cd before-deploy && zip -r before-deploy *
- cd ../ && mkdir -p deploy
- mv before-deploy/before-deploy.zip deploy/spring-nginx-CD.zip
deploy:
- provider: s3
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
bucket: springboot-build-helloworld
region: ap-northeast-2
skip_cleanup: true
acl: private
local_dir: deploy
wait-until-deployed: true
on:
all_branches: true
notifications:
email:
recipients: 연락 받을 이메일
Travis CI & AWS S3, CodeDeploy 연동하기
- AWS IAM 서비스로 이동
- 왼쪽 사이드바 역할 - 역할 만들기
- 유형의 개체 - AWS 서비스
- 사용할 서비스 - EC2
- 정책 선택 - AmazonEC2RoleforAWSCodeDeploy
- 태그는 자유롭게
- 최종 검토 후 생성
- EC2 인스턴스로 이동
- 서버가 가동중인 EC2의 IAM 역할 수정 (우클릭 - 보안)
- 방금 만든 AWS IAM 역할 설정
- EC2 인스턴스 재부팅
CodeDeploy 에이전트 설치
EC2 접속 후
1
2
3
4
5
6
7
8
aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/install . --region ap-northeast-2
chmod +x ./install
sudo apt install ruby
sudo ./install auto
sudo service codedeploy-agent status # 실행 상태 확인
CodeDeploy를 위한 권한 생성
- AWS IAM 서비스로 이동
- 왼쪽 사이드바 역할 - 역할 만들기
- 사용사례 - CodeDeploy 선택
- 권한은 1개밖에 없으므로 넘어가기
- 태그는 자유
- 최종 검토 후 생성
CodeDeploy 생성
- AWS CodeDeploy 서비스로 이동
- 애플리케이션 생성 (EC2)
- 배포 그룹 생성
- 서비스 역할 - 위에서 생성한 CodeDeploy 용 IAM 선택
- 현재 위치 (서비스가 2대 이상이면 블루/그린 선택)
- 환경구성 - Amazon EC2 인스턴스
- 배포 구성 - CodeDeployDefault.AllAtOnce (2대 이상이면 1대씩 배포, 30%, 50% 등등 선택)
본격적인 연동 시작
AWS CodeDeploy 설정은 appspec.yml 로 진행
.travis.yml 과 같은 위치에 appspec.yml 생성
1
2
3
4
5
6
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/app/step2/zip/
overwrite: yes
.travis.yml 에도 CodeDeploy 내용 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
deploy:
...
- provider: codedeploy
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
bucket: springboot-build-helloworld
key: spring-nginx-CD.zip
bundle_type: zip
application: springboot-nginx-cd
deployment_group: springboot-nginx-CD-group
region: ap-northeast-2
wait-until-deployed: true
on:
all_branches: true
해당 파일을 push 한 후에 travis CI, CodeDeploy 확인을 해보면 연동이 완료된 것을 볼 수 있다.
배포 자동화 구성
.travis.yml 파일이 있는 곳에 script 디렉터리 생성
해당 디렉터리에 deploy.sh 파일 생성
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
32
#!/bin/bash
REPOSITORY=/home/ubuntu/app/step2
PROJECT_NAME=spring-nginx-CD
echo "> Build 파일 복사"
cp $REPOSITORY/zip/*.war $REPOSITORY/
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -fl helloworld | awk '{print $1}')
echo "현재 구동 중인 애플리케이션 pid: $CURRENT_PID"
if [ -z "$CURRENT_PID" ]; then
echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> 새 애플리케이션 배포"
WAR_NAME=$(ls -tr $REPOSITORY/*.war | tail -n 1)
echo "> WAR Name: $WAR_NAME"
echo "> $WAR_NAME 에 실행권한 추가"
chmod +x $WAR_NAME
echo "> $WAR_NAME 실행"
nohup java -jar \
-Dspring.config.location=classpath:/application.properties,/home/ubuntu/app/application-rds.properties \
-Dspring.profiles.active=real \
$WAR_NAME > $REPOSITORY/nohup.out 2>&1 &
Travis 파일 수정
실제로 필요한 파일들은 jar, appspec.yml, 스크립트들 이기 때문에 모두를 압축할 필요는 없습니다.
따라서 .travis.yml 파일의 before_deploy 부분 수정
1
2
3
4
5
6
7
8
before_deploy:
- mkdir -p before-deploy
- cp script/*.sh before-deploy/
- cp appspec.yml before-deploy/
- cp build/libs/*.war before-deploy/
- cd before-deploy && zip -r before-deploy *
- cd ../ && mkdir -p deploy
- mv before-deploy/before-deploy.zip deploy/spring-nginx-CD.zip
CodeDeploy 파일 수정
permission, hooks 부분 추가
1
2
3
4
5
6
7
8
9
10
11
permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu
hooks:
ApplicationStart:
- location: deploy.sh
timeout: 60
runas: root
CodeDeploy 로그 확인
/opt/codedeploy-agent/deployment-root/deployment-logs 에 있다.
전체적인 흐름도
- User 가 코드 변경 후 push
- Travis 가 Github Web Hooking
- Travis -> S3 War 파일 전달
- Travis -> AWS CodeDeploy 배포 요청
- S3 -> AWS CodeDeploy War 파일 전달
- AWS CodeDeploy -> AWS EC2 압축 해제 후 zip 파일 전달