Runner CI/CD 구성하기
개요

GitLab에 IaC 코드와 개발했던 소스 코드를 업로드했다. 레포지토리 별로 gitlab-ci.yml 파일을 작성해봐야겠다.
- GitLab Group 구성정보
- grpc-auth (auth_service 소스코드)
- grpc-board (board_service 소스코드)
- grpc-gateway (gateway 소스코드)
- grpc-helm (gateway, auth, board Helm Chart가 담겨져있는 레포지토리)
- grpc-proto (proto 파일이 담겨져있는 레포지토리)
GitLab Runner 구성하기
필요한 구성 정보 만들기
- GitLab - Group Access Token 발급

- ArgoCD - Repository 연결하기

ArgoCD Settings → Repositories → Connect Repo
- GitLab - CI/CD Variables 설정

공통으로 사용되는 HARBOR 정보는 변수로 추가하기.
Gitlab-ci.yml 작성하기
아래 블로그에서 gitlab-ci.yml 정리가 잘 되어있어서 작성할때 참고하기!
https://bravenamme.github.io/2020/11/09/gitlab-runner/
1.1. Stage 나누기
먼저 Stage를 나눠서 생각해봐야겠다. 총 3단계로 구분지어서 작성할 예정인데 preset, build, deploy로 구성할 예정이다.
- preset : proto가 담긴 레포지토리를 clone 단계
- build : proto 파일을 빌드하고 kaniko를 이용해서 container image 빌드 후 harbor에 업로드
- deploy : ArgoCD가 감지할 수 있도록 helm 차트가 담긴 레포지토리를 clone 후 values.yaml에 이미지 태그 변경
1.2. Stage별 Job 나누기
각 Stage에서 Job을 구성해보자. (preset 부분에서 proto, git clone job을 나눠서 해야겠다.)
- preset : git_clone, proto_build
- build : image_build
- deploy : deploy_argocd
1.3. Job Script 제작하기
먼저 preset에 들어갈 간단한 git_clone 만들기
git_clone:
stage: preset
image:
name: bitnami/git:latest
script:
- git clone https://journalctl:그룹토큰그룹토큰@gitlab.journalctl-xe.com/grpc-test/grpc-proto.git --branch dev
- ls -lh
artifacts: # proto_build에 사용할 수 있도록 artifact로 저장해서 다음 job에서 다운로드 받을 수 있게 설정
paths:
- grpc-proto/
expire_in : 1 hour
tags:
- test
proto 빌드에 사용하는 job 만들기
proto_build:
stage: preset
needs: ["git_clone"] # git_clone이 수행된 이후 proto_build 수행하도록 설정.
image:
name: harbor.journalctl-xe.com/library/python:grpcio-3.9.6
artifacts: # proto 컴파일 후 나온 파일들 image build시 포함될 수 있도록 artifact로 저장
paths:
- output/
expire_in: 1 hour
script:
- mkdir output
- python3 -m grpc_tools.protoc -I./grpc-proto/proto --python_out=./output --grpc_python_out=./output ./grpc-proto/proto/*
- ls -lh
tags:
- test
kaniko로 이미지 빌드 후 harbor에 푸시하는 job 만들기
image_build:
stage: build
# before_script로 Kaniko에서 사용할 Harbor 인증정보 담기
before_script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$HARBOR_URL\":{\"username\":\"$HARBOR_USERNAME\",\"password\":\"$HARBOR_PASSWORD\"}}}" > /kaniko/.docker/config.json
- cat /kaniko/.docker/config.json
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
artifacts:
paths:
- output/
script:
- echo "Building the app"
- cp ./output/*.py ./
# $CI로 시작하는 변수는 GitLab Runner에서 전역으로 사용가능한 변수
- /kaniko/executor --context dir://$CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $HARBOR_URL/library/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA
tags:
- test
ArgoCD가 감지할 수 있도록 이미지 태그 변경하는 job 만들기
deploy_argocd:
stage: deploy
image:
name: alpine:latest
before_script:
- apk add --no-cache git curl jq yq
script:
- git clone https://journalctl:그룹토큰그룹토큰@gitlab.journalctl-xe.com/grpc-test/grpc-helm.git --branch dev
- yq -i ".image.tag = \"$CI_COMMIT_SHORT_SHA\"" ./grpc-helm/$CI_PROJECT_NAME/values.yaml
- git config --global user.email "dltkdrnd123@gmail.com"
- git config --global user.name "journalctl"
- cd grpc-helm
- git status
- git add $CI_PROJECT_NAME/values.yaml
# Runner CI에서 ':' escape 방법으로 > 후에 작성한다.
- >
git commit -m "UPDATE :: $CI_PROJECT_NAME - values.yaml"
- git push origin dev
# only 태그 사용해서 dev 브랜치에서만 작업할 수 있도록 강제할 수 있다.
only:
- dev
tags:
- test
1.4. 완성된 전체 스크립트
#variables:
# CI_DEBUG_TRACE: "true"
stages:
- preset
- build
- deploy
git_clone:
stage: preset
image:
name: bitnami/git:latest
script:
- git clone https://journalctl:glpat-M2kxL54mt7pHxg_h2kGo@gitlab.journalctl-xe.com/grpc-test/grpc-proto.git --branch dev
- ls -lh
artifacts:
paths:
- grpc-proto/
expire_in : 1 hour
tags:
- test
proto_build:
stage: preset
needs: ["git_clone"]
image:
name: harbor.journalctl-xe.com/library/python:grpcio-3.9.6
artifacts:
paths:
- output/
expire_in: 1 hour
script:
- mkdir output
- python3 -m grpc_tools.protoc -I./grpc-proto/proto --python_out=./output --grpc_python_out=./output ./grpc-proto/proto/*
- ls -lh
tags:
- test
image_build:
stage: build
needs: ["proto_build"]
before_script:
# Setting to Kaniko
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$HARBOR_URL\":{\"username\":\"$HARBOR_USERNAME\",\"password\":\"$HARBOR_PASSWORD\"}}}" > /kaniko/.docker/config.json
- cat /kaniko/.docker/config.json
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
artifacts:
paths:
- output/
script:
- echo "Building the app"
- cp ./output/*.py ./
- /kaniko/executor --context dir://$CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $HARBOR_URL/library/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA
tags:
- test
deploy_argocd:
stage: deploy
image:
name: alpine:latest
before_script:
- apk add --no-cache git curl jq yq
script:
- git clone https://journalctl:glpat-M2kxL54mt7pHxg_h2kGo@gitlab.journalctl-xe.com/grpc-test/grpc-helm.git --branch dev
- yq -i ".image.tag = \"$CI_COMMIT_SHORT_SHA\"" ./grpc-helm/$CI_PROJECT_NAME/values.yaml
- git config --global user.email "dltkdrnd123@gmail.com"
- git config --global user.name "journalctl"
- cd grpc-helm
- git status
- git add $CI_PROJECT_NAME/values.yaml
- >
git commit -m "UPDATE :: $CI_PROJECT_NAME - values.yaml"
#- git commit -m *commit_message
- git push origin dev
only:
- dev
tags:
- test
GitLab Runner로 CI 해보기
GitLab에서 레포지토리 최상단에 .gitlab-ci.yml 파일이 있을경우 감지하여 Runner가 해당 파일을 참조하여 동작하게 된다.
GitLab Runner 페이지

Harbor 페이지

ArgoCD 페이지


Kubernetes
$ kubectl get po -n grpc
NAME READY STATUS RESTARTS AGE
grpc-auth-695f47b49f-ct5nf 1/1 Running 0 36h
grpc-board-5cd78b5c5-v95xx 1/1 Running 0 36h
grpc-gateway-6f57c46947-hx9ht 1/1 Running 0 36h
후기
기존 CI 툴로 Jenkins를 주로 사용했었는데 Runner와 비교해서 내가 느끼는 장단점은 확실한 것 같다.
- Jenkins는 Groovy 문법을 사용하는데 Runner는 Yaml 형식으로 작성할 수 있어서 개인적으로 Runner가 편했다.
- Jenkins는 다양한 플러그인이 지원해서 원하는 기능을 찾아서 설치하면 되지만 Runner는 상대적으로 부족하다
- GitLab을 사용하면 Jenkins, Runner 둘 다 사용가능하지만 독립적인 CI로 Runner는 불가능하다.
- Jenkins를 Kubernetes에서 사용할때 Agent Pod Template 형태로 여러 이미지를 스크립트 실행 시 사용할 수 있는데 Runner는 각 Job별로 하나의 이미지만 사용가능해서 조금 아쉬웠다.
- job별로 pod가 생성되고 삭제되는데 여러 job이 수행되는경우 꽤나 시간이 오래걸린다. log도 pipeline 전체 로그를 한번에 확인하고 싶은데 job별로 로그 확인해야해서 불편함이 있었다. (이건 많이 사용해보지 않아서 Runner에서 해당 기능을 제공하는지 찾아봐야겠다.)
정리하면 소규모 프로젝트나 GitLab을 사용하는 기업이라면 Runner도 괜찮을 것 같다. 하지만 Jenkins가 범용적인 부분에서 더 좋은 것 같다.
