[CI/CD] 모델과 코드 배포
ML/AI 서비스를 제공하기 위해서 해당 모델과 추론 코드 등을 Production 서버에 배포하게 된다. 그러나 이 때 단순하게 배포하는 게 아닌 운영 안정성과 속도 등 사용자들의 니즈를 충족시키기 위한 여러가지 고려사항 혹은 개념들이 필요하다. 이 포스트에서 CI/CD 에 대해 알아보자.
환경 분리와 배포
- 소프트웨어 개발에서 의미하는 환경의 정의와 배포에 대해 알아보자. 먼저 개발 환경은 아래와 같이 구분할 수 있다.
- 로컬 환경 : 처음 개발할 때는 각자의 로컬 컴퓨터에서 개발하게 된다. 이 때 각자의 환경을 통일시키기 위해 Docker 등을 사용한다. 또한 패키지 의존성 문제를 완화하기 위해서 poetry 등을 사용한다.
- Dev 환경 : 의미 그대로 개발 환경이다. 로컬에서 개발한 기능을 테스트할 수 있는 환경으로, 테스트 서버를 띄우고 거기서 개발하게 된다.
- Staging 서버 : Production 환경에 배포하기 전에 운영하거나 보안, 성능 등을 측정하는 환경이다.
- Production. 서버 : 실제 서비스를 운영하는 환경, 서버다.
- 이와 같이 개발환경을 나누는 이유는 아래와 같다.
- 실제 운영 중인 서비스에 장애가 발생하는 것을 피해야 한다.
- 만약 Dev = Staging = Production 인 경우에 소스 코드를 수정, 저장하면 바로 반영된다.
- 이 때 장애가 나면 바로 운영 서버에서 장애가 나게 된다. 의도하지 않게 자동 저장이 될 수도 있고, 업데이트가 될 수도 있다. 따라서 개발 환경을 꼭 나누게 된다.
- 현업 개발 프로세스에서 환경(dev, staging, prod 등)을 분리하는 이유는 검증되지 않은 변경 사항이 유저에게 전달되어 예상치 못한 오류가 발생하는 것을 방지하기 위해서다.
- 환경을 분리함으로써 각각의 환경에서 개발된 소프트웨어가 사용자에게 배포되기 전에 테스트되고 검증될 수 있다.
- 특히, Production 환경에서 발생할 수 있는 예상치 못한 오류나 문제를 사전에 파악하고 수정함으로써 사용자에게 불편을 줄일 수 있다.
- 따라서 의도하지 않은 변경 사항이 유저에게 전달되어 예상치 못한 오류가 발생하는 것을 방지하기 위해 각각의 환경을 분리하는 것이 일반적이다.
Git Flow
- 현업에서의 github 을 활용한 개발 프로세스다.
- main branch (운영용), staging branch (staging 서버용), dev branch, feature/기능 이름 branch 가 존재한다.
- feature branch 에서 dev branch 로 PR 과 review 를 넣는다. 그러면 dev branch 는 staging branch 로 PR, review 를 보낸다. 또 staging 에서는 main 으로 PR, review 를 보낸다.
- staging 서버는 없을 수도 있다. 또한 feature/기능 이름 branch 도 다를 수 있다. github 에서 branch 를 따는 이름은 다 다들 수 있다.
-
그러나 main 이 production(운영용), staging 이 staging, dev 가 개발 환경을 뜻하는 것은 변하지 않는다.
- 위 그림처럼 각각의 branch 를 서버와 연결시킨다. feature branch 는 보통 로컬에서 개발하게 된다.
CI/CD
- 서버에 코드를 보내는 것과 반복적으로 진행할 Test 를 어떻게 실행해야 할까?
- feature branch 에서 Dev branch 로 PR, review 를 날리고 Merge 한다. 이를 수동으로 하면 로컬에서
git pull
을 하게 된다. -
그리고 Test 후
FTP
또는scp
로 Dev 서버에 파일을 전송하여 코드를 배포하게 된다. 이는 매우 번거로운 일이다. - 이에 따라 CI 혹은 CD 구축의 필요성이 증가했다.
- Continuous Integration(CI), 지속적 통합
- 새롭게 작성한 코드의 변경 사항이 Build 또는 Test 할 때 test case 에서 통과되는지를 확인한다.
- CI 는 지속적으로 코드의 품질 관리를 위해 사용하는 과정이다.
- 일반적으로 10 명의 개발자가 코드를 수정했다면 모두 CI 프로세스를 진행한다.
- Continuous Deploy/Delivery(CD), 지속적 배포
- 작성한 코드가 항상 신뢰 가능한 상태가 되면 자동으로 배포될 수 있도록 하는 과정이다. 따라서 CI 이후 CD 를 진행한다.
- dev / staging / main branch 에 Merge 가 될 경우, 해당 branch 가 바라보고 있는 서버에 코드를 자동으로 전달한다. 즉 배포하는 것이다.
- 각 branch 에서 Merge 됐을 때,
git pull
을 하고 이를FTP
,scp
명령어로 서버에 보내는 과정을 수동으로 하지 않고, 자동으로 하는 과정이다.
- 정리하면, CI 는 빌드/테스트 자동화에 해당하고, CD 는 배포 자동화에 해당한다.
- CI 에서는 데이터 검증 과정도 가능하다. 데이터가 어떤 상태인지 확인하도록 만들 수 있다.
- CI 에서 테스트는 Python 의
pytest
를 이용한다. 테스트 코드를 작성하여 github 에서 merge 가 되는 순간 테스트가 돌아가도록 만들고, 모두가 pass 되면 merge 할 수 있도록 설정하는 것이다. - local 에서 개발하고 main 으로 merge 시 production 서버에 코드를 배포하는 것도 가능하다.
- 개인 프로젝트에서는 서버를 두지 않는 경우도 존재한다.
- Dev, Staging, Prod 모두 다 서버로, 모두 비용이다.
- 이 서버들은 모두 다 똑같은 성능이 아니라, Prod 가 실제로 서비스를 받기 때문에 용량이 제일 커야한다.
- Dev 와 Staging 은 유저가 실제로 쓰지 않아 트래픽이 굉장히 작다.
- 따라서 개인 프로젝트에서는 로컬에서 개발하고 Prod 보내는 경우도 많다. 그럼에도 branch 를 나눠서 작업하는 습관을 들이면 더 좋은 협업 능력을 함양할 수 있다.
ML 모델 배포 시 주의할 점
- Docker 이미지
- 대부분 Docker 를 이용하여 배포하게 된다. 이 때 Image 사이즈가 큰 편이기 때문에 관리가 필요하다.
- Multi stage build와 같은 테크닉을 사용해서 최대한 Docker Image 의 사이즈를 줄여야 한다. 이에 대해서는 해당 포스트에서 정리했다.
- 또한 호스트 머신의 디스크 용량도 관리가 필요하다. Docker 를 띄우면 CLI 에 로그가 많이 남는다. 이 로그들은 어딘가에 저장되고 있을 가능성이 크다. 이 로그를 주기적으로 삭제하거나 AWS S3 와 같은 클라우드로 보낼 수 있다.
- 모델 버저닝
- 모델 코드에 대한 확실한 버저닝이 필요하다.
- 어떤 버전의 모델이 현재 배포 중이고, 과거에는 어떤 버전으로 배포되었는지 이런 히스토리가 관리되어야 한다.
- 우리가 만든 모델에 대해 롤백이 필요하다면 어떤 버전으로 재배포해야 하는지 이런 것들도 기록되어야 한다.
- 모델의 버전 별 특징을 쉽게 알아볼 수 있어야 한다.
1.0.1
,1.2.0
이런 버전들이 무엇을 의미하는지 기록이 되어 있어야, 모델 버저닝이 잘 되어서 모델을 운영할 때 이슈에 빠르게 대응할 수 있다.
- 모델 아티팩트
- 모델을 저장할 때는 Docker Image 에 저장하는 것보다 S3 와 같은 Object Storage 에 저장하는 것을 권장한다.
- 일반적으로 딥러닝 모델은 엄청 무거운데, 이를 Image 에 저장하게 되면 그만큼 사이즈가 커져 이슈가 발생할 수 있다.
- 모델을 로드하고 싶으면, 클라우드 스토리지나 ML flow 같은 모델 저장소, 모델 레지스트리에 저장하고 불러오는 것이 좋다. 이렇게 되면 모델을 불러오는 로직만 있으면 된다.
- 이 떄 모델 버전과 아티팩트의 버전이 다른 경우도 있으므로 메타 정보를 확인해야 한다. 이 때 효과적인 도구가 MLflow다.
- MLflow 를 잘 활용하면 기록, 메타데이터 기반으로 모델을 사용할 수 있다.
- 파일 권한 관리(VM 인스턴스, Object Storage 등)
- VM 인스턴스에서
pth
파일을 읽지 못한다면 정상 실행이 불가능하다. - 따라서 VM 인스턴스에서 Object Storage 에 접근할 수 있도록 서비스 계정을 만들고 설정해줘야 한다.
- Object Storage 는 다른 사용자가 버킷을 삭제하면 롤백이 불가능하기 때문에 잘 관리해줘야 한다. 따라서 삭제 권한을 제어하는 것이 필요하다.
- 실제로 삭제 권한은 회사에서 일반 직원에게 잘 주지 않는다. 프로젝트 할 때 이런 것도 생각해야 한다.
- VM 인스턴스에서
Github Action
- Github Action 은 배포하는 과정에서 사용할 대표적인 CI/CD 도구다. 회사, 개인 프로젝트 어디서든 사용할 수 있다.
-
Github 에서 출시한 기능으로, 소프트웨어의 Workflow 자동화를 도와주는 도구다. 아래와 같이 여러 Workflow 를 지원한다.
- Node.js 등 다양한 언어별 Workflow 를 지원한다. 그리고 위와 같이 기본적인 템플릿이 제공되기 때문에, 이를 스스로의 스타일로 수정하면 된다.
- 그리고 Github Action 을 이용해서 아래와 같은 것들이 가능하다.
- Test Code
- 특정 함수의 return 값이 어떻게 나오는지 확인하는 Test Code 를 자동화할 수 있다.
- 특정 변수의 타입이 원하는 타입이 맞는지도 test 할 수 있다.
- Unit Test, End to End Test 도 가능하다.
- 배포
-
Prod, Staging, Dev 서버에 코드를 배포하는 것을 자동화할 수 있다.
- 배포는 Image 혹은 파일을 서버로 보내는 것이라 생각하면 된다.
- 파일의 경우
FTP
또는scp
로 파일 전송을 할 수도 있고, Docker Image 를 Push 하는 방법 등이 있다.
-
- Python, Shell 스크립트 실행
- Github Repo 에 저장된 스크립트를 일정 주기를 가지고 실행할 수도 있다.
- 이에 따라 일정 주기로 체크해야 하는 것들은 github action 으로 수행하기도 한다. batch serving 에서 봤던 linux 의
crontab
의 대용으로 쓰기도 한다. - 그러나 시간이 정상적으로 동작하지 않을 때도 있다. 따라서 batch serving 을 할 때는 github action 이 좋지 않을 수 있다. 그러나 사이드 프로젝트나 개인 프로젝트에서
cron
으로 주기적인 작업을 하고 싶을 때 github action 을 사용하는 것은 좋은 방법이다. -
데이터 수집을 주기적으로 해야할 경우에도 활용 가능하며, Issue 에 기록하는 것도 만들 수 있다.
- 위와 같이 setup-python 과 같은 미리 만들어진 것을 이용해서 Python 의 환경 세팅도 가능하다.
- Github Tag, Release 자동으로 설정
- main branch 에 Merge 될 경우에 특정 작업을 실행하도록 만들 수 있다.
- 예를 들어 새로 Merge 된 경우, 기존 버전에서 버전 Up(1.0.1 → 1.0.2) 하는 것을 자동화 한다.
- 새로운 branch 생성 시 특정 작업을 실행하는 것도 가능하다. 마찬가지로 새로운 branch 를 만들고 remote 에 push 하면 새로운 작업이 실행되는 것도 가능하다.
- 이처럼 개발자라면 github action 은 범용적으로 많이 쓸 수 있는 도구다. 위에서 소개한 것 외에도 다양한 workflow 를 만들 수 있다. 이에 따라 다양한 사용자들이 만든 workflow 템플릿이 많이 공유되어 있다.
-
원하는 기능이 있는 경우 “<기능> github action" 등으로 검색하면 어렵지 않게 찾아볼 수 있다.기능>
github action pricing
-
public repo 는 무료지만, private repo 는 아래의 조건을 따른다.
github action 제약조건
- github repo 당 workflow 는 최대 20 개까지 등록할 수 있다. 또한 많은 작업들을 하나의 repo 에서 다 처리하기는 어렵다.
- workflow 에 존재하는 job(실행)은 최대 6시간 동안 진행할 수 있으며, 초과시 자동으로 중지된다. 따라서 계속 뭔가를 돌리는 작업은 어렵다.
- 또한 동시에 실행할 수 있는 job 에도 제한이 존재한다. 즉 계속 무료는 아니다.
github action 사용 방식
- github action 을 사용할 때는 코드 작업 $\rightarrow$ github action 으로 무엇을 할 것인지 생각 $\rightarrow$ 사용할 workflow 정의 $\rightarrow$ 정상 작동 확인의 방식으로 사용한다.
- workflow 정의할 때는 github action 에 workflow 파일을 올리고 merge 될 때 trigger 조건 등을 설정해서 계속 시도해보는 것.
Github Action Core
- github action 의 핵심개념으로는 workflow, event, job, step, action, runner 이 있다.
-
아래와 같은 YAML 파일을 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 & event." - run: echo "This job is now running on a $ server hosted by Github." - run: echo "The name of your branch is $ and your repository is $." - name: Check out repository code uses: actions/checkout@v2 - run: echo "The $ 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 $ - run: echo "This job's status is $."
- Workflow
- 여러 job 으로 구성되고 event 로 trigger(실행)되는 자동화된 process 다.
- workflow 하나에 job 1, 2, 3 등 여러 job 이 생길 수 있다.
- 즉 github action 에서의 최상위 개념이다. 이러한 workflow 파일은 YAML 파일로 작성되고, github repo 의 .github/workflows 폴더에 저장된다.
- 다른 오픈소스를 봤을 때 위 폴더가 있으면 github action 코드가 있는 것이다.
- Event
- workflow 를 trigger 하는 특정 활동이나 규칙을 뜻한다.
- 특정 branch 로
push
하는 경우 - 특정 branch 로
pull request
하는 경우 - 특정 시간대에 반복(Cron)하는 경우
- 특정 branch 로
- 위 예제에서 Event 는
on [push]
라고 되어 있다. 이는push
될 때 돌아가는 workflow 라는 것이다. 여기에 branch 를 직접 기입할 수도 있다.
- workflow 를 trigger 하는 특정 활동이나 규칙을 뜻한다.
- Jobs
- Runner 에서 실행되는 Steps 의 조합이다.
- 여러 job 이 있는 경우 병렬로 실행하며, 순차적으로도 실행 가능하다.
- 다른 job 에 의존 관계를 가질 수 있다. 예를 들어 A job 이 success 된 후 B job 을 실행하도록 할 수 있다.
- Steps
- job 에서 실행되는 개별 작업이다.
- action 을 실행하거나 쉘 커맨드를 실행한다.
- 하나의 job 안에서는 데이터를 공유할 수 있다.
- job 안에 step 이 있다.
- Actions
- job 을 생성하기 위해 여러 step 을 묶은 개념으로, workflow 의 제일 작은 단위이며 재사용이 가능한 컴포넌트다.
uses: actions/checkout@v2
는 actions 의 checkout v2 를 사용하겠다 라는 것이다.- 개인적으로 action 을 만들수도 있고, marketplace 의 action 을 가져다가 사용할 수도 있다.
uses
다른 만들어진 특정 action 을 가져와서 템플릿처럼 쓰겠다는 것을 의미한다.
- Runner
- github action 도 일종의 서버에서 실행되는 개념이다. Runner 는 workflow 가 실행될 서버를 의미한다.
Github-hosted Runner
는 Github 에서 유지하고 관리하며 요금제에 무료/유료 시간을 사용할 수 있다. 여기서 vCPU2, memory 7GB, Storage 14GB 와 같은 성능을 지정해줄 수 있다. heavy 한 작업은 어렵다.Self-hosted Runner
는 직접 서버를 호스팅해서 사용하는 방법이다.- 로컬 컴퓨터를 이용해서 github action 이 동작할 서버를 호스팅하는 것으로, github action 을 사용하고자 하는 repo 에서 Settings - Actions - Runners 에서 지정해줄 수 있다.
- 이처럼 Github Action 의 서버를 사용할 수도 있고, github action 을 내 컴퓨터에서 하고 싶으면 내 서버를 직접 호스팅해서 사용할 수 있다.
Github Action 예제1
- 먼저 github repo 를 새로 생성한다.
- 이후 github action 을 사용하도록 설정해줘야 한다. 특정한 곳에서는 사용이 되지 않는다.
- Add file - Create new file 로 Python 파일을 하나 만들어준다.
hello-world.py
를 만들어보자. - 해당 github repo 에서 상단의 Action 을 클릭한다.
- 맨 하단에 Continuous Integration 을 클릭한다.
- 검색창에 “python application” 검색 후 “Configure” 을 클릭한다. 그러면 기본적인 파일 형태가 불러와진다.
-
이제 해당 repo
./github/workflows/python-app.yml
과 같이 템플릿으로 아래와 같은 파일이 생성된다.on: push: branches: [ main ] prull_requests: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python 3.10 uses: actions/setup-python@v3 with: python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip pip install flake8 pytest if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Gihub Action Demo run: | python hello-world.py
-
맨 마지막
run
안에python hello-world.py
를 실행하면 된다. 이제 해당 repo 에 커밋 후 push 하게 되면 Actions 에 노란색 동그라미가 나오게 된다. 이는 작업중이라는 의미다. 이를 클릭하면 디테일을 볼 수 있다.해당 블로그도 github action 이 적용되어 있다.
- 동그라미가 초록색으로 바뀌면 Success 를 의미하고, 마찬가지로 클릭하면 로그를 확인할 수 있다.
- 우측에 Re-run all jobs 를 누르면 재실행도 가능하다.
- 정의한 Step 별로 로그를 확인할 수 있다. 오류가 발생하면 특정 부분만 클릭하면 된다.
- 이제 위 YAML 파일을 분석해보자.
on
- Event 와 관련되며, 언제 workflow 가 실행될 것인가를 의미한다.
- 위 예제는 main branch 에 푸시될 때 실행하기 혹은 main branch 에 PR 이 될 때 실행하겠다는 것을 의미한다.
jobs
-
jobs 를 정의한다. 위 예제에서
build
는 해당 job 의 이름이다. 로그를 보면 jobs 에 build 라고 나오는 것을 볼 수 있다. 물론 이름을 바꿀수도 있다.
-
runs-on
- 어떤 환경에서 실행할 것인가를 뜻한다.
Github-hosted Runner
,Self-hosted Runner
모두 가능하다. 이 예제에서는 github action 이 유지관리하는ubuntu
를 사용한다. Self-hosted Runner
를 사용하려면 Runner 를 로컬 서버로 만들어준 후,self-hosted
라고 작성하면 된다.
- 어떤 환경에서 실행할 것인가를 뜻한다.
uses
- 사용할 github action 이다.
- uses 가 없는 경우에는 run 에 작성된 쉘 커맨드를 실행한다.
name
- step 의 이름을 뜻한다.
- github action 은 보통 템플릿으로 다른 사용자들이 만들어둔 것이 있으니 그걸 보면서 다양한 usecase 를 파악하고 적용하는 것을 추천한다. 이를 처음부터 암기해서 바닥부터 쓰는 경우는 거의 없다.
- 템플릿이나 마켓플레이스를 보고
uses
에 기입해주면 된다.
Github Action 예제2
- 다른 예제를 통해 현업의 관점에서 github action 을 이용한 CI/CD 를 이해해보자.
- 모델 Image 를 준비한다. 즉 코드를 배포하기 전에 모델(.pt, .pkl, .onnx 등)도 준비해서 서빙할 환경을 만들어준다. 서빙할 모델 코드, Online Serving 을 위한 API Endpoint 정의 코드, 컨테이너화를 위한 의존성 정의(requirements.txt)가 필요하다.
-
Dockerfile 은 아래와 같이 작성할 수 있다.
FROM python:3.8 WORKDIR /code COPY ./requirements.txt /code/requirements.txt RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt COPY src /code/app CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
- Docker Image Repository 는 수많은 Docker Image 들을 저장하는 저장소다.
- 자체적으로 Image 의 이름과 버전 등을 저장하고 불러올 수 있다.
- Docker 의 공식 저장소는 Dockerhub 다. 또는 AWS ECR 과 같은 클라우드의 저장소를 사용할 수 있다.
-
해당 예제에서는 GCP 의 Google Cloud Artifact Registry 를 사용해보자. GCP 의 이미지 저장소로서, 아티팩트를 저장할 수 있다. 즉 Docker Image, npm 패키지 등을 저장하고 관리할 수 있다.
- 위 그림과 같이 gcloud CLI 설치 후 인증을 설정해주면 gcloud 에서 Docker 설정을 사용할 수 있게 된다.
- Artifact Registry 에 Docker Image Push 과정은 아래와 같다.
- Docker Image Build
- 태그 설정
- Image Push
-
아래 그림과 같이 GCP artifacts 웹에 접속 후, Project id 를 확인한다. 이후 “create repository” 를 클릭한다.
-
이름을 지정한 후 Format 을 Docker 로 정의한다. 나머지는 아래 그림과 같이 설정 후 생성한다.
- 이제 로컬에서 Docker Image 를 Build 한다. 이 때
-t
옵션을 통해model_deploy:test
로 설정한다. - 그리고
docker tag 기존 이미지:태그 새 이미지 이름:태그
커맨드를 이용해서 빌드할 때 썼던 태그를 GCP 의 artifact registry 로 태그한다.-
아래와 같이 커맨드를 실행할 수 있다.
-
위와 같이 실행해주면 새 이미지 이름은 GCP 의 Artifact repository URL 을 가지게 된다.
-
- 이후
docker push Artifact Registry/프로젝트 id/Repository/이미지 이름:버전
커맨드를 이용해서 Image 를 Artifact Registry 에 올린다.-
아래와 같이 실행한다.
- Image 가 Artifact Registry 에 올라가고, 웹 콘솔에서 Image 가 올라간 것을 확인할 수 있다.
-
- 올라간 Docker Image 를 Pull 하고 싶다면
docker pull
하면 된다. - 이제 Github action 을 사용해서 특정 조건에
docker image build, push
를 자동화해보자.- 예를 들어 main branch 에 Merge 되면 docker Image 를 새로 만들고 registry 에 push 하는 작업이다. 즉 로컬에서 위와 같이 registry 에 올리는 게 아니라 github action 을 통해서 하는 방법이다.
- 이를 위해 github repo 의 setting 에서 Secrets and variables → Actions → Reopsitory secrets 에 secret 을 만들어준다.
- 여기에 GCP 서비스 계정을 설정한다. 서비스 계정에서 다운된 json 파일의 전체 경로를 기입하고 이름을 지정해주면 된다.
-
이를 통해 github action 에서 GCP 에 접근이 가능해진다.
- json 의 ENV 설정에서 project id, region, repository, image 를 지정한다.
- jobs 에 CI 라고 되어 있는데, steps, run, uses 등을 확인한다.
- SHA(hash) 값을 태그 값으로 설정해서, 매 커밋마다 이름이 겹치지 않도록하여 새로운 Image 가 Build + Push 될 수 있도록 한다.
- Google Cloud 인증을 위해
auth
를 사용한다. 여기서 우리가 secret 에 저장한 credential 키를 사용하게 된다. - 이후 Docker 에 로그인 하고
docker push
해준다. - 이를 통해 main 에 merge 됐을 때 새로운 Image 를 빌드하고 push 하는 것까지 자동화가 된다.
- 이제 서버에 배포하기 위해 GCP Compute Engine 을 세팅하고 인스턴스를 생성하자.
- 컨테이너 옵션을 사용한다. 컨테이너 Image 배포에서 위에서 빌드한 Image 를 사용한다. 이를 통해 직접 만든 Image 를 사용해서 compute engine 을 띄우게 된다.
- 컨테이너 구성은 어떤 Image 를 사용할 것인가를 입력하면 된다. Volume Mount 도 사용할 수 있다.
- 인스턴스 생성을 완료하면 외부 IP 주소를 확인할 수 있다.
- VM instance 에 새 Image 배포하기 (컨테이너 업데이트)
- 컨테이너 업데이트에는 정답이 있는 건 아니다.
- 인스턴스를 띄울 때 Docker Image 를 기반으로 생성하면, 이후 업데이트된 Image 를 기반으로 컨테이너 업데이트가 가능하다. 클라우드마다 기능이 다르긴 하지만, Image 가 바뀌면 새롭게 컨테이너를 업데이트 하는 기능이 대부분 존재한다.
- 만약 컨테이너로 띄우지 않고, 그냥 서버를 띄웠다면 새로운 코드를 pull 하고 scp/FTP 등으로 서버에 전송하고, 그 코드를 기반으로 앱을 재실행하게 된다. reload 옵션 등이 있으면 설정해준다.
-
reload = True
로 주면, 파일이 바뀔 때마다 새롭게 알아서 웹을 껐다 킨다. 그게 아니면 웹을 껐다가 다시 동작시켜야 하는데, 그 찰나에 이슈가 있을 수도 있다. 이 시간동안 API 응답을 못하기 때문이다. - 새로운 모델, 코드, 의존성 등이 하나의 Image 로 만들어지고, 컨테이너 Image 업데이트 요청을 compute engine 에게 하는 방법이 권장된다.
- Compute Engine 에서는 GCP 명령어를 이용해서 Image 로 만들어진 인스턴스를 빠르게 업데이트 할 수 있는 기능을 CLI 로 제공하고 있다.
gcloud compute instances update-container <서버 이름> --container-image <컨테이너 이미지>
- CI (Continuous Integration) 를 진행한 후, GCE VM Instance 에 변경 사항을 전파한다.
- workflow.yml 에
needs
라는 필드에needs: [ci]
와 같이 ci 작업이 정상 완료되어야 실행하겠다고 알려준다. -
업데이트할 인스턴스, 존(영역) 정보를 사용하여 해당 인스턴스를 업데이트하게 된다.
- github action 에서는 위와 같이 쉘 커맨드를 많이 사용한다.
- secret 같은 환경변수를 잘 사용하는 것이 보안에 안전하다.
-
이렇게 되면 Actions 메뉴에서 ci 가 완료된 후 cd 가 실행됨을 확인할 수 있다. 즉
needs
를 통해 dependeny 가 생긴 것이다.
- workflow.yml 에
- 이렇게 Image 를 만들고 registry 에 push 한 뒤, 해당 Image 를 사용해서 compute engine 에 배포한다. 이후 Github Action 을 통해 코드가 변경되면 CI 를 진행하고 CD 를 통해 자동 업데이트 할 수 있다.
- 중요한 것은 이미 많이 공유되어 있는 github action 템플릿들을 적극적으로 이용해서 CI/CD 에 대해 익숙해지는 것이다.
댓글 남기기