새소식

부스트캠프 AI Tech 4기

[Product Serving Part.4] Github Action을 사용한 CI/CD

  • -

1. CI/CD(Continious Integration/Continuous deploymen)

 

 

  • Local  : 각자의 컴퓨터에서 개발, 각자의 환경 통일을 위해 Docker 등을 사용
  • Dev : Local에서 개발한 기능을 테스트할 수 있는 환경
  • Staging : Production 환경에 배포하기 전에 운영하거나 보안, 성능을 측정하는 환경
  • Production : 실제 서비스를 운영하는 환경

 

 

서버에 코드를 보내는 것과 반복적으로 진행할 Test를 어떻게 실행해야할까?

Dev Branch에 Merge되면 → Local에서 Git Pull & Test 실행 후 괜찮으면 코드 배포 (FTP로 파일 전송)

→ 매번 해주기가 너무 번거롭다!

 

→ CI (Continuous Integration:지속적 통합) !!

새롭게 작성한 코드 변경 사항이 Build, Test 진행 후 Test case에 통과했는지 확인하여 지속적인 코드 품질 관리 가능

 

→ CD (Continuous Deploy:지속적 통합) !!

작성한 코드가 항상 신뢰 가능한 상태가 되면(CI가 통과가 되면) 자동으로 배포될 수 있도록 하는 과정

 

 

CI/CD를 활용할 수 있는 도구

 

 

 

2. Github Action

  • Github Repo 당 Workflow는 최대 20개까지 등록할 수 있다.
  • Workflow에 존재하는 Job(실행)은 최대 6시간 실행 가능, 초과 시 자동으로 중지
  • 동시에 실행할 수 있는 Job 제한 존재

 

Github Action 사용 방식

  1. 코드 작업
  2. 코드 작업 후, Github Action으로 무엇을 할 지 생각
  3. 사용할 workflow 정의
  4. 정의 후 정상 작동하는 지 확인

 

Github Action Core

  • Workflow
    • 최상위 개념
    • 여러 Job으로 구성되고 Event로 Trigger(실행)되는 자동화된 Process
    • Workflow 파일은 YAML로 작성되고, Github Repo의 .github/workflows 폴더에 저장
name: GitHub Actions Demo
on: [push]
jobs:
  Explore-GitHub-Actions:
    runs-on: ubuntu-latest
    steps:
      - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
      - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
      - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
      - name: Check out repository code
        uses: actions/checkout@v2
      - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
      - run: echo "🖥️ The workflow is now ready to test your code on the runner."
      - name: List files in the repository
        run: |
          ls ${{ github.workspace }}
      - run: echo "🍏 This job's status is ${{ job.status }}."

 

 

  • Event
    • Workflow를 Trigger하는 특정 활동, 규칙
    • 특정 Branch로 Push하는 경우
    • 특정 Branch로 Pull Request 하는 경우
    • 특정 시간대에 반복(Cron)

 

  • Jobs
    • Runner에서 실행되는 Steps의 조합
    • 여러 Job이 있는 경우 병렬로 실행하며, 순차적으로 실행할 수도 있음
      • 다른 Job에 의존 관계를 가질 수 있음 (A Job Success 후 B Job 실행)

 

 

  • Step
    • Job에서 실행되는 개별적인 작업
    • Action을 실행하거나 쉘 커맨드 실행
    • 하나의 Job에서는 데이터 공유가 가능

 

 

  • Actions
    • Workflow의 제일 작은 단위
    • Job을 생성하기 위해 여러 Step을 묶은 개념
    • 재사용이 가능한 Component
    • 개인적으로 Action을 만들 수도 있고, Marketplace의 Action을 사용할 수도 있음

 

  • Runner
    • Github Action도 일종의 서버에서 실행되는 개념
    • Workflow가 실행될 서버
    • Github-hosted Runner: Github Action의 서버를 사용하는 방법
      • 성능: vCPU 2, Memory 7GB, Storage 14GB
    • Self-hosted Runner : 직접 서버를 호스팅해서 사용하는 방법

 

 

Github Action Hello World

repo를 하나 파고 아무거나 출력되는 간단한 print 코드가 있는 .py 파일을 생성한 뒤 Actions를 클릭

 

 

Python application 검색 후 Configure 클릭

 

 

클릭하면 자동으로 python-app.yml 파일이 자동으로 생성된다.

 

 

우리는 Test with pytest를 하는게 아니라 아까 만든 파이썬 코드를 실행할 것이다.

name에 무엇을 할지 설명하고

run에 python hello-world.py 를 할 것이라고 변경해준다.

 

 

커밋하고 해당 파일을 들어가보면 노란색 동그라미가 생김을 확인할 수 있다.

노랑색 동그라미는 github action이 실행되고 있다는 것을 뜻한다.

 

 

노란색 동그라미를 클릭하면 현재 check중인지 check가 다 되었는지 알 수 있다.

 

 

Details를 눌러보면 로그를 확인할 수 있는데 아래 그림처럼 초록색이면 Success를 의미

 

 

YAML 파일 분석

on : Event

언제 Workflow가 실행될 것인지

 

  • main 브랜치로 push 될 때 실행
  • main 브랜치에 pull_request 될 때 실행

 

jobs : jobs 정의, build는 job의 이름이다.

 

 

runs-on : ubuntu 환경에서 실행

 

 

uses : 사용할 Github Action

name : step의 이름

 

 

uses가 없는 경우 : run에 작성된 쉘 커맨드 실행

 

 

 

3. 배포하고 CI/CD까지 설정하기

진행 순서

1.  Compute Engine 실행

2. SSH 키 생성 및 Github Secrets 설정

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

4. Gihub Action을 통한 배포 자동화

 

 

3.1 Compute Engine에서 Streamlit 실행

  • 인스턴스 생성
    • 인스턴스 이름 작성
    • Region 설정 : 서울
    • 머신 유형 설정 : 메모리 8GB 이상인 유형으로 설정
    • 부팅 디스크 설정

 

 

  • 인스턴스 생성 완료

 

  • SSH 클릭 후 브라우저 창 열기로 터미널 진입

 

  • SSH Key 생성
cd ~/.ssh/
ssh-keygen -t rsa -b 4096 -C "이메일"
그 뒤로 그냥 Enter

 

 

  • cat 명령어로 id_rsa.pub 파일을 authorized_keys에 등록한다.
    기본적으로 authorized_keys에 퍼블릭 키가 등록되면 외부에서 접근이 가능하다.
cat id_rsa.pub >> authorized_keys

 

  • 단 GCP는 주기적으로 authorized_keys 파일을 삭제하므로 외부에서 키파일을 등록하는 과정이 필요하다.
    따라서 cat 명령어로 id_rsa.pub을 출력한 후 복사해서 개인적으로 저장해둔다.
cat id_rsa.pub

 

  • GCP 콘솔로 이동한 후 메타데이터 클릭

 

  • SSH 키로 이동 후 수정 클릭

 

  • 아까 개인저장해둔 퍼블릭 키를 추가 후 저장

 

 

 

  • Setting - Secrets의 Action으로 이동한 후 New Repository secret 클릭

 

 

  • 그러면 왼쪽 아래같은 화면이 나타나는데 총 3개의 Secret을 등록해야함
  • 첫번째로는 Host를 추가해야 함
    • 인스턴스 외부 IP를 복붙해서 붙여넣기

 

  • 두번째로는 USERNAME 추가
    • 터미널의 저 값을 적어주면 된다.

 

 

  • Private Key는 vi id_rsa로 확인한 후 전체 복사

 

 

  • 3개의 Secret이 등록된다.
  • 한 번 저장하면 값을 확인할 수는 없고 update만 가능하다.

 

  • Github Action에서 Secret을 활용할 수 있다.
    • ${{ secrets.HOST }} : secrets에 저장된 HOST의 Value

 

 

  • Github Action에서 추가 인증 없이 사용하도록 설정하기 위해 아래 코드 터미널에서 실행
nextlevelpotato13@boostcamp:~/.ssh$ cd
nextlevelpotato13@boostcamp:~$ git config --global credential.helper store

 

 

  • Fork한 Repo Clone

  • 만약 이 부분에서 인증 오류가 난다면 Github의 Access Token 발급이 필요하다.
    • Github의 우측 상단 계정의 Settings 클릭

 

 

  • 좌측 하단의 Developer Settings 클릭

 

  • 토큰 생성 클릭

 

  • Note, 기한, 권한 scope 설정

 

 

  • 해당 값은 지금 창을 나가면 다시는 확인할 수 없으므로 개인저장해두고 절대 유출되어서는 안됨

 

  • 그리고 아까 실패했던 git clone에서 password에 해당 토큰 값을 붙여넣으면 된다.

 

 

  • 다시 돌아와서 이제 필요한 프로그램을 설치해야 한다.
sudo apt-get update
sudo apt-get install python3.8-venv -y

 

  • 가상환경 venv 만들고 실행
python3 -m venv venv
source venv/bin/activate

 

  • 아까 클론한 레포의 CI/CD 폴더로 이동하고 requirments.txt 설치
cd Boostcamp-AI-Tech-Product-Serving/part2/04-cicd/
pip install -r requirements.txt

 

 

  • 설치가 완료되면 아래 코드로 Streamlit을 실행한다.
nohup streamlit run app.py --server.runOnSave true &

runOnSave : 파일이 변경될 경우 자동으로 다시 실행

nohup으로 Background 실행한다.

 

  • nohup.out을 출력하면 Externel URL을 확인할 수 있다.
cat nohup.out

 

  • 그러나 해당 URL로 접속하면 사이트에 접근이 할 수 없다.
    → 방화벽 이슈
    → 클라우드 서비스엔 아무나 접근할 수 없도록 설정되어 있기 때문에 방화벽 설정을 수정해야 접근할 수 있다.

 

 

  • GCP 웹사이트의 인스턴스 목록 하단에서 방화벽 규칙 설정을 클릭한다.

 

 

  • 방화벽 규칙 만들기

 

 

  • 이름 설정
  • 지정된 대상 태그
  • 태그 이름은 그냥 이름이랑 똑같이 설정함

 

  • 소스 IPv4 범위 : 0.0.0.0/0
    • 누구나 접근 가능
  • Streamlit을 실행할 것이므로 Streamlit Port를 지정
    • 8501

 

  • 그럼 생성된 방화벽을 확인할 수 있다.

 

 

  • Compute Engine 페이지로 간 후, 인스턴스 이름 클릭

 

  • 수정 클릭 후, 네트워크 태그에 아까 생성한 streamlit 추가한 후 저장

 

 

  • 다시 그 URL에 접근해보면 접속이 가능하다!

 

 

이제  Github Action을 사용해 자동화 배포를 해보자

  • Fork한 Repo로 이동해서 Actions를 클릭하고 I understand를 클릭

 

  • Boostcaml-AI-Tech-Product-Serving/.github/workflow/deploy_ssh.yml 으로 이동
  • ssh-action을 사용해 볼 것이다.
    • SSH로 붙은 후, 스크립트를 실행

 

 

  • push 하단의 paths의 의미
    • main branch로 push/merge가 될 경우 
    • 이 경로에 있는 파일이 변경된 경우에 실행

 

  • ignore를 하면 해당 경로에 수정된건 신경쓰지 않겠다는 것

 

 

  • deploy_ssh.sh 쉘 스크립트 실행
    • cicd 폴더로 이동
    • deploy_ssh.sh 쉘 스크립트를 실행

 

  • deploy_ssh.sh 쉘 스크립트 실행
    • git pull 받은 후
    • 가상환경 만든 것 activate
    • 라이브러리 설치
    • 아까 Streamlit을 runOnSave true로 설정해서 실행했기 때문에 파일이 바뀌면 rerun됨

 

 

+ 임시로 IP 할당했을 경우, 인스턴스를 중지했다가 다시 실행할 경우 IP가 변경됨
→ 고정 IP로 설정하면 인스턴스 중지 후 다시 실행해도 그대로 유지 가능

 

  • VPC 네트워크의 IP주소에서 외부 고정 주소 예약

 

  • 이름/설명/리전/연결대상 설정

 

  • 네트워크 인터페이스에서 외부IP를 쓰고 있음을 확인할 수 있다.

 

 

  • 인스턴스를 삭제하면 수동으로 고정주소 해제를 해줘야 한다.

728x90
Contents