CI/CD(Continuous Integration/Continuous Delivery)란?
CI/CD(지속적 통합/지속적 배포)는 애플리케이션 개발 단계를 자동화하는 방법이다.
CI/CD 종류(Jenkins, Github Actions)
저는 Github Acions를 이용했습니다.
GithubActions
yml 파일을 이용해 자동화를 수행 할 workflow를 설정
Github에서 발생하는 이벤트(push, merge)를 트리거로 동작 시킨다.
CI/CD 프로세스(Back-end: Spring boot)
1. 원격 저장소에 있는 main branch에 push를 기준으로 트리거
2. 프로젝트 빌드
3. 서버에 ssh 접속
4. 기존의 jar 파일 백업
5. jar파일 전송
6. 실행 권한 변경 및 docker 재시작
yml 작성 전 Github Action으로 서버에 ssh 접속을 위한 key 값 설정
경로 : Git Repository -> Settings -> Secrets and variables -> Actions
New repository secret 을 클릭해 이런식으로 추가해준다.
STAGING_SSH_HOST: ip 혹은 Domain
STAGING_SSH_KEY: 발급 받은 Private Key 값( 밑에서 자세하게 설명)
STAGING_SSH_PORT: 22(ssh 기본 접속 포트)
STAGING_SSH_USER: 서버에 유저 name
ssh-keygen으로 서버 SSH_KEY 발급 받기
윈도우 CMD (public key, private key 발급)
ssh-keygen -t rsa -b 4096 -C "example@gmail.com"
명령 입력 후
1. Key를 저장할 경로 지정 (기본값: $HOME/.ssh/id_rsa)
2. 추가로 사용할 암호(기본값: 없음)
3. 암호 확인
저는 암호는 추가로 설정하지 않아서 Enter 키를 눌러주고 넘어갔습니다.
Public Key 서버에 저장
/.ssh/authorized_keys 파일에 공개키를 넣어줍니다.
(최초 발급 받은 공개키에서 enter나 space등 다른 값들이 잘 못들어가지 않게 주의)
홈(/)에 .ssh 폴더가 없다면
# 홈(/)경로에 .ssh 폴더만들기
mkdir /.ssh
# .ssh 폴더에 authorized_keys 파일 만들기
vi /.ssh/authorized_keys
Private Key Github Actions에 Key값 넣어주기
STAGING_SSH_KEY: 발급 받은 Private Key 값
( -----BEGIN OPENSSH PRIVATE KEY-----와 -----END OPENSSH PRIVATE KEY----- 부분까지 넣어줍니다.)
Workflow yml 작성
name: Multi-Module Deployment # Workflow의 이름을 지정합니다.
on: # Workflow의 트리거 조건을 설정합니다.
push: # 코드가 push 될 때마다 실행되는 조건을 설정합니다.
branches: [ "main" ] # main 브랜치에 push가 발생할 때만 실행됩니다.
permissions: # Workflow가 GitHub Repository 내에서 수행할 수 있는 권한을 설정합니다.
contents: read # 이 Workflow는 리포지토리의 컨텐츠를 읽는 것만 허용됩니다.
jobs: # Workflow 내에서 실행될 작업을 정의합니다.
deploy: # deploy라는 이름의 작업을 정의합니다.
runs-on: ubuntu-latest # 이 작업은 ubuntu-latest 가상 환경에서 실행됩니다.
steps: # 작업의 단계를 순차적으로 나열합니다.
- name: checkout # 현재 GitHub 리포지토리의 코드를 체크아웃합니다.
uses: actions/checkout@v3 # actions/checkout 액션을 v3 버전으로 사용합니다.
- name: Set up JDK 17 # JDK 17을 설정합니다.
uses: actions/setup-java@v3 # actions/setup-java 액션을 v3 버전으로 사용합니다.
with:
java-version: '17' # 사용할 Java의 버전을 지정합니다.
distribution: 'temurin' # Java 배포판을 temurin으로 지정합니다.
- name: Grant execute permission for gradlew # gradlew 파일에 실행 권한을 부여합니다.
run: chmod +x gradlew # chmod 명령어를 사용하여 gradlew 파일에 실행 권한을 추가합니다.
- name: Build with Gradle # Gradle을 사용하여 빌드합니다.
uses: gradle/gradle-build-action@v2.2.1 # gradle/gradle-build-action 액션을 v2.2.1 버전으로 사용합니다.
with:
arguments: clean build # gradle 명령어 인자로 clean build를 실행합니다.
- name: Configure SSH # SSH 설정을 구성합니다.
run: | # 다음의 스크립트를 실행하여 SSH 설정을 합니다.
mkdir -p ~/.ssh/
echo "$SSH_KEY" > ~/.ssh/staging.key
chmod 600 ~/.ssh/staging.key
cat >>~/.ssh/config <<END
Host staging
Port $SSH_PORT
HostName $SSH_HOST
User $SSH_USER
IdentityFile ~/.ssh/staging.key
StrictHostKeyChecking no
END
chmod 400 ~/.ssh/config
env: # 환경 변수를 설정합니다.
SSH_USER: ${{ secrets.STAGING_SSH_USER }}
SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
SSH_HOST: ${{ secrets.STAGING_SSH_HOST }}
SSH_PORT: ${{ secrets.STAGING_SSH_PORT }}
- name: ssh 1 connect # SSH를 통해 서버에 첫 번째로 연결합니다.
uses: appleboy/ssh-action@master # appleboy/ssh-action 액션을 사용하여 SSH 연결을 수행합니다.
with:
host: ${{ secrets.STAGING_SSH_HOST }}
username: ${{ secrets.STAGING_SSH_USER }}
key: ${{ secrets.STAGING_SSH_KEY }}
port: ${{ secrets.STAGING_SSH_PORT }}
script: | # 다음 스크립트를 서버에서 실행합니다.
echo /home/${{ secrets.STAGING_SSH_USER }}
cd /home/${{ secrets.STAGING_SSH_USER }} &&
mv admin-api-0.0.1-SNAPSHOT.jar admin-api-0.0.1-SNAPSHOT-$(date +'%Y%m%d%H%M%S').jar &&
mv client-api-0.0.1-SNAPSHOT.jar client-api-0.0.1-SNAPSHOT-$(date +'%Y%m%d%H%M%S').jar
env:
SSH_USER: ${{ secrets.STAGING_SSH_USER }}
- name: scp jar # jar 파일을 서버로 안전하게 복사합니다.
run: |
rm -f ~/.ssh/known_hosts # 기존에 저장된 known_hosts 파일을 삭제합니다. 이는 서버의 호스트 키가 변경되었을 때 발생하는 문제를 방지합니다.
scp -v admin-api/build/libs/admin-api-0.0.1-SNAPSHOT.jar staging:/home/$SSH_USER/admin-api-0.0.1-SNAPSHOT.jar # admin-api jar 파일을 서버의 지정된 위치로 복사합니다.
scp -v client-api/build/libs/client-api-0.0.1-SNAPSHOT.jar staging:/home/$SSH_USER/client-api-0.0.1-SNAPSHOT.jar # client-api jar 파일을 서버의 지정된 위치로 복사합니다.
env: # SCP 명령을 실행할 때 사용할 환경 변수들을 설정합니다.
SSH_USER: ${{ secrets.STAGING_SSH_USER }} # 서버의 SSH 사용자 이름
SSH_HOST: ${{ secrets.STAGING_SSH_HOST }} # 서버의 호스트 주소
- name: ssh 2 connect # SSH를 통해 서버에 두 번째로 연결합니다.
uses: appleboy/ssh-action@master # appleboy/ssh-action 액션을 사용하여 SSH 연결을 수행합니다.
with:
host: ${{ secrets.STAGING_SSH_HOST }} # SSH 호스트 정보
username: ${{ secrets.STAGING_SSH_USER }} # SSH 사용자 이름
key: ${{ secrets.STAGING_SSH_KEY }} # SSH 키
port: ${{ secrets.STAGING_SSH_PORT }} # SSH 포트
script: | # 다음 스크립트를 서버에서 실행합니다.
chmod 755 /home/${{ secrets.STAGING_SSH_USER }}/admin-api-0.0.1-SNAPSHOT.jar # admin-api jar 파일에 실행 권한을 부여합니다.
chmod 755 /home/${{ secrets.STAGING_SSH_USER }}/client-api-0.0.1-SNAPSHOT.jar # client-api jar 파일에 실행 권한을 부여합니다.
env: # SSH 연결을 위한 환경 변수들을 설정합니다.
SSH_USER: ${{ secrets.STAGING_SSH_USER }} # 서버의 SSH 사용자 이름
Git push main을 트리거로 Github Actions에 들어가 확인 할 수 있다.
같은 방식으로 Vue프로젝트에도 적용하면 되기 때문에 프론트쪽 workflow만 예시로 보여드릴게요
# 이 워크플로우는 Node.js 의존성을 깨끗하게 설치하고, 캐시/복원하며, 소스 코드를 빌드하고 다양한 버전의 Node에서 테스트를 실행합니다.
# 자세한 정보는 다음에서 확인할 수 있습니다: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: Node.js CI # 워크플로우의 이름을 설정합니다.
on: # 워크플로우가 언제 실행될지 설정합니다.
push:
branches: [ "main" ] # main 브랜치에 푸시가 발생할 때
jobs:
build: # 빌드 작업을 정의합니다.
runs-on: ubuntu-latest # 작업이 실행될 환경을 설정합니다. 여기서는 최신의 Ubuntu를 사용합니다.
strategy:
matrix:
node-version: [18.16.0] # 사용할 Node.js 버전을 설정합니다.
steps:
# 0. 체크아웃
- name: checkout
uses: actions/checkout@v3 # GitHub 저장소를 체크아웃하기 위한 액션입니다.
# 1. Node.js 환경 설정
- name: Set up Node.js
uses: actions/setup-node@main # Node.js를 설정하기 위한 액션입니다.
with:
node-version: 18.x # Node.js의 버전을 설정합니다.
# SSH 설정
- name: Configure SSH
run: | # 서버에 SSH로 접근하기 위한 설정을 합니다.
mkdir -p ~/.ssh/
echo "$SSH_KEY" > ~/.ssh/staging.key
chmod 600 ~/.ssh/staging.key
cat >>~/.ssh/config <<END
Host staging
Port $SSH_PORT
HostName $SSH_HOST
User $SSH_USER
IdentityFile ~/.ssh/staging.key
StrictHostKeyChecking no
END
chmod 400 ~/.ssh/config
env: # SSH 연결을 위한 환경 변수를 설정합니다.
SSH_USER: ${{ secrets.STAGING_SSH_USER }}
SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
SSH_HOST: ${{ secrets.STAGING_SSH_HOST }}
SSH_PORT: ${{ secrets.STAGING_SSH_PORT }}
# 2. 의존성 패키지 설치
- name: Install dependencies
run: npm install # npm을 사용하여 프로젝트 의존성을 설치합니다.
# 3. 빌드
- name: Build Page
run: npm run build # 프로젝트를 빌드합니다.
env:
NODE_ENV: production # NODE_ENV 환경 변수를 production으로 설정합니다.
# 4. 기존 빌드 파일 백업
- name: Backing Up Existing Build Files
uses: appleboy/ssh-action@master # SSH를 통해 서버에 접속하여 백업 스크립트를 실행합니다.
with:
host: ${{ secrets.STAGING_SSH_HOST }}
username: ${{ secrets.STAGING_SSH_USER }}
key: ${{ secrets.STAGING_SSH_KEY }}
port: ${{ secrets.STAGING_SSH_PORT }}
script: | # 기존에 있는 dist 디렉토리를 백업합니다.
pwd
cd /home/${{ secrets.STAGING_SSH_USER }}/jed-vue &&
mv dist dist-$(date +'%Y%m%d%H%M%S')
env:
SSH_USER: ${{ secrets.STAGING_SSH_USER }}
# 5. 배포
- name: Deploy Vue Application
run: | # 압축된 빌드 파일을 서버로 전송하고 기존 파일을 제거합니다.
rm -f ~/.ssh/known_hosts
tar -czvf dist.tar.gz ./dist
scp dist.tar.gz staging:/home/$SSH_USER/jed-vue/
rm -f dist.tar.gz
env:
SSH_USER: ${{ secrets.STAGING_SSH_USER }}
# 6. 서버에서 압축 파일 해제, 삭제 및 Vue 앱 권한 설정
- name: Set Vue App Permissions on Server
uses: appleboy/ssh-action@master # SSH를 통해 서버에 접속하여 스크립트를 실행합니다.
with:
host: ${{ secrets.STAGING_SSH_HOST }}
username: ${{ secrets.STAGING_SSH_USER }}
key: ${{ secrets.STAGING_SSH_KEY }}
port: ${{ secrets.STAGING_SSH_PORT }}
script: | # 서버에서 압축을 해제하고, 파일 권한을 설정하고, 관련된 Docker 컨테이너를 재시작합니다.
tar -xzvf /home/${{ secrets.STAGING_SSH_USER }}/jed-vue/dist.tar.gz -C /home/${{ secrets.STAGING_SSH_USER }}/jed-vue/
rm -f /home/${{ secrets.STAGING_SSH_USER }}/jed-vue/dist.tar.gz
chmod 755 /home/${{ secrets.STAGING_SSH_USER }}/jed-vue/dist
docker restart jed_client
env:
SSH_USER: ${{ secrets.STAGING_SSH_USER }}
참고
https://seosh817.tistory.com/104
[CI/CD] CI/CD란? - 지속적 통합(Continuous Integration)/지속적 배포(Continuous Deployment) 기본개념
매번 개발자가 코드를 수정하고 빌드와 테스트를 하고 배포까지 한다면 상당히 많은 시간이 소요됩니다. 하지만 git에 코드를 올리는 것만으로도 누군가가 빌드와 테스트, 배포까지 해준다면,
seosh817.tistory.com
https://velog.io/@ssol_916/Github-Action%EC%9C%BC%EB%A1%9C-CICD-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0
Github Action으로 CI/CD 구성하기
개발자는 반복적인 작업을 싫어하는 사람들이라고 한다. 뉴비 개발자인 나도 귀찮은 걸 싫어한다. 똑같은 행위를 계속 반복해야 한다면 이것을 시스템으로 자동화 해버리면 되지 않을까?
velog.io
https://github.com/marketplace/actions/ssh-remote-commands
SSH Remote Commands - GitHub Marketplace
Executing remote ssh commands
github.com
'Git' 카테고리의 다른 글
Git 에서 CRLF 개행 문자 차이 해결 (0) | 2023.06.28 |
---|---|
협업 시 충돌 상황 (0) | 2023.05.25 |
Github repository 만들기 및 함께할 팀원 추가 (0) | 2023.05.04 |
Git token 컴퓨터에 저장하기 (0) | 2023.05.04 |