CI & CD 소개
코드 버전 관리를 하는 VCS 시스템(Git, SVN 등)에 PUSH가 되면 자동으로 테스트와 빌드가 수행되어 안정적인 배포 파일을 만드는 과정을 CI(Continuous Integration - 지속적 통합)이라고 하며, 이 빌드 결과를 자동으로 운영 서버에 무중단 배포까지 진행되는 과정을 CD(Continuous Deployment - 지속적인 배포) 라고 한다.
CI 도구들
1. Jenkins
Jenkins는 정말 많이 사용한다. EC2에 Jenkins를 설치해야 한다. 그리고 과금이 있다. 그러므로 Pass
2. Travis CI
지금 내가 읽고 있는 책도 Travis CI로 CI/CD를 구현하셨다. Travis를 사용해도 되지만 구글링을 해본 결과 속도가 굉장히 느리다고 한다. 그래서 이것도 Pass
3. Github Action
Github Action은 일단 github repository에서 관리할 수 있다. 속도가 빠르고 상대적으로 요즘 많이 사용한다고 한다. 크롤링도 할 수 있다고 한다. 그래서 나는 내가 만든 프로젝트를 Github Action을 사용해 CI/CD를 해볼려고 한다.
일단 지금 내가 하고 있는 프로젝트는 용량도 크지않고 사용량도 적기 때문에 EC2 프리티어 인스턴스에서 과금을 유발하지 않는다. 나중에 Docker를 이용해 더 확장해보고 싶다.
여기서 slack 대신 Discord로 할 생각이다.
CI/CD 과정
- github에 push 한다.
- github action에서는 빌드 및 테스트를 진행한다.
- 빌드 결과인 Jar 파일을 AWS S3에 업로드 한다.
- AWS CodeDeploy의 배포 그룹에 등록된 EC2로 Jar 파일을 업로드한다.
- EC2에서 미리 작성한 배포 스크립트가 실행된다.
https://bcp0109.tistory.com/363
이 블로그를 참고하여 공부했다.
EC2 설정
만들어 논 EC2 인스턴스에 추가해야할 것이 있다.
- Tag 추가 (CodeDeploy 에서 어떤 인스턴스에 실행할 지 구분하는 값)
- IAM 역할 등록
- EC2 서버에 CodeDeploy Agent 설치
Tag 추가
사용할 인스턴스에 설정에 들어가 태그를 추가 해준다.
IAM 역할 추가
IAM은 AWS에서 제공하는 인증 및 권한 부여 서비스이다. IAM을 사용하면 AWS 리소스에 대한 액세스를 안전하고 제어 가능한 방식으로 관리할 수 있다.
여기서 역할을 추가해줘야 한다. 어떤 역할이냐면 EC2 인스턴스에서 S3에 올려놓은 파일에 접근할 수 있도록 권한을 추가해줘야 한다.
- 역할 추가에 들어가 엔티티 선택은 AWS 서비스, 사용 사례는 EC2를 선택한다
- AmazonS3FullAccess를 추가하고 생성을 완료한다.
- 이 후 다시 인스턴스에 돌아가 방금 만든 IAM을 추가해주면 된다.
CodeDeploy Agent 설치하기
$ sudo apt update
$ sudo apt install ruby-full
$ sudo apt install wget
$ cd /home/ubuntu
$ wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
$ chmod +x ./install
$ sudo ./install auto > /tmp/logfile
$ sudo service codedeploy-agent status
amazon에서 알려주는 방법대로 그대로 치면 된다.
AWS S3 생성
버킷을 생성하면 된다. 이 때 모든 요소를 제일 처음 선택된 요소로 선택하면 된다.
- AWS 리전 = 서울
- ACL 비활성화
- 모든 퍼블릭 엑세스 차단
- 버킷 버전 관리 = 비활성화
- 기본 암호화 = 비활성
CodeDeploy 생성
CodeDeploy IAM 생성
CodeDeploy를 사용하기 위해선 IAM 에서 역할을 만들어야 한다.
역할은 위에와 비슷하게 만들지만 사용사례에서 다르다.
- 사용 사례는 다른 AWS 서비스의 사용 사례 = CodeDeploy를 선택해야 한다.
- 권한은 AWSCodeDeployRole을 선택하면 된다.
CodeDeploy 애플리케이션 생성
이제 CodeDeploy에서 애플리케이션을 생성해야 한다.
- 컴퓨팅 플랫폼은 EC2/온프레머스를 선택한다.
그 후 배포 그룹을 생성해야 한다.
- 서비스 역할 = 방금 위에서 만든 IAM
- 배포 유형은 현재 위치
- Amazon EC2 인스턴스 생성(태그 등록)
- 배포 구성 = CodeDeployDefault.AllAtOnce 등록
- 로드 밸런서는 하지 않는다 (과금 ㅜㅜ)
Github Actions 에서 사용할 IAM 사용자 추가
AWS 를 Github Actions 워크 플로우에서 접근하려면 권한이 필요하다.
지금까지는 IAM 역할만 추가해서 특정 서비스에게 부여했지만 이번에는 IAM 사용자를 추가해야 한다.
사용자 추가
엑세스 관리에서 사용자를 선택하고 사용자 추가를 한다.
- 사용자 이름을 설정한다.
- 접근 권한은 AWSCodeDeployFull과 AmazonS3FullAccess를 선택한다.
- 사용자 만들기를 완료한다.
예전에는 사용자를 만들 때 바로 엑세스키와 Secret Key를 만들 수 있었다. 하지만 이제 정책이 바뀌어 만들 수 없다고 한다.
보안 자격 증명을 선택하면 엑세스 키를 만드는 부분이 있다!! 이것을 Git Repository에 등록해주면 된다.
AppSpec.yml 생성
이제 서버에 띄울 EC2, 배포할 결과물을 저장할 S3, 배포를 도와줄 CodeDeploy 이렇게 3가지 AWS 서비스를 만들었다.
이제 CodeDeploy 에서 배포를 위해 참조할 AppSpec 파일을 만든다. 참고로 이 파일은 루트에 있어야한다.
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/app/step1
overwrite: yes //복사할 위치에 파일이 있는 경우 대체
permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu
hooks:
ApplicationStart:
- location: script/deploy.sh
timeout: 60
runas: ubuntu
지금 내 파일 저장소는 /home/ubuntu/app/step1에 존재한다. 그리고 permissions를 통해 지금 내 EC2 접근을 허락한다.
hooks가 중요하다. hooks는 일련의 라이프사이클이 존재해서 적절한 Hook을 찾아 실행할 스크립트를 지정한다.
저번 블로그 글에 deploy.sh를 만들었다. 그러므로 나는 Application이 시작할때 저 스크립트를 실행 시킬 것이다. 그러면 자동 배포가 완료된다. timeout (optional)은 스크립트 실행에 허용되는 최대 시간이며, 넘으면 배포 실패로 간주된다.
build.gradle 파일 수정
스프링 부트2.5 버전부터는 빌드 시 일반 jar 파일 하나와 -plain.jar 파일 하나가 같이 만들어진다. 그러므로 빌드 시 plain jar 파일은 만들어지지 않도록 build.gradle 파일에 내용을 추가해야 한다.
jar {
enabled = false
}
Github Actios Workflow 작성
이제 Workflow를 작성해야한다. Git Repository에 Actios를 선택해 EC2에 대해 만들면 된다.
난 이것을 선택하고 변경해주었다.
name: Deploy to Amazon EC2
on:
push:
branches: [ "master" ] //master에서만 실행
env:
AWS_REGION: ap-northeast-2
S3_BUCKET_NAME: heron-github-actions-s3-bucket
CODE_DEPLOY_APPLICATION_NAME: heron-codedeploy-app
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: Heron-codedeploy-deployment-group
permissions:
contents: read
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production
steps:
# (1) 기본 체크아웃
- name: Checkout
uses: actions/checkout@v3
# (2) JDK 17 세팅
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Run chmod to make gradlew executable //Gradle 권한을 변경해줘야 실행 가능하다.
run: chmod +x ./gradlew
# (3) Gradle build (Test 제외)
- name: Build with Gradle
uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee
with:
arguments: clean build -x test //Test는 하지 않는다.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# (5) 빌드 결과물을 S3 버킷에 업로드
- name: Upload to AWS S3
run: |
aws deploy push \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--ignore-hidden-files \
--s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \
--source .
# (6) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행
- name: Deploy to AWS EC2 from S3
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip
(5) AWS S3에 업로드 하기
- --application-name: (문자열) 필수. 애플리케이션 개정과 연관된 CodeDeploy 애플리케이션의 이름.
- --ignore-hidden-files 또는 --no-ignore-hidden-files: (부울) 선택 사항. --no-ignore-hidden-files
플래그(기본값)를 사용하여 숨겨진 파일을 번들링하고 Amazon S3로 업로드합니다. - --s3-location: (문자열) 필수. Amazon S3에 업로드할 애플리케이션 개정의 위치에 대한 정보. Amazon S3 버킷과 키를 지정해야 합니다.
- --source (문자열) 선택 사항. 배포할 콘텐츠와, 압축하여 Amazon S3로 업로드될 개발 시스템 상의 AppSpec 파일의 위치, 지금은 현재 위치에 저장
(6) CodeDeploy 실행
- --application-name : CodeDeploy 애플리케이션 이름
- --deployment-config-name : 배포 방식인데 기본값을 사용 (CodeDeploy 만들 때 설정한 것)
- --deployment-group-name : CodeDeploy 배포 그룹 이름
- --s3-location : 버킷 이름, 키 값, 번들타입
트러블 슈팅
중간에 보면 Gradle의 권한을 변경해주는 부분이 존재한다. 저 부분을 변겅을 안해줘서 오류가 엄청 많이 났다.
지금 배포 당시에는 JAR 파일에 대한 실행 권한이 없다. 그러므로 한번 실행가능하게 변경해줘야 한다!!
성공!!
CodeDeploy에도 성공한 모습이다.
시험 삼아서 이름을 바꿔서 push 해봤는데 바로 변경 되었다!!!.
다만 배포하는 과정에서 잠시동안 멈춘다. 아마 삭제하고 다시 실행하기 때문인 것 같다. 그러므로 이제 무중단 배포에대해 공부하러 가야겠다!!!
'토이프로젝트 > 스프링 부트로 구현한 웹' 카테고리의 다른 글
Github Action으로 자동배포 문제점 해결하기 (0) | 2023.03.15 |
---|---|
서브모듈을 이용해 application관리하기 (1) | 2023.03.12 |
EC2 서버에 프로젝트 배포하기 (0) | 2023.03.12 |
스프링 시큐리티와 OAuth2.0으로 로그인 기능 구현하기 - 네이버 (0) | 2023.03.09 |
세션 저장소로 데이터베이스 사용하기 (0) | 2023.03.09 |