본문 바로가기

부스트캠프 AI Tech 3기/프로젝트 : P-stage

[Day90] Product Serving 2-5 CI/CD

CI/CD

개발환경

Local dev staging production
각자의 컴퓨터 local에서 개발한 기능 테스트 production 환경에 배포하기 전에 성능, 보안 측정을 위해서 실제 서비스를 운영하는 환경
환경을 통일하기 위해 docker 사용 =Test 서버 =staging 서버 = 운영서버
  • 실제 운영중인 서비스에는 장애가 발생하지 않도록 함
  • dev=staging=production환경인 경우
    → 소스코드를 저장하면 바로 반영됨
  • feature branch → dev branch → staging branch → main branch로 점점 넓혀나감
  • 서버를 코드를 보내기
    dev에서 test하고 괜찮으면 FTP로 파일을 보내고 확인 등 번거롭다

CI : Continuous Integration : 지속적 통합

  • 빌드, 테스트 자동화
  • 새롭게 작성한 코드를 build, test를 하며 지속적으로 코드 품질 관리
  • 어쩌다 한 번씩 하는게 아니라 각자 개발자가 변경된 내용이 있을 때마다 CI를 진행

CD : Continuous Deploy/Delivery : 지속적 배포

  • 배포 자동화
  • CI가 통과되면 자동으로 배포될 수 있도록
  • CI → CD 순서
  • dev branch에, staging bran, main branch 코드가 merge 될 때 마다 자동으로 서버에 배포

도구

  • jenkins : 제일 많이 쓰임
  • AWS codedeploy, circleci, travisci, GCP could build, Github action

Github Action

 소프트웨어 worflow 자동화를 도와주는 도구

Worflow 예시

1) Test Code

  • CI에 포함
  • 함수의 return값 확인, 변수의 type확인
  • Unit Test, End to End Test

2) 배포

  • production, staging, dev 서버에 코드 배포
  • FTP나 Docker image로 push 할 수도 있음

3) 파이썬, 쉘 script 실행

  • 예시) 매일 아침 몇 시에 데이터를 모으기 위한 파일을 실행
  • crontab의 대용
  • 예시) merge 될 때마다 python 실행

제약조건

  • 한 repository 당 20개
  • workflow의 job은 최대 6시간
  • 동시에 실행할 수 있는 job 제한
  • github에서 사용하는 서버를 사용하고 있는 것임

Core

  • Workflow
    • 최상위 개념
    • 여러 job으로 구성
    • 특정 event로 trigger됨
    • yaml file로 저장
  • Event
    • workflow를 실행할 수 있는 활동이나 규칙
    • ex) 특정 branch로 push하는 경우
  • Jobs
    • 작업
    • 병렬, 순차적으로 모두 실행할 수 있다
    • runner에서 실행되는 step의 조합
  • Step
    • job 내에서 실행되는 개별 작업
    • 실질적인 작업
    • 하나의 job에서는 데이터를 공유할 수 있다
  • Actions
    • worflow의 제일 작은 단위
    • step을 여러개 묶은 개념
    • 재사용이 가능한 component
    • 서버에서 실행된다
  • Runner
    • workflow가 실행되는 서버
    • Github-hosted runner와 self-hosted runner가 있다

실행해보자

레포지토리를 public으로 만들어줍니다.

파일을 하나 push 해줍니다.

메뉴에서 actions를 찾아 클릭합니다.

 

파이썬 파일을 만들었더니 관련 worflow를 추천해주네요

Python application을 찾아줍니다.

그럼 자동으로 생성되고, 이 템플릿을 기반으로 수정하면 된다.

 

아까 만든 print.py를 실행시키기 위해 test부분 대신 위의 코드를 넣어준다.

on:
  push: # main 브랜치로 push 될 때 이 파일을 실행
    branches: [ main ]
  pull_request:  # main 브랜치로 pull request가 올 때 이 파일을 실행
    branches: [ main ]
jobs: # build라는 이름을 가진 jobs
  build:
runs-on: ubuntu-latest # 어디서 실행하냐. os 환경

steps:
- uses: actions/checkout@v3 # 사용할 github action # 없으면 bash shell command 사용
- name: Set up Python 3.10
  uses: actions/setup-python@v3
  with:
    python-version: "3.10"

다음 push한다.

위쪽에 노란색 불이 들어와있는데, github action이 실행되고 있다는 뜻이다. 클릭해보면

설명이 뜨고, Details를 눌러준다

중간에 아까 수정한 run hello가 있는 것을 볼 수 있다. 오른쪽 위의 버튼 re-run all jobs를 누르면 재실행할 수 있다.

하나하나를 클릭하면 로그를 확인할 수 있다.

 

Streamlit 배포하기

GCP에서 VM 인스턴스를 하나 30GB이상으로, ubuntu 20.04로 만들고

ssh-브라우저 열기를 해서 CLI를 띄워준다.

SSH Key가 있어야 서버에 접속할 수 있어서 아래 명령어를 통해 key를 생성한다

ssh-keygen -t rsa -b 4096 -C "이메일"

묻는것에 다 엔터를 치면 끝난다

~/의 위치에 있다면 cd .ssh를 해서 .ssh폴더로 옮겨간 후에

cat id_rsa.pub >> authorized_keys

 

cat id_rsa.pub >> authorized_keys

pub키를 authorized_keys 폴더로 복사한다. 하지만 주기적으로 이 파일을 GCP에서 삭제하기 때문에 외부에서 키파일을 등록해야하기 때문에

cat id_rsa.pub

를 쳐서 나오는 ssh-rsa~이메일 까지 복사해둔다

GCP로 가서 메타데이터 탭으로 간다.

SSH키를 탭으로 가서

키 추가를 누르고 저 칸에 아까 복사한 것을 붙혀넣고 저장을 클릭한다.

복사한 public키가 정상적이면 내 아이디가 사용자 이름에 잘 나오게 된다.

 

만들어 두었던 github 레포에서 settings-secrets-actions-new repository secret을 눌러 secret을 추가한다.

secret은 변수같이 사용할 수 있고 외부에 노출되면 안되는 것을 저장해둘 수 있는 것이다.

인스턴스의 외부 IP를 복사해서

HOST란 이름으로 IP를 저장한다.

 

ssh 브라우저에서 @앞쪽에 있는 것이 user name인데 그것도 USERNAME이라는 name으로 secret에 추가해준다.

 

public key는 끝났고, private key를 가져와야 한다.

 

vi id_rsa

로 private key를 vim으로 열어준다. 너무 길어서 cat으로 안보이기 때문이다.

 

위의 내용을 복사해서 SSH_KEY라는 이름으로 new secret 에 추가한 다음

:wq로 vim 편집기를 나가준다.

 

등록된 secret들은 코드에서 secrets.HOST와 같은 방식으로 접근해서 사용할 수 있다.

 

다음 사용하던 레포에 가서 https를 복사한다.

git config --global credential.helper store
git clone "복사해 온 https 주소"

github에서 추가 인증없이 사용하기 위해서 첫번째 명령어를 입력한다.

 

오류나면 personal access token을 만들어서 인증해주면 된다.

profile클릭해서 setting - developer settings - personal access tokens - generate new token

기간이 지나도 만료되지 않게 하고 레포에 대한 권한을 준다. 그러고 generate token을 눌러 만든다. 여기에서 나오는

이 값은 이 페이지를 나오면 다시 볼 수 없기 때문에 서버가 해킹당하지 않게 아주 잘 모셔둬야 한다.

 

다시 git clone할 때 암호에 저 위의 값을 넣어주면 잘 된다.

 

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

그 후에 필요한 기본적인 것들을 설치한다.

 

streamlit 서버에서 실행

nohup streamlit run app.py --server.runOnSave true & #를 하면 process id가 나온다
# file이 변경되면 자동으로 다시 실행해주는 옵션을 추가한다.
nohup: ignoring input and appending output to 'nohup.out' #가 알아서 출력되는데
# nohup.out에 로그가 저장된다는 뜻이다.
cat nohup.out # streamlit run app.py가 실행된다.

nohup은 background에서 실행해서 쉘을 꺼도 실행이 유지된다.

 

방화벽 때문에 보여지는 링크에 들어가도 연결할 수없다고 뜬다.

GCP로 돌아가서 vm인스턴스-방화벽 규칙 설정에 들어간다.

방화벽 규칙 만들기

대상 태그에 추가된 태그가 compute engine에 쓰이면 해당 방화벽 규칙을 적용한다.

0.0.0.0/0 은 누구나 접속 가능하게 하겠다는 뜻이다. 내 컴퓨터에서만 접속하고 싶다면 내 IP만 적으면 된다.

 

이제 방화벽을 compute engine에 적용해야 한다. vm인스턴스 메뉴에서 해당 인스턴스 이름을 클릭

수정을 클릭한다.

네트워크 태그에 streamlit을 추가한다.

그러고 조금 기다리면 방화벽 에러가 사라지는 것을 볼 수 있다.

 

Github action 적용

 github접속 후 원하는 레포로 가서

actions탭 클릭- enable해준다. 필요한 yaml을 입력해주고 실행하면 된다!