CI/CD 구축하기(1)-Gitlab-ci(Gitlab-ci + Helm + ArgoCD, GCP kubernetes 등)

Roy Jung·2024년 8월 4일
0
post-thumbnail
post-custom-banner

목표

  • GCP에 있는 K8S 서비스의 CI/CD를 구축해본다.
  • 기술 스택은 Gilab-ci, helm chart, argoCD
  • 최종 결과의 Flow는 gitlab에 소스코드를 푸시하면 gitlab ci가 소스 코드를 빌드하고 Docker Registry에 푸시한다. Helm chart manifest(이 프로젝트에서는 GCP Source repository라는 서비스를 사용했다. 특별한 서비스는 아니고 gcp에 있는 git이다. 회사 네트워크 보안 때문에 이를 사용하게 됐다.)의 태그를 바꿔주고 argoCD가 Helm manifest를 참조해서 알맞는 Docker image를 가져와 k8s에 서비스를 배포하게 되는 구조다.

구축하기에 순서는 helm, argoCD, gitlab-ci가 맞는 것 같은데 정리는 가장 쉬운 Gitlab-ci부터 해보자
일단 stage라는 걸 나누게 되는데 나는 아래와 같이 stage를 나눴고. 추후에 테스트 코드 작성 후에 test라는 stage는 추가해야겠다.

  • build: 소스 코드를 빌드 후 Docker Registry(GCP Artifact Registry)에 푸시. 태그는 date를 사용했다.
  • bake: Helm manifest가 있는 Repository(GCP Source Repository)에 variable 중 tag를 위에서 사용한 tag로 수정해준다.
  • migration: DB migration 해주는 부분. Database를 사용하지 않는 서비스라면 필요하지 않는 stage
  • deploy: 구축된 argoCD 서버에 sync 명령을 날려주는 stage. argoCD가 먼저 구축되어 있어야하고, auto sync만 사용해도 괜찮은 경우도 있을 듯하다.

코드도 어렵지 않고 읽어보면 쉽게 이해할 수 있을 것 같다. 지피티와 함께라면..

stages:
  - build
  - bake
  - migration
  - deploy
variables:
  DEV_VALUES_FILE: "values-dev.yaml"

build:
  stage: build
  image: docker:24.0.5
  tags:
    - shared
  only:
    - dev
  environment:
    name: dev
  services:
    - docker:24.0.5-dind
  script:
    - export TAG=$(date +'t%Y%m%d%H%M%S')
    - echo "TAG=$TAG" >> build.env
    - apk update
    - apk --no-cache add git curl tar python3 ca-certificates
    - curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-457.0.0-linux-x86_64.tar.gz
    - tar -xf google-cloud-cli-457.0.0-linux-x86_64.tar.gz
    - ./google-cloud-sdk/install.sh --quiet
    - ./google-cloud-sdk/bin/gcloud init --console-only
    - ./google-cloud-sdk/bin/gcloud auth activate-service-account --key-file $SERVICE_ACCOUNT_SECRET --project $PROJECT_ID
    - ./google-cloud-sdk/bin/gcloud auth configure-docker $REGION
    - cat $SERVICE_ACCOUNT_SECRET | docker login -u _json_key --password-stdin https://$REGION
    - docker build -t $IMAGE_NAME:latest -f Dockerfile .
    - docker tag $IMAGE_NAME:latest $DOCKER_REGISTRY/$IMAGE_NAME:$TAG
    - docker push $DOCKER_REGISTRY/$IMAGE_NAME:$TAG
    - docker rmi $IMAGE_NAME:latest
  artifacts:
    reports:
      dotenv: build.env

bake_dev_manifest:
  stage: bake
  image: google/cloud-sdk:alpine
  tags:
    - shared
  environment:
    name: dev
  only:
    - dev
  dependencies:
    - build
  script:
    - gcloud init --console-only
    - gcloud auth activate-service-account --key-file $SERVICE_ACCOUNT_SECRET --project $PROJECT_ID
    - gcloud --version
    - gcloud auth configure-docker $REGION
    - docker login -u _json_key --password-stdin https://$REGION < "$SERVICE_ACCOUNT_SECRET"
    - gcloud source repos clone $MANIFEST_REPOSITORY
    - echo "Modifying manifest file!"
    - ls
    - cd $MANIFEST_REPOSITORY
    - sed -i "s|tag:.*|tag:\ $TAG|" $DEV_VALUES_FILE
    - git config user.email "argo-cd@xxxxxx.iam.gserviceaccount.com"
    - git config user.name "argo-cd"
    - git add $DEV_VALUES_FILE
    - git commit -m "Modify docker tag $TAG"
    - export MANIFEST_COMMIT_HASH=$(git rev-parse HEAD)
    - git push origin HEAD
    - cd ..
    - echo "MANIFEST_COMMIT_HASH=$MANIFEST_COMMIT_HASH" >> build.env
  artifacts:
    reports:
      dotenv: build.env

migration_dev:
  stage: migration
  image: node:18
  tags:
    - shared
  environment:
    name: dev
  only:
    - dev
  dependencies:
    - bake_dev_manifest
  script:
    - npm install @nestjs/typeorm typeorm pg
    - npm run typeorm:migration:run

deploy_dev:
  stage: deploy
  image: alpine:latest
  tags:
    - shared
  environment:
    name: dev
  only:
    - dev
  dependencies:
    - migration_dev
  script:
    - apk add --no-cache wget
    - >
      wget --no-check-certificate \
        --method POST \
        --header "Authorization: Bearer $ARGOCD_API_KEY" \
        --header "Content-Type: application/json" \
        --body-data '{
          "appNamespace": "argocd",
          "revision": "HEAD",
          "prune": false,
          "dryRun": false,
          "strategy": { "hook": { "force": false } },
          "resources": null,
          "syncOptions": { "items": [] }
        }' \
        "$ARGOCD_API_SERVER/api/v1/applications/xxxxxxx/sync"
  artifacts:
    reports:
      dotenv: build.env

Gitlab UI에서 요런걸 볼 수 있게 된다. 언제 파이프라인을 돌릴 지 브랜치 정책과 관련해서 잘 결정하면 된다.

profile
내가 보려고 쓰는 글
post-custom-banner

0개의 댓글