일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 배포
- 컨테이너
- virtualization
- 도커
- spring cloud
- computer science
- Container
- spring batch
- CI/CD
- Spring Security
- HTTP
- ORM
- Spring
- 웹 서버
- 스프링 배치
- 자바
- CS
- mysql
- spring boot
- 스프링
- 데이터베이스
- JPA
- 백엔드
- web server
- 스프링 부트
- 가상화
- 영속성 컨텍스트
- 스프링 시큐리티
- vm
- Java
- Today
- Total
개발 일기
[Git Actions] 깃 액션(Git Actions)를 통한 CI/CD 본문
도입한 계기
기존에 나는 Spring Boot로 구현한 백엔드 서버를 배포하는 과정은 처음에는 수작업으로 Dockerfile을 작성하고, 빌드한 이미지를 Docker Hub에 업로드한 후 EC2 서버에서 이를 pull하는 방식으로 진행했다. Nginx 역시 config 파일과 Dockerfile을 작성하고 빌드하여 동일한 방식으로 Docker Hub에 푸시하고 EC2에서 pull해오는 과정을 거쳤다. 이러한 과정을 하나하나 수동으로 처리하다 보니, 소스 코드에 수정이 있을 때마다 수정된 버전을 재배포하기 위해 반복적으로 이미지를 삭제하고, 컨테이너를 지우는 작업을 수행해야만 했다. 이렇게 적으면서만 봐도 너무 번거럽고 귀찮은 작업이다.
이러한 반복적인 배포 과정을 자동화하기 위해 Jenkins나 GitHub Actions와 같은 CI/CD 도구를 사용할 수 있다. 이러한 도구를 활용하면 코드 변경 시 자동으로 빌드, 테스트, 배포 과정을 수행할 수 있어, 수동으로 처리해야 하는 번거로움을 줄일 수 있다고 하여 도입했다.
Git Actions가 뭐하는 애인데?
전에 CI/CD를 정리해봤었다. 지속적 통합 + 지속적 서비스 제공/배포를 더한 것으로 한마디로 코드를 수정함에 따라 이후 과정인 빌드, 테스트, 병합 그리고 배포 과정까지 모두 자동화 시켜주는 방법을 말하는 것이다.
- 깃허브 액션(Github Actions)은 깃허브에서 제공하는 서비스로 위와 같은 CI/CD를 가능케 해주는 툴이다.
- 레포지토리(원격 코드 저장소)에 특정 이벤트가 발생하면 자동으로 빌드, 테스트, 배포 등의 작업을 수행한다.
- 내가 이때까지 배포과정을 수작업으로 했다면 이제는 코드를 작성해 깃허브에 푸쉬하게되면 이후에는 "자동으로" 해당 코드에 문제가 없는지 자동으로 코드를 빌드, 테스트한 이후 배포까지 할 수 있게 된 것이다.
Git Actions 구성요소
GitHub Actions는 워크플로우(workflow)를 정의하여 다양한 이벤트에 반응하여 작업을 자동으로 실행할 수 있도록 한다.
name: CI/CD with Git Actions & Docker Hub
# 워크플로우 트리거: "createrun" 브랜치에 대한 push 및 pull request 이벤트 발생 시 실행
on:
push:
branches: [ "createrun" ]
pull_request:
branches: [ "createrun" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
# 소스 코드를 체크아웃 (클론)합니다.
- name: Checkout-source code
uses: actions/checkout@v3
# application.yml 파일 생성
- name: Set application.yml
run: |
mkdir -p ./src/main/resources
touch ./src/main/resources/application.yml
echo ${{ secrets.APPLICATION_YML }} | base64 --decode >> ./src/main/resources/application.yml
# .env파일 생성 -> OPEN AI API키 보관용
- name: Set .env file
run: |
echo ${{ secrets.ENV_FILE }} | base64 --decode > .env
# Open JDk 21
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
# Gradle 실행권한 부여
- name: Grant execute permission to gradlew
run: chmod +x ./gradlew
# Spring Boot 애플리케이션을 Gradle로 빌드 (테스트는 제외)
- name: Build with Gradle
run: ./gradlew clean build -x test
# Docker Hub에 로그인합니다.
- name: Login docker hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Spring Boot 애플리케이션의 Docker 이미지를 빌드하고 Docker Hub에 푸쉬합니다.
- name: Build and push Spring Boot app Docker image
run:
docker build -t ${{ secrets.DOCKER_REPOSITORY }}:backend --platform linux/amd64 .
docker push ${{ secrets.DOCKER_REPOSITORY }}:backend
# nginx 도커 이미지 빌드 후 도커허브에 push하기
- name: Build and push Nginx Docker image
run: |
cd ./src/main/resources/nginx-config/
docker build -t ${{ secrets.DOCKER_REPOSITORY }}:nginx --platform linux/amd64 .
docker push ${{ secrets.DOCKER_REPOSITORY }}:nginx
# Docker Compose 설정 파일을 EC2 인스턴스로 전송
- name: Send compose.yml
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }} # 퍼블릭 IPv4 DNS
username: ubuntu
key: ${{ secrets.SSH_KEY }} # cat {ec2_instance_name}.pem
port: ${{ secrets.SSH_PORT }} # 보안 그룹 인바운드 규칙의 SSH Port Number
source: "./compose.yml"
target: "/home/ubuntu/workspace/server/"
# EC2 인스턴스에서 Docker 이미지를 pull하고 Docker Compose를 사용하여 애플리케이션을 배포
- name: Deploy at EC2 instance
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }} # 퍼블릭 IPv4 DNS
username: ubuntu
key: ${{ secrets.SSH_KEY }} # cat {ec2_instance_name}.pem
port: ${{ secrets.SSH_PORT }} # 보안 그룹 인바운드 규칙의 SSH Port Number
script: |
docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
sudo docker pull ${{ secrets.DOCKER_REPOSITORY }}:backend
sudo docker pull ${{ secrets.DOCKER_REPOSITORY }}:nginx
cd /home/ubuntu/workspace/server/
sudo docker-compose down
sudo docker rmi $(docker images -q)
sudo docker-compose up -d
이게 내가 처음으로 해봤던 .github/workflows/cicd.yml파일이다.
물론 Nginx도 같이 배포를 해봤지만 그냥 80포트로 받아서 8080 스프링 부트 서버로 뿌려주는 리버스 프록시 역할만 하도록 테스트 해봤을 뿐 따로 로드 밸런싱 등 기타 기능 들을 설정하진 않아서 제쳐두고 스프링 부트가 EC2에 뿌려지는 과정을 중점으로 보겠다.
Workflows
워크플로우는 GitHub Actions의 기본 구성 단위이다. 일반적으로 ".github/workflows/<workflow_name>.yml"이라는 YAML 파일에 정의된다. 워크플로우는 하나 이상의 작업을 포함할 수 있으며 리포지토리에서 push 또는 pull request와 같은 이벤트에 의해 트리거된다.
Events
이벤트는 워크플로를 시작하는 트리거이다. 일반적인 이벤트에는 push 또는 pull request 등이 포함된다. 특정 요구 사항에 따라 워크플로를 트리거하는 사용자 지정 이벤트 만들기도 가능하다.
Jobs
작업은 워크플로 내에서 실행되는 개별 작업이다. 러너라는 가상 머신에서 실행되며 하나 이상의 단계를 포함할 수 있다. 작업은 종속성에 따라 병렬 또는 순차적으로 실행될 수 있다.
Steps
단계는 작업 내 작업의 가장 작은 단위이다. 각 단계는 셸 명령을 실행하거나 작업을 실행할 수 있다. 단계는 워크플로 파일에 지정된 순서대로 실행되며 각 단계는 동일한 실행기 인스턴스 내에서 실행된다. 위에 코드 상으로 보면 나는 11개의 단계를 포함하고 있다.
작업은 작업 흐름에서 공유 및 결합할 수 있는 재사용 가능한 코드 단위이다. GitHub 커뮤니티에서 개발 및 게시하거나 자체적으로 사용할 수 있도록 만들 수 있다. 작업은 일반적으로 별도의 리포지토리에 저장되며 해당 리포지토리 이름으로 워크플로 파일에서 참조된다.
Runners
Runners는 작업이 실행되는 가상 머신 또는 자체 호스팅 환경이다. GitHub는 다양한 운영 체제(Linux, macOS 및 Windows) 및 하드웨어 구성을 호스팅 러너에 제공하거나 보다 전문적인 요구 사항을 위해 자체 호스팅 러너를 설정할 수 있다.
Environment Variables and Secrets
환경 변수는 워크플로 내의 작업 및 스크립트에서 액세스할 수 있는 데이터를 저장하는 데 사용된다. 비밀은 액세스 토큰 또는 API 키와 같은 민감한 데이터를 저장하는 데 사용되는 암호화된 환경 변수이다. 로그에 노출되지 않으며 동일한 리포지토리에서 실행되는 작업을 통해서만 액세스할 수 있다.
Secrets는 Git Actions를 사용하는 Repo의 Settings>Secrets and variables>actions에서
하나씩 지정해줄 수 있다.
- APPLICATION_YML: 내 스프링 부트 서버의 application.yml을 base64인코딩을 거친후에 담아줌.
- DOCKERHUB_TOKEN: 도커 허브의 account settings>security>new access token을 통해 발급 받을 수 있다.
- DOCKERHUB_USERNAME: 그냥 도커 허브에서 사용하는 유저 명이다.
- DOCKER_REPOSITORY: 도커 허브에서 생성한 레포지토리 명이다.
- OPENAI_API_KEY: 프로젝트에서 gpt로 프롬프트 엔지니어링을 진행해서 openai api 키가 필요했다.
- SSH_HOST: EC2 퍼블릭 IPv4 등 IP 주소를 넣으면 된다.
- SSH_KEY
: EC2 인스턴스를 생성할 때 SSH 키 페어를 생성하는데 SSH 키 페어 중 프라이빗 키를 담고 있는 파일 형식인 .pem 키가 아마 로컬에 있을 텐데 그 경로로 가서 cat [key명].pem 이렇게하면 -----BEGIN RSA PRIVATE KEY----- 부터 -----END RSA PRIVATE KEY-----까지 모두 복사하여 넣으면 된다. - SSH_PORT: EC2 보안 그룹에서 설정해둔 SSH port를 쓰면되는데 대게는 22번을 쓰는 것 같다.
이렇게 설정들을 마치고 깃허브의 지정해준 브랜치로 푸쉬하게되면 깃 액션이 자동으로 동작하게된다.
아래에 수많은 실패들이 있지만 결국 성공을했다.
이제 들어가면 각 단계들이 저렇게 나와있고 혹시나 중간에 실패를 하게되면 왼쪽에 체크가 아닌 엑스가 되어서
왜 틀렸는지도 알 수 있게 도와준다.
이러한 툴의 도입으로 배포속도에 있어서 확실한 이점이 있는 것 같고 간편하다. 그냥 나는 푸쉬나 PR만해주면 배포까지 완료되니 너무 편리한 것 같다.
'DevOps > CI CD' 카테고리의 다른 글
[CI/CD] CI/CD란? (0) | 2024.05.20 |
---|