[Product Serving] Github Action을 활용한 CI/CD

hyunsooo·2023년 1월 10일
0

CI/CD

현업 개발 프로세스

개발환경

Local

  • 각자의 컴퓨터에서 개발
  • 각자의 환경을 통일시키기 위해 Docker, pyenv, virtualenv 등을 사용

Dev

  • Local에서 개발한 기능을 테스트할 수 있는 환경
  • Test 서버

Staging

  • Production 환경에 배포하기 전 운영하거나 보안, 성능을 측정하는 환경

Production

  • 실제 서비스를 운영하는 환경

개발 환경을 나누는 이유?
Dev, Staging, Production이 같게 되면 소스 코드를 저장하는 순간 바로 반영이 된다. 개발할때 생길 수 있는 여러 치명적인 문제를 최소화 하기 위한 방법이다.

현업 Git Flow

main과 staging, dev 브랜치가 존재하며 각 브랜치는 각각 알맞은 서버와 매핑되어 있는 환경이다. 즉 dev에 존재하는 코드는 dev서버에 존재하고 테스트를 해야 한다.

CI/CD 개념

반복적인 테스트를 위와 같이 매번 하는것은 굉장히 번거로운 일이다.
이런 문제점을 보완하고 나온 개념이 Continuous Integration(CI), 지속적 통합이다. CI는 새롭게 작성한 코드 변경을 자동으로 Build하고 Test 진행 후 Test Case에 통과했는지 확인하게 된다.
Continuous Deploy/Delivery(CD), 지속적 배포는 작성한 코드가 항상 신뢰 가능한 상태가 되면(CI 통과) 자동으로 배포될 수 있도록 하는 과정이다. 즉 CI진행 후 CD를 진행하는 프로세스이며 dev/staging/main 브랜치에 Merge가 될 경우 자동으로 알맞은 서버로 배포하게 된다.

CI/CD를 활용할 수 있는 도구로는 Jenkins, circleci, Travis CI, AWS CodeDeploy, GCP Cloud Build, Github Action 등이 존재한다.

Github Action

Github에서 출시한 기능으로, 소프트웨어 Workflow 자동화를 도와주는 도구

Github Action 소개

Workflow 예시

1. Test code

  • 특정 함수의 return 값을 확인하는 Test code
  • 특정 변수의 타입 확인
  • Unit Test, End to End Test

2. 배포

  • Prod, Staging, Dev 서버에 코드 배포
  • 기존은 FTP로 파일 전송할 수도 있고, Docker Image를 Push하는 방법 사용
  • 현재는 workflow로 배포를 자동화할 수 있다.

3. 파이썬, 쉘 스크립트 실행

  • Github Repo에 저장된 스크립트를 일정 주기를 가지고 실행
  • crontab의 대용
  • 데이터 수집을 주기적으로 해야할 경우 활용할 수 있다.
  • 참고

4. Gtihub Tag, Release 자동으로 설정

  • Main 브랜치에서 Merge될 경우 특정 작업 실행
  • 기존 버전에서 버전 up하기
  • 새로운 브랜치 생성시 특정 작업 실행

5. etc

  • 그 외 다양한 Workflow를 만들 수 있다.

  • Action Marketplace에 존재하는 action을 사용할 수 있다.

  • Awesome Github Action

    github Action pricing
    Public Repo는 무료지만 Private Repo는 유료로 이용해야 한다.

    github Action 제약조건
    하나의 Repo당 workflow는 최대 20개까지 등록할 수 있으며 workflow에 존재하는 Job(실행)은 최대 6시간 실행할 수 있다. 그 시간이 초과되면 자동으로 중지되며 동시에 실행할 수 있는 Job의 제한도 존재한다.

    Github Action 사용하는 방식

  • 코드 작업

  • 코드 작업 후, Github Action으로 무엇을 할 것인가 생각

  • 사용할 Workflow정의 (기존의 Workflow중 사용할게 없으면 쉘스크립트 자동화도 고려해볼 수 있다.)

  • Workflow 정의 후 정상 작동하는지 확인

    Github Action Core

    핵심개념 : Workflow, Event, Job, Step, Action, Runner

1. Workflow

Workflow는 최상위 개념으로 무엇을 자동화할지 이름으로 구성하고 그 아래에 여러개의 Job으로 구성된다. 또한 Event로 Trigger(실행)되는 방식을 거친다.
Workflow 파일은 YAML으로 작성되고, Github Repository의 .github/workflows폴더에 저장한다.

2. Event

위의 사진을 보면 on에 해당하는 부분이 Event이며 push가 될때마다 실행하겠다는 의미이다. 이 부분에 특정 브랜치에 push, Pull Request, merge나 특정 시간대에 반복(Cron)등을 지정할 수 있다.

3. Jobs

Runner라는 서버에서 실행되는 Steps의 조합이다.
일련의 작업이라고 생각할 수 있으며 여러 Job으로 구성되어 있는 경우 병렬, 순차적 실행을 설정할 수 있으며 다른 Job에 의존 관계를 가질 수 있다.

4. Steps

Step은 Job에서 실행되는 개별 작업으로 Action을 실행하거나 쉘 커맨드는 실행하는 작업이 실행된다. 하나의 Job에서는 데이터 공유가 가능하다.

5. Actions

Workflow의 제일 작은 단위로 Job을 생성하기 위해 여러 Step을 묶는 개념이다. 재사용이 가능한 Component로 개인적으로 Action을 만들 수 있고 Marketplace의 Action을 사용할 수 있다. Action을 YAML파일에서 uses 부분에서 확인할 수 있다.

6. Runner

github Action도 일종의 서버에서 실행되는 개념으로 Workflow가 실행될 서버이다. github-hosted Runner는 vCPU 2, Memory 7GB, Storage 14GB의 성능을 가지고 있으며 직접 서버를 호스팅해서 사용하는 self-hosted Runner 방법을 사용할 수 있다.

Github Action 실습

  • 새로운 repository를 생성 후 hello-wolrd.py 파일을 생성하고 print문을 작성 후 저장한다.

  • 상단의 Actions탭에서 Python application의 configure를 클릭하면 YAML파일이 생성된다.

  • 해당 YAML파일의 Jobs에서 하단의 Test with pytest 부분을 수정한다.

  • YAML옆에 노란색 동그라미는 Actions가 실행하고 있다는 의미이고 Details를 클릭하면 각 스텝마다 로그정보를 확인할 수 있으며 초록색으로 바뀌면 Success를 의미한다.

  • on에 해당하는 부분이 Event이며 main branch에 push, pull_request가 왔을때 실행하겠다는 의미이다.

  • jobs는 jobs를 정의할 수 있으며 build는 job의 이름이다.

  • runs-on은 실행 환경에 대한 정보이다.

  • uses는 사용할 github Action을 명시하고 name은 step의 이름을 명시한다. uses가 없는 경우 run으로 쉘 커맨드를 실행하는 의미이다.

Mask Classification Streamlit 배포하기

진행 순서

  • Compute Engine 실행

  • SSH 키 생성 및 Github Secrets 설정

  • 터미널에서 최초로 서비스 실행

  • Github Action을 통한 배포 자동화

Compute Engine에서 Streamlit 실행하기

지난 시간에 배웠던 GCP에서 Compute Engine의 VM 인스턴스를 생성한다.
실습환경은 Region은 서울 머신 유형은 e2-standard-2(vCPU 2개, 8GB 메모리)로 진행한다. 실습 후 인스턴스를 바로 삭제하기 때문에 무료 크레딧으로 사용할 수 있으며 비용이슈는 발생하지 않는다.
또한 부팅 디스크 부분에서 운영체제를 설정할 수 있으며 실습 환경에서는 Ubuntu 20.04 LTS, 30GB로 설정한다.

인스턴스가 생성이 완료되면 SSH를 클릭하여 브라우저 창에서 열기를 클릭한다.
CLI환경이 로드되면 SSH Key를 생성해야 한다.

  • cd ~/.ssh/

  • ssh-keygen -t rsa -b 4096 -C "my email"

  • passphrase는 엔터를 쳐도 기본설정으로 생성한다.

  • id_res.pub이 생성되었다면 cat id_rsa.pub >> authorized_keys로 파일을 생성한다.

  • authorized_keys에 퍼블릭 키가 등록되면 외부에서 접근이 가능하지만 GCP는 주기적으로 authorized_keys 파일을 삭제해서 외부에서 키파일 등록하는 과정이 필요하다.

  • 따라서 cat id_rsa.pub을 사용해 내용을 복사한다.

  • GCP Console로 이동한 후 좌측 메뉴에서 메타데이터를 클릭 후 SSH 키를 추가할 수 있다.

  • SSH키 값을 정상적으로 등록하면 사용자이름이 정상적으로 나타나게 되며 비정상적인 이름이 나타난다면 키를 복사하는 과정을 다시 진행해야 한다.

위의 과정을 정상적으로 완료했다면 실습을 위해 zzsza Repo의 내용을 Fork해온다.

  • Fork를 해왔다면 해당 Repository에서 Settings - Secrets - Actions로 이동하여 New repository secret을 클릭한다. secret이란 일종의 변수같이 사용할 수 있는것으로 암호처럼 외부에 노출되면 안되는 값을 이 기능으로 생성하게 된다.

  • 해당 secret에는 HOST라는 이름으로 VM인스턴스의 외부 아이피주소를 복사하여 저장한다.

  • 다음 secret을 생성후 USERNAME으로 VM인스턴스의 username을 추가한다.

  • 마지막으로 Private SSH를 등록해야하는데 VM인스턴스 환경에서 id_rsa파일을 복사하여 SSH_KEY라는 이름으로 등록해준다. private key값을 길기 때문에 vi를 이용해서 복사할 수 있다.

이렇게 등록된 secrets들은 Github Action에서 Secret을 활용할 수 있다.
${{secrets.HOST}}와 같이 secrets에 저장된 HOST의 값을 가져올 수 있다.

VM인스턴스 서버로 접속한 후 git config --global credential.helper store를 사용해 Github Action에서 추가 인증없이 사용하고 Fork한 저장소를 clone해준다.

clone이 완료되면 필요한 프로그램을 설치해준다.

  • sudo apt-get update
  • sudo apt-get install python3.8-venv -y

설치가 완료되면 clone한 repository의 part2 --> 04-cicd로 이동한 후 아래의 명령어를 실행해준다.

  • python3 -m venv venv

  • source venv/bin/activate

  • pip install -r requirements.txt 설치 중 error는 기다리면 진행이 된다.

  • 설치가 완료되면 nohup streamlit run app.py --server.runOnSave true &를 실행한다.

  • runOnSave : 파일이 변경될 경우 자동으로 다시 실행하는 기능이다.

  • cat nohup.out로 외부 URL정보를 확인할 수 있다.

  • 해당 URL로 접속하면 병화벽 이슈로 인해 접속이 불가능 한데 GCP console에서 방화벽 규칙 설정을 클릭한다.

  • 해당 메뉴에서 방화벽 규칙 만들기를 클릭하여 이름과 대상을 지정된 대상 태그로 한 후 태그 이름을 설정한다. 이 옵션은 해당 태그가 compute engine에 쓰이면 이 규칙을 적용하겠다는 의미이다.

  • 소스 IPv4 범위(0.0.0.0/0, 누구나 접근)와 지정된 프로토콜 및 포트(TCP 8501, streamlit port)를 설정한다.

  • 생성된 방화벽을 확인하면 아래와 같다.

  • 생성된 방화벽을 Compute Engine에 적용하기 위에 Compute Engine페이지에 인스턴스이름을 클릭한다. 상단의 수정버튼을 누른 후 네트워크 태깅 섹션에서 태그 이름을 추가한다. 여러개를 추가할 경우 쉼표로 구분한다.

  • 태그가 완료되었다면 다시 외부 url로 접속하면 접속이 되는것을 확인할 수 있다.

여기까지가 streamlit을 Cloud환경에 띄운것이라 말할 수 있다. 다만 CI/CD와 같이 배포 자동화를 다루진 않았으며 다음 내용에서 다룰 예정이다.

Github Action을 사용한 배포 자동화

배포 자동화 실습을 위해 Fork한 Repository로 이동 후 Actions를 클릭 후 understand를 클릭한다.

해당 Repository에는 이미 Actions(YAML파일)이 존재하고 Boostcamp-AI-Tech-Product-Serving/.github/workflow/deploy_ssh.yml로 이동해서 파일을 확인한다.

위에서 부터 살펴보면서 어떻게 구성되어 있는지 살펴본다.

  1. 해당 Action의 이름은 CICD-SSH로 이루어져 있고 main 브랜치에 part2/04-cicd/ 경로에 push 이벤트가 발생했을때 Jobs가 실행된다.

  2. Job의 이름은 build이며 Runner서버의 환경은 ubuntu이다.

  3. Steps들 중 첫번째 step의 이름은 executing remot ssh이며 appleboy/ssh-action@master를 action을 사용하며 이때 사용할 value들은 with에 포함된 secret에 저장한 HOST, USERNAME, SSH_KEY 등을 활용하며 SSH로 서버에 접근한 후 script를 실행한다.

  4. 해당 script의 deploy_ssh.sh 파일은 git pull과 라이브러리 설치로 이루어져 있다.

위의 Actions가 잘 동작하는지 확인하기 위해 새로운 브랜치를 생성후 app.py의 Title을 수정하고 Push 후 Pull Request로 main 브랜치에 merge하는 동작을 수행한다.

위의 동작을 수행하면 Actions이 수행중인 노란색 불이 들어오는데 Details을 확인해서 정상적으로 완료되면 문제가 없지만 ssh: handshake failed ...와 같은 오류가 발생한다면 private key의 정보를 복사 붙여넣는 과정이나 서버에서 생성한 authorized_keys파일이 자동 삭제가 되었을 수 있기 때문에 확인을 해봐야 한다.

현재 IP는 인스턴스를 다시 실행할 경우 IP가 변경된다. 따라서 고정 IP로 변경해주면 인스턴스 중지 후 다시 실행해도 그대로 유지할 수 있다.
VPC 네트워크메뉴에서 IP주소탭으로 들어가면 인스턴스들에 대한 네트워크 정보가 나오며 우측 끝에 예약이라는 메뉴를 눌러 고정 IP주소를 생성할 수 있으며 고정IP를 사용할 수 있다.
만약 인스턴스를 삭제하더라도 IP주소는 자동으로 삭제되지 않기 때문에 꼭 고정 주소 해제를 해줘야 한다.

profile
지식 공유

0개의 댓글