제 개인 포트폴리오 웹사이트 (https://dykim.dev/) 는 pynecone (https://pynecone.io/) 으로 만들어 google cloud platform 의 무료 프로그램 (https://cloud.google.com/free/docs/free-cloud-features?hl=ko) 을 이용하여 배포하여 쓰고 있습니다.
pynecone 과 gcp 를 공부하면서 만들면서 ci/cd 를 셋업해두지 않았더니 업데이트가 있을때 마다 여간 불편한게 아니라 github action 을 이용해 ci/cd 를 구축해보고자 합니다.
회사에서는 주로 jenkins 로 구현을 하고, 일부 gitlab ci/cd 로 쓰고 있습니다. github action 은 처음인데 계획은 이렇습니다.
제 포트폴리오의 소스코드는 github (https://github.com/DongyoungKim2/home) 있습니다.
github action 을 이용해 pynecone docker container 를 base 로 해서 git clone 을 한 후 pynecone 을 실행시키는 컨테이너를 만들고, version 을 변경후 이를 dockerhub registry 에 push 합니다.
github action 을 이용해 gcp instance 에 container version 정보를 업데이트하고 재시작 시킵니다.
Ta-da! (https://dykim.dev/)
github action 을 사용하면 github-hosted runners 라는 ubuntu 컨테이너가 생성되고, 컨테이너 내에서 ci/cd 를 수행할 수 있습니다. 컨테이너에서 해야할 일은 다음과 같습니다. 저는 아래 작업에 대해 main branch 에 push 가 되면 수행되게끔하려 합니다.
docker login (docker 로그인 정보 필요)
docker container build
dockerhub push
gcp login (gcp 로그인 정보 필요)
gcloud cli 설치
gcloud cli command 로 gcp instance에 새 컨테이너 설정
gcloud cli command 로 gcp instance 재시작 (reset)
github action 은 기본적으로 yml 파일로 할일을 리스트 하고, 이를 .github/workflows/파일이름.yml
에 저장하면, 이를 github runner 가 상황에 따라 인식 하고 돌려주는 방식입니다. 위 내용대로 yml 파일을 작성하면 다음과 같습니다.
name: cicd for dykim_dev
on:
push:
branches: ["main"]
env:
VERSION: "0.1.10"
PROJECT_ID: ***
GCE_INSTANCE: ***
GCE_INSTANCE_ZONE: ***
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: check out the repo
uses: actions/checkout@v3
- name: login to docker hub
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: build and push to docker hub
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
push: true
tags: dongyoungkim/home:${{ env.VERSION }}
labels: ${{ env.VERSION }}
- name: google auth
id: "auth"
uses: "google-github-actions/auth@v1"
with:
credentials_json: "${{ secrets.GCE_SA_KEY }}"
- name: set up Cloud SDK
uses: "google-github-actions/setup-gcloud@v1"
with:
project_id: ${{ env.PROJECT_ID }}
- name: use gcloud cli
run: "gcloud info"
- name: gcp deploy
run: |-
gcloud compute instances update-container "${{ env.GCE_INSTANCE }}" \
--zone "${{ env.GCE_INSTANCE_ZONE }}" \
--container-image "dongyoungkim/home:${{ env.VERSION }}"
- name: gcp reset
run: |-
gcloud compute instances reset "${{ env.GCE_INSTANCE }}" \
--zone "${{ env.GCE_INSTANCE_ZONE }}"
상당히 길어 보이지만 그 작동방식만 알면 단순합니다.
name: Docker Image CI
on:
push:
branches: ["main"]
main branch 에 push 되면 본 스크립트가 작동할것을 의미합니다
env:
VERSION: "0.1.10"
PROJECT_ID: ***
GCE_INSTANCE: *** # instance name
GCE_INSTANCE_ZONE: *** # instance zone
환경변수입니다. yml 파일 내에서 전역적으로 사용가능합니다. 사용방법은 ${{ env.변수명 }} 입니다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: check out the repo
uses: actions/checkout@v3
여기서부터 시작입니다. github runner 는 ubuntu 를 사용한다는것이고, steps 부터 -name
으로 단계를 시작합니다. uses
는 미리 만들어진 스크립트를 사용한다는 의미입니다. checkout 은 현재 리포를 checkout 하는 스크립트로 기본적으로 실행될 내용입니다.
- name: login to docker hub
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: build and push to docker hub
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
push: true
tags: dongyoungkim/home:${{ env.VERSION }}
labels: ${{ env.VERSION }}
도커관련 내용입니다. docker login 스크립트와 build & push 스크립트를 이용하여 two step 으로 진행합니다.
login
에 ${{ secrets.DOCKER_USERNAME }}
와 같이 secrets 으로 된 내용은 github repo 내 settings > secrets and variables > actions > new repositry secret
에서 만들어 저장해 두면 불러올 수 있는 내용입니다. docker username 및 password (token) 은 docker hub 로그인 후 계정정보account settings > security > Access Tokens
에서 발급받을 수 있습니다.
build & push
에서는 tags 와 labels 에 docker hub registry 정보를 적어줍니다.
- name: google auth
id: "auth"
uses: "google-github-actions/auth@v1"
with:
credentials_json: "${{ secrets.GCE_SA_KEY }}"
- name: set up Cloud SDK
uses: "google-github-actions/setup-gcloud@v1"
with:
project_id: ${{ env.PROJECT_ID }}
- name: use gcloud cli
run: "gcloud info"
gcp 에 로그인하고, cloud sdk 설치하고 cli 설정하는 위 세단계에는 gcp 의 project id 와 gcp secrets 이 필요합니다. gcp secret 은 IAM 및 관리자 > 서비스 계정 > 서비스계정 만들기
하면 만들어지고 다운로드 되는 json 파일을 열어 그 내부 내용을 github secret 에 저장하고 불러오면 됩니다.
- name: gcp deploy
run: |-
gcloud compute instances update-container "${{ env.GCE_INSTANCE }}" \
--zone "${{ env.GCE_INSTANCE_ZONE }}" \
--container-image "dongyoungkim/home:${{ env.VERSION }}"
- name: gcp reset
run: |-
gcloud compute instances reset "${{ env.GCE_INSTANCE }}" \
--zone "${{ env.GCE_INSTANCE_ZONE }}"
위 과정을 거치면 gcloud cli 를 github runner 내에서 사용할 수 있게 되고, run 명령어를 통해 gcloud cli 로 컨테이너 업데이트 및 재시작을 수행합니다. 여기에선 run 명령어로 직접 실행하기에 uses 의 scipr load 가 없습니다.
위와 같이 yml 을 작성하고 push 하면 github action 에서 다음과 같이 그 과정 및 로그를 확인할 수 있습니다.
다만 ci/cd 가 github action 에서 완료되더라도 gcp 의 computing instance 에서 load balancer, dns 까지 모두 propagation 되는데는 10분 정도 걸리네요.