Cloud/AWS

[AWS] Spring Boot, Jenkins, CodeDeploy로 CI/CD 하기

백엔드 규니 2021. 4. 6. 10:07
728x90
반응형

들어가기 전에

이번 글에서 CI/CD를 할 때는 위의 아키텍쳐로 진행하려고 합니다. (다만, Auto Scaling은 사용하지 않고 운영용 EC2 1대, Jenkins 빌드용 EC2 1대를 사용할 예정입니다.)


그래서 사용한 도구에 대해서 정리하면 아래와 같습니다.

  • Spring Boot(gradle)
  • EC2 Linux2 2대(운영용 프리티어 1대, 젠킨스 빌드용 RAM 16G 1대)
  • Jenkins(CI)
  • CodeDeploy(CD)
  • S3 Bucket
  • Docker
  • Github Hook

 

이러한 기술들을 사용해서 CI/CD를 진행하는 글을 이어나가겠습니다. 추가로 이번 글에서 EC2 생성, S3 버켓 생성, CodeDeploy 생성, IAM 사용자 권한 부여 등등 같은 것들에 대해서는 다루지 않겠습니다.

 

 

 

EC2 인스턴스 생성하기

jenkins를 사용할 때 EC2 프리티어로 사용하니까 빌드를 할 때마다 EC2가 맛이가는 문제가 발생했습니다. 그래서 여기 에서 저와 비슷한 상황의 분을 찾았는데 역시.. EC2 프리티어로는 버티기가 힘들었던 거 같습니다. 그래서 젠킨스 빌드용 EC2는 성능 좋은 것으로 생성해보겠습니다. (운영용 EC2는 프리티어 Linux2로 이미 만들어놓았습니다.)

 

123

 

위와 같이 RAM 16G로 하나 생성하겠습니다.

 

 

 

EC2 Linux2에 Docker 설치하기

sudo yum update -y
sudo amazon-linux-extras install -y docker
sudo service docker start

그리고 EC2에 접속한 후에 위의 명령어로 EC2에 Docker를 설치하겠습니다.

 

 

 

docker로 jenkins 설치하기

sudo docker run -d --name jenkins -p 32789:8080 jenkins/jenkins:jdk11

스크린샷 2021-04-05 오전 12 09 37

위와 같이 컨테이너가 잘 실행되고 있다면 http://EC2-IP:32789로 접속하겠습니다.

 

 

스크린샷 2021-04-05 오전 12 08 58스크린샷 2021-04-05 오전 12 13 44

sudo docker exec -it jenkins bash  // jenkins bash 쉘 접속
cat /var/jenkins_home/secrets/initialAdminpassword

위와 같이 jenkins bash에 접속해서 비밀번호를 알아낸 후 접속하겠습니다.

 

 

 

스크린샷 2021-04-05 오전 12 16 43스크린샷 2021-04-05 오전 12 20 15

 

그리고 원하는 계정으로 가입을 하겠습니다.

 

 

스크린샷 2021-04-05 오전 12 21 26스크린샷 2021-04-05 오전 12 21 32

 

 

스크린샷 2021-04-05 오전 12 24 55

 

그리고 현재 Jenkins로 CI(빌드 및 테스트)를 하고 이 결과를 S3에 저장합니다. 그리고 저장된 빌드 파일을 AWS CodeDeploy가 EC2에 CD(자동 배포)를 해주는 것이기 때문에 Jenkins에 CodeDeploy 플러그인을 설치하겠습니다.

 

 

 

스크린샷 2021-04-05 오전 12 30 05스크린샷 2021-04-05 오전 12 31 03

 

그리고 위와 같이 프로젝트를 하나 생성하겠습니다.

 

 

 

스크린샷 2021-04-05 오전 12 32 48스크린샷 2021-04-05 오후 5 35 27

 

Github에 push가 되었을 때 Github이 Jenkins에 Hook을 날려 자동 빌드할 수 있도록 Github hook Trigger를 선택하겠습니다.(아래에서 Github Hook 설정을 하게 됩니다.)

 

./gradlew clean build

그리고 Build 부분을 보면 위와 같이 적었습니다. Spring Boot gradle은 위의 명령어를 통해서 jar 파일을 만들기 때문입니다.

 

 

스크린샷 2021-04-05 오전 12 41 36

 

또한 이번에는 빌드 후 조치로 Jenkins 빌드가 끝난 이후에 CodeDeploy가 배포하는 단계의 설정입니다.

 

 

스크린샷 2021-04-05 오후 5 33 38스크린샷 2021-04-05 오전 12 48 20

  • AWS S3 Bucket, CodeDeploy 애플리케이션, 배포 그룹을 만들었을텐데 그것의 이름을 위에 맞게 적으면 됩니다.
  • Include Files를 보면 CodeDeploy가 EC2로 옮길 파일들을 적는 것입니다.(**/*.jar, **/appspec.yml, **/scripts/* 라고 적었습니다. Dockerfile은 이 글에서 다루지 않기 때문에 적지 않아도 괜찮습니다.)
  • 마지막으로 IAM 사용자에게 발급받은 액세스 키, 비밀 엑세스 키가 있을 것입니다. 그것을 입력하겠습니다.

 

그러면 이제 Jenkins에 대한 기본적인 설정은 끝났습니다.

 

 

 

Github WebHook 추가

Github에 push가 되었을 때 Jenkins로 Hook을 날려 빌드가 실행되도록 하는 역할을 합니다.

 

스크린샷 2021-04-05 오전 12 50 38스크린샷 2021-04-05 오전 12 51 02

  • PayLoad URL에 http://{EC2 IP}:32789/github-webhook/을 입력하겠습니다.(마지막에 / 안쓰면 302에러 뜨니 꼭 써야 합니다!)
  • application/json 선택

 

 

스크린샷 2021-04-05 오전 12 53 12

그리고 위와 같이 초록색 체크 버튼이 떠야 제대로 등록이 된 것입니다.

 

 

 

EC2 Linux2 CodeAgent 설치하기

CodeDeploy가 EC2에 배포를 하기 위해서는 CodeAgent 설치가 필요합니다. 그래서 아래의 명령어를 통해서 설치를 하겠습니다.

sudo yum install -y aws-cli
cd /home/ec2-user/ 
sudo aws configure 
wget https://aws-codedeploy-ap-northeast-2.s3.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto (/usr/bin/env: ruby: No such file or directory 이런 에러 난다면 아래 설치)
sudo yum install ruby
sudo service codedeploy-agent status

test

여기서도 Jenkins에서 입력했던 것과 마찬가지로 IAM 사용자의 액세스 키, 비밀 엑세스 키를 입력해주면 됩니다.

 

 

 

스크립트 파일과 yml 파일 작성하기

CodeDeploy가 배포를 어디에 어떤 과정으로 할 지를 담은 파일은 appspec.yml이고, deploy.sh는 EC2 내부에서 동작하도록 만든 스크립트 파일입니다.

스크린샷 2021-04-06 오전 9 47 37

 

파일의 구조는 위와 같습니다. 하나씩 작성을 해보겠습니다.

 

 

 

appspec.yml

version: 0.0
os: linux
files:
  - source:  /
    destination: /home/ec2-user/jenkins  # EC2 내부 배포 할 위치
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    owner: ec2-user
    group: ec2-user

hooks:
  ApplicationStart:
    - location: scripts/deploy.sh    # ApplicationStart 단계에서 해당 파일을 실행해라
      timeout: 60
      runas: ec2-user

 

 

deploy.sh

#!/bin/bash
BUILD_JAR=$(ls /home/ec2-user/jenkins/build/libs/*.jar)     # jar가 위치하는 곳
JAR_NAME=$(basename $BUILD_JAR)
echo "> build 파일명: $JAR_NAME" >> /home/ec2-user/deploy.log

echo "> build 파일 복사" >> /home/ec2-user/deploy.log
DEPLOY_PATH=/home/ec2-user/
cp $BUILD_JAR $DEPLOY_PATH

echo "> 현재 실행중인 애플리케이션 pid 확인" >> /home/ec2-user/deploy.log
CURRENT_PID=$(pgrep -f $JAR_NAME)

if [ -z $CURRENT_PID ]
then
  echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다." >> /home/ec2-user/deploy.log
else
  echo "> kill -15 $CURRENT_PID"
  kill -15 $CURRENT_PID
  sleep 5
fi

DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "> DEPLOY_JAR 배포"    >> /home/ec2-user/deploy.log
nohup java -jar $DEPLOY_JAR >> /home/ec2-user/deploy.log 2>/home/ec2-user/deploy_err.log &

위의 스크립트 파일을 통해서 최종 자동 배포의 과정이 일어나는 것입니다. 그리고 Github의 아래와 같이 간단한 Controller를 만든 후에 push를 해보겠습니다.

 

 

스크린샷 2021-04-06 오전 9 56 48

 

스크린샷 2021-04-05 오후 5 31 36

 

그러면 위와 같이 Jenkins CI가 성공한 것도 확인할 수 있습니다. 또한 CodeDeploy도 성공 되었나 확인해보겠습니다.

 

 

스크린샷 2021-04-06 오전 9 58 33

그리고 CodeDeploy도 보면 성공한 것을 볼 수 있습니다. 성공했다면 EC2에도 파일들이 잘 배포가 되었을 것입니다.

 

 

스크린샷 2021-04-06 오전 9 54 15

실제로 EC2 내부를 보면 위와 같이 파일들이 잘 전달된 것을 볼 수 있습니다.

 

 

스크린샷 2021-04-06 오전 10 00 04

그리고 보면 실제로 8080 포트의 java가 실행되고 있는 것을 볼 수 있습니다.

 

 

스크린샷 2021-04-06 오전 10 01 08

 

다음 포스팅에서는 배포 파일을 좀 더 깔끔하게 EC2에 올리고 Docker로 이미지를 만들어 컨테이너로 실행시키는 것에 대해서 다뤄보겠습니다. 

반응형