github action ci/cd

Dongyoung Kim·2023년 3월 10일
0

Development

목록 보기
1/1
post-thumbnail

제 개인 포트폴리오 웹사이트 (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 를 구축해보고자 합니다.

github action with dockerhub and gcp

회사에서는 주로 jenkins 로 구현을 하고, 일부 gitlab ci/cd 로 쓰고 있습니다. github action 은 처음인데 계획은 이렇습니다.

  1. 제 포트폴리오의 소스코드는 github (https://github.com/DongyoungKim2/home) 있습니다.

  2. github action 을 이용해 pynecone docker container 를 base 로 해서 git clone 을 한 후 pynecone 을 실행시키는 컨테이너를 만들고, version 을 변경후 이를 dockerhub registry 에 push 합니다.

  3. github action 을 이용해 gcp instance 에 container version 정보를 업데이트하고 재시작 시킵니다.

  4. Ta-da! (https://dykim.dev/)

설계

github action 을 사용하면 github-hosted runners 라는 ubuntu 컨테이너가 생성되고, 컨테이너 내에서 ci/cd 를 수행할 수 있습니다. 컨테이너에서 해야할 일은 다음과 같습니다. 저는 아래 작업에 대해 main branch 에 push 가 되면 수행되게끔하려 합니다.

  1. docker login (docker 로그인 정보 필요)

  2. docker container build

  3. dockerhub push

  4. gcp login (gcp 로그인 정보 필요)

  5. gcloud cli 설치

  6. gcloud cli command 로 gcp instance에 새 컨테이너 설정

  7. gcloud cli command 로 gcp instance 재시작 (reset)

github action yml

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 }}"

상당히 길어 보이지만 그 작동방식만 알면 단순합니다.

on

name: Docker Image CI
on:
  push:
    branches: ["main"]

main branch 에 push 되면 본 스크립트가 작동할것을 의미합니다

env

env:
  VERSION: "0.1.10"
  PROJECT_ID: ***
  GCE_INSTANCE: *** # instance name
  GCE_INSTANCE_ZONE: *** # instance zone

환경변수입니다. yml 파일 내에서 전역적으로 사용가능합니다. 사용방법은 ${{ env.변수명 }} 입니다.

steps: checkout

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: check out the repo
        uses: actions/checkout@v3

여기서부터 시작입니다. github runner 는 ubuntu 를 사용한다는것이고, steps 부터 -name 으로 단계를 시작합니다. uses 는 미리 만들어진 스크립트를 사용한다는 의미입니다. checkout 은 현재 리포를 checkout 하는 스크립트로 기본적으로 실행될 내용입니다.

steps: docker

      - 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 정보를 적어줍니다.

steps: gcp

      - 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분 정도 걸리네요.

profile
AI professional for science and industry

0개의 댓글