본문 바로가기
개발

Github Actions를 이용한 EC2 인스턴스로 스프링부트 애플리케이션 배포

by ^..^v 2022. 10. 25.
728x90
반응형

git 설치

본인 환경에 맞는 git 설치 프로그램을 내려받아 기본 설정 상태로 설치를 진행합니다. (https://git-scm.com/downloads)

 

작업개요

 

샘플 프로젝트 생성

배포할 스프링부트 애플리케이션을 생성합니다. 

스프링 스타터 프로젝트 생성

 

컨트롤러 메서드 추가

SampleApplication.java 파일에 hello() 컨트롤러 메서드를 추가합니다. 

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class SampleApplication {

	public static void main(String[] args) {
		SpringApplication.run(SampleApplication.class, args);
	}

	@GetMapping("/hello")
	public String hello() {
		return "Hello";
	}
}

 

동작 확인

스프링부트 애플리케이션 시작 후 브라우저로 http://localhost:8080/hello 주소로 접속해 동작을 확인합니다.

 

Github에 레포지터리(repository) 생성 및 이클립스 연동

레포지터리 생성

https://github.com 에 본인 계정으로 로그인 후 레포지터리를 생성합니다. 

 

원격 레포지터리의 주소를 복사합니다. 

 

액세스 토큰 생성

원격 레포지터리 접근에 사용할 액세스 토큰을 생성합니다.

 

이클립스 연동

이클립스 퍼스펙티브에 Git Repositories 뷰를 추가합니다. 

 

이클립스 하단에 Git Repositories 탭에서 Clone a Git repository를 클릭합니다. 

 

Sample 프로젝트를 git에 연결합니다.

 

프로젝트를 커밋합니다.

 

++ 기호를 클릭해서 Stage 상태를 변경하고, 커밋 메시지를 입력한 후 Commit and Push 버튼을 클릭합니다. 

 

 깃허브에 프로젝트가 등록된 것을 확인합니다.

 

이클립스에서 소스 코드를 수정한 후 깃허브에 변경 사항이 등록되는 것을 확인합니다. 

 

기본 VPC 생성

EC2 인스턴스 생성 시 사용할 기본 VPC를 생성합니다. 

 

EC2 인스턴스 생성 및 설정

EC2 인스턴스 생성

 

나머지 설정을 그대로 유지한 상태로 [인스턴스 생성] 버튼을 클릭합니다. 

 

인스턴스로 SSH 접속

 

인스턴스에 JDK 설치 

스프링부트 애플리케이션 실행을 사용할 JDK를 설치합니다. 

ubuntu@ip-172-31-11-166:~$ java -version

Command 'java' not found, but can be installed with:

sudo apt install openjdk-11-jre-headless  # version 11.0.16+8-0ubuntu1~20.04, or
sudo apt install default-jre              # version 2:1.11-72
sudo apt install openjdk-16-jre-headless  # version 16.0.1+9-1~20.04
sudo apt install openjdk-17-jre-headless  # version 17.0.4+8-1~20.04
sudo apt install openjdk-8-jre-headless   # version 8u342-b07-0ubuntu1~20.04
sudo apt install openjdk-13-jre-headless  # version 13.0.7+5-0ubuntu1~20.04

ubuntu@ip-172-31-11-166:~$ sudo apt update

ubuntu@ip-172-31-11-166:~$ sudo apt install openjdk-17-jre-headless

ubuntu@ip-172-31-11-166:~$ java -version
openjdk version "17.0.4" 2022-07-19
OpenJDK Runtime Environment (build 17.0.4+8-Ubuntu-120.04)
OpenJDK 64-Bit Server VM (build 17.0.4+8-Ubuntu-120.04, mixed mode, sharing)

 

인스턴스에 CodeDeploy Agent 설치

참고: 명령줄을 사용하여 CodeDeploy 에이전트 설치 ⇒ https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-cli.html

참고: Ubuntu Server용 CodeDeploy 에이전트 설치 ⇒ https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html

 

CodeDeploy Agent 설치에 필요한 패키지를 설치하고, 작업 디렉터리(사용자 홈 디렉터리)로 이동합니다. 

ubuntu@ip-172-31-11-166:~$ sudo apt install ruby-full
ubuntu@ip-172-31-11-166:~$ sudo apt install wget
ubuntu@ip-172-31-11-166:~$ cd /home/ubuntu

 

리전에 맞는 CodeDeploy Agent 설치 파일을 다운로드합니다.

ubuntu@ip-172-31-11-166:~$ wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
--2022-10-13 02:52:46--  https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
Resolving aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com (aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com)... 52.219.148.78
Connecting to aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com (aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com)|52.219.148.78|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 17816 (17K) []
Saving to: ‘install’

install                  100%[==================================>]  17.40K  --.-KB/s    in 0s

2022-10-13 02:52:46 (141 MB/s) - ‘install’ saved [17816/17816]

ubuntu@ip-172-31-11-166:~$ ls -al
total 48
drwxr-xr-x 4 ubuntu ubuntu  4096 Oct 13 02:52 .
drwxr-xr-x 3 root   root    4096 Oct 13 02:21 ..
-rw-r--r-- 1 ubuntu ubuntu   220 Feb 25  2020 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu  3771 Feb 25  2020 .bashrc
drwx------ 2 ubuntu ubuntu  4096 Oct 13 02:34 .cache
-rw-r--r-- 1 ubuntu ubuntu   807 Feb 25  2020 .profile
drwx------ 2 ubuntu ubuntu  4096 Oct 13 02:21 .ssh
-rw-r--r-- 1 ubuntu ubuntu     0 Oct 13 02:36 .sudo_as_admin_successful
-rw-rw-r-- 1 ubuntu ubuntu 17816 Sep 28 17:44 install	⇐ 다운로드한 install 파일에 실행 권한이 없음

 

설치 파일(install)에 실행 권한을 부여합니다. 

ubuntu@ip-172-31-11-166:~$ chmod +x ./install
ubuntu@ip-172-31-11-166:~$ ls -al
total 48
drwxr-xr-x 4 ubuntu ubuntu  4096 Oct 13 02:52 .
drwxr-xr-x 3 root   root    4096 Oct 13 02:21 ..
-rw-r--r-- 1 ubuntu ubuntu   220 Feb 25  2020 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu  3771 Feb 25  2020 .bashrc
drwx------ 2 ubuntu ubuntu  4096 Oct 13 02:34 .cache
-rw-r--r-- 1 ubuntu ubuntu   807 Feb 25  2020 .profile
drwx------ 2 ubuntu ubuntu  4096 Oct 13 02:21 .ssh
-rw-r--r-- 1 ubuntu ubuntu     0 Oct 13 02:36 .sudo_as_admin_successful
-rwxrwxr-x 1 ubuntu ubuntu 17816 Sep 28 17:44 install	⇐ 실행 권한이 부여됨

 

설치 파일을 실행해 설치를 진행합니다.

ubuntu@ip-172-31-11-166:~$ sudo ./install auto

 

에이전트의 정상 설치 및 실행을 확인합니다. 

ubuntu@ip-172-31-11-166:~$ sudo service codedeploy-agent status
● codedeploy-agent.service - LSB: AWS CodeDeploy Host Agent
     Loaded: loaded (/etc/init.d/codedeploy-agent; generated)
     Active: active (running) since Thu 2022-10-13 02:55:29 UTC; 58s ago		⇐ 정상적으로 동작되는 것을 확인
       Docs: man:systemd-sysv-generator(8)
      Tasks: 2 (limit: 1143)
     Memory: 65.0M
     CGroup: /system.slice/codedeploy-agent.service
             ├─15624 codedeploy-agent: master 15624
             └─15626 codedeploy-agent: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller of m>

Oct 13 02:55:28 ip-172-31-11-166 systemd[1]: Starting LSB: AWS CodeDeploy Host Agent...
Oct 13 02:55:29 ip-172-31-11-166 codedeploy-agent[15618]: Starting codedeploy-agent:
Oct 13 02:55:29 ip-172-31-11-166 systemd[1]: Started LSB: AWS CodeDeploy Host Agent.

 

EC2 인스턴스에서 S3 버킷에 저장된 코드를 가져올 수 있도록 권한을 부여

역할을 생성해서 권한을 부여합니다. 

 

생성한 역할을 EC2 인스턴스에 연결합니다. 

 

S3 버킷 생성

빌드한 프로젝트 코드를 압축해서 저장할 저장소로, 버킷에 저장된 파일을 EC2 인스턴스에서 가져가서 배포합니다.

 

다른 설정은 기본 설정 상태를 유지하면서 버킷을 생성합니다.

 

CodeDeploy 애플리케이션 및 배포 그룹 생성

https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/welcome.html

CodeDeploy는 Amazon EC2 인스턴스, 온프레미스 인스턴스, 서버리스 Lambda 함수 또는 Amazon ECS 서비스로 애플리케이션 배포를 자동화하는 배포 서비스입니다.

CodeDeploy에 적용할 역할을 생성

 

CodeDeploy 애플리케이션 생성

애플리케이션: 배포할 애플리케이션을 식별할 수 있는 고유 이름

 

배포 그룹 생성

배포 그룹: 개별 인스턴스 집합

 

배포 유형: 배포 그룹의 인스턴스에서 최신 애플리케이션 수정 버전을 사용 가능하게 만드는 방법

  • 현재 위치 배포: 배포 그룹의 각 인스턴스에 있는 애플리케이션이 중지되고 최신 애플리케이션 개정 버전이 설치되며 애플리케이션의 새 버전이 시작되고 유효성이 검사됩니다. 로드 밸런서를 사용하면 배포가 진행될 때 각 인스턴스를 등록 취소한 후 배포가 완료된 후 서비스로 복원할 수 있습니다. EC2/온프레미스 컴퓨팅 플랫폼을 사용하는 배포만 인 플레이스 배포를 사용할 수 있습니다.
  • Blue/Green 배포: 배포 동작은 사용하는 컴퓨팅 플랫폼에 따라 다릅니다.EC2/온프레미스 컴퓨팅 플랫폼에서의 블루/그린 배포: 배포 그룹(원래 환경)의 인스턴스가 다음 단계를 거쳐 인스턴스의 다른 집합(대체 환경)으로 대체됩니다.
    • 인스턴스는 대체 환경을 위해 프로비저닝됩니다.
    • 최신 애플리케이션 수정은 대체 인스턴스에 설치됩니다.
    • 애플리케이션 테스트 및 시스템 검증과 같은 활동에 선택적 대기 시간이 발생합니다.
    • 대체 환경의 인스턴스가 Elastic Load Balancing 로드 밸런서에 등록되고 트래픽이 이러한 인스턴스로 라우팅됩니다. 원래 환경의 인스턴스는 등록이 취소되고 종료되거나 다른 용도로 계속 실행될 수 있습니다.

 

Github Actions 설정

Github Actions에서 사용할 사용자 생성 및 권한 추가

 

AWSCodeDeployFullAccess 권한과 AmazonS3FullAccess 권한을 선택, 추가합니다.

 

Github Repository에 Secrets 추가

 

AWS_ACCESS_KEY_ID에는 액세스 키 ID 값을, AWS_SECRET_ACCESS_KEY에는 비밀 액세스 키 값을 입력합니다.

 

Github Repository에 start.sh 파일 생성

#!/usr/bin/env bash

PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/springboot-app.jar"

APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

echo "$TIME_NOW : copy $JAR_FILE" >> $DEPLOY_LOG
cp $PROJECT_ROOT/Sample/target/*.jar $JAR_FILE

echo "$TIME_NOW : run $JAR_FILE" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &

CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW : process id is $CURRENT_PID" >> $DEPLOY_LOG

 

Github Repository에 stop.sh 파일 생성

#!/usr/bin/env bash

PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/springboot-app.jar"

DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

CURRENT_PID=$(pgrep -f $JAR_FILE)

if [ -z $CURRENT_PID ]; then
	echo "$TIME_NOW : no process" >> $DEPLOY_LOG
else
	echo "$TIME_NOW : stop PID $CURRENT_PID" >> $DEPLOY_LOG
	kill -15 $CURRENT_PID
fi

 

Github Repository에 appspec.yml 파일 생성

참고: https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/reference-appspec-file-structure-files.html

version: 0.0
os: linux
files:
  - source: / 
    destination: /home/ubuntu/app
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    owner: ubuntu
    group: ubuntu
        
hooks:
  AfterInstall:
    - location: scripts/stop.sh
      timeout: 60
      runas: ubuntu
  ApplicationStart:
    - location: scripts/start.sh
      timeout: 60
      runas: ubuntu

 

Github Actions 워크 플로우 작성

name: Deploy to Amazon EC2

on:		⇐ https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on
  push:		⇐ https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push		
    branches: [ "main" ]

# 본인이 설정한 값으로 입력해야 함
env:		⇐ https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#env
  AWS_REGION: ap-northeast-2
  S3_BUCKET_NAME: myanjini-cicd-bucket
  CODE_DEPLOY_APPLICATION_NAME: my-codedeploy-app
  CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: my-codedeploy-deployment-group

permissions:	⇐ https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
  contents: read

jobs:		⇐ https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobs
  deploy:			⇐ jobs.<job_id>
    name: Deploy		⇐ jobs.<job_id>.name
    runs-on: ubuntu-latest	⇐ jobs.<job_id>.runs-on
    environment: production	⇐ jobs.<job_id>.environment
    steps:			⇐ jobs.<job_id>.steps
    - name: Checkout
      uses: actions/checkout@v3				⇐ https://github.com/actions/checkout

    - name: Set up JDK 11
      uses: actions/setup-java@v3			⇐ https://github.com/actions/setup-java
      with:
        distribution: 'temurin'
        java-version: '11'  

    - name: Build with Maven 
      run: mvn -B package --file ./Sample/pom.xml	⇐ jobs.<job_id>.steps[*].run

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1	⇐ https://github.com/aws-actions/configure-aws-credentials
      with: 
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ env.AWS_REGION }}

    # https://docs.aws.amazon.com/cli/latest/reference/deploy/push.html
    - 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 . 

    # https://docs.aws.amazon.com/cli/latest/reference/deploy/create-deployment.html
    - 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

 

자동 배포 확인

이클립스에서 소스 코드 수정 후 Commit & Push

 

Github Actions 확인

 

S3 버킷 확인

 

CodeDeploy 배포 확인

 

EC2 인스턴스에서 스프링부트 애플리케이션 실행을 확인

ubuntu@ip-172-31-11-166:~$ ps -ef | grep jar
ubuntu      1058       1  2 02:04 ?        00:00:06 java -jar /home/ubuntu/app/springboot-app.jar
ubuntu      1202    1192  0 02:08 pts/0    00:00:00 grep --color=auto jar

ubuntu@ip-172-31-11-166:~$ pgrep -f springboot-app.jar
1058

 

EC2 인스턴스의 퍼블릭 주소를 확인한 후 브라우저를 이용해서 스프링부트 애플리케이션을 호출

 

 

http://3.36.119.172:8080/hello  ⇒ 연결되지 않음

 

보안그룹에 8080 포트를 인바운트 포트로 등록 

 

 

리소스 정리

Github Actions

 

S3 버킷 비우고 삭제

 

 EC2 인스턴스 종료

 

CodeDeploy 애플리케이션 삭제

 

기본 VPC 삭제

 

728x90
반응형

'개발' 카테고리의 다른 글

카카오 로그인  (0) 2023.04.06
네이버 로그인  (0) 2023.04.06
EC2 인스턴스에 React + SpringBoot + MySQL 연동  (0) 2023.03.29
폼 데이터와 함께 파일 업로드  (0) 2023.02.21
그래들 빌드 및 실행  (0) 2023.01.17

댓글