IaC/CI CD Tool

6. Gitlab CI Build(with GCP Artifact Registry, Harbor)

Somaz 2024. 6. 24. 13:27
728x90
반응형

Overview

Gitlab CI를 사용해서 Build 후 GCP Artifact Registry와 Harbor에 업로드 하는 방법에 대해서 알아본다.

 


Gitlab CI Build and Push(with GCP Artifact Registry, Harbor)

 

dockerConfigJson 작성

 

Harbor

  1. 사용자 이름과 비밀번호 인코딩: `echo -n` 을 사용하여 사용자 이름과 비밀번호를 한 줄로 출력하고, `base64` 명령으로 인코딩한다. `n` 옵션은 라인 끝의 개행문자를 제거한다.
  2. JSON 파일 생성: `cat <<EOF > config.json` 를 사용하여 다중 라인의 텍스트를 `config.json` 파일로 리다이렉션한다. 변수 `$AUTH` 는 이전 단계에서 생성된 인코딩된 문자열을 사용한다.
  3. 전체 JSON 파일 인코딩: `cat config.json` 으로 파일을 읽고, ` base64` 로 인코딩한 다음, `tr -d '\\n'` 으로 인코딩된 문자열에서 개행 문자를 제거한다.
  4. Kubernetes Secret 생성용 YAML 파일 준비: 위와 비슷한 방식으로 `YAML` 파일을 생성하며, 이 파일은 Kubernetes에서 사용할 수 있다.

 

사용자 이름과 비밀번호를 인코딩한다.

AUTH=$(echo -n 'somaz:somaz@2024' | base64)

 

 

JSON 파일을 생성한다.

cat <<EOF > config.json
{
  "auths": {
    "your.harbor.domain": {
      "username": "somaz",
      "password": "somaz@2024",
      "email": "somaz.link",
      "auth": "$AUTH"
    }
  }
}
EOF

# 한줄작성
echo '{"auths":{"your.harbor.domain":{"username":"somaz","password":"somaz@2024","email":"somaz.link","auth":"'"$AUTH"'"}}}' > config.json

 

 

전체 JSON 파일을 BASE64로 한번더 인코딩한다.

# JSON 파일을 BASE64로 인코딩
ENCODED_JSON=$(cat config.json | base64 -w 0)

or
# 둘중 하나 선택
ENCODED_JSON=$(cat config.json | base64 -w 0 | tr -d '\\n')

# 확인
echo $ENCODED_JSON
eyJhdXRocyI6eyJ5b3VyLmhhcmJvci5kb21haW4iOnsidXNlcm5hbWUiOiJzb21heiIsInBhc3N3b3JkIjoic29tYXpAMjAyNCIsImVtYWlsIjoic29tYXoubGluayIsImF1dGgiOiJjMjl0WVhvNmMyOXRZWHBBTWpBeU5BPT0ifX19Cg==

echo "eyJhdXRocyI6eyJ5b3VyLmhhcmJvci5kb21haW4iOnsidXNlcm5hbWUiOiJzb21heiIsInBhc3N3b3JkIjoic29tYXpAMjAyNCIsImVtYWlsIjoic29tYXoubGluayIsImF1dGgiOiJjMjl0WVhvNmMyOXRZWHBBTWpBeU5BPT0ifX19Cg==" |base64 -d -w 0
{"auths":{"your.harbor.domain":{"username":"somaz","password":"somaz@2024","email":"somaz.link","auth":"c29tYXo6c29tYXpAMjAyNA=="}}}

 

 

마지막으로 Kubernetes Secret 생성용 YAML 파일 준비한다.

cat <<EOF > k8s-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: myregistrykey
  namespace: default
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: $ENCODED_JSON
EOF

 

 

Google Artifact Registry

  1. Docker 로그인 실행 : 로컬에서 `serviceaccount.json` 파일을 사용하여 Docker 로그인을 수행하고, 결과로 생성된 `config.json` 파일을 생성한다.
  2. dockerconfigjson 파일 준비 : 로그인 후 생성된 `~/.docker/config.json` 파일을 `base64` 로 인코딩한다. 인코딩된 결과는 Helm의 values 파일에 사용된다.
  3. Kubernetes Secret 생성 : 인코딩된 `dockerconfigjson`를 Helm 차트의 values 파일에 삽입하여 Kubernetes에서 사용할 수 있는 Secret을 생성한다.

 

`serviceaccount.json` 파일을 사용하여 로컬에서 `dockerconfigjson` 을 생성해본다.

export REGION=<YOUR-REGION>
cat serviceaccount.json | docker login -u _json_key --password-stdin https://$REGION.pkg.dev

 

 

생성된 `config.json` 파일의 내용을 복사하여 Helm values 파일의 `artifactregistry.dockerConfigJson` 필드에 `base64` 인코딩된 형태로 삽입한다.

cat ~/.docker/config.json | base64 -w 0

 

 

Kubernetes Secret을 생성한다. 이번에는 Helm Chart를 사용해본다. template을 먼저 생성한다.

 

`gcp-ar-secret.yaml`

{{- if .Values.artifactregistry.enabled }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ include "somaz.fullname" . }}
  namespace: {{ .Release.Namespace }}
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: {{ .Values.artifactregistry.dockerConfigJson }}
{{- end }}

 

`values.yaml`

image:
  repository: <region>-docker.pkg.dev/mgmt-2023/<repo name>/<image name>
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: "<image Tag>"

imagePullSecrets:
  - name: <image pull secret name>

artifactregistry:
  enabled: false
  dockerConfigJson: "BASE64_ENCODED_JSON_HERE"

 

 

Gitlab CI 작성

Build에는 Kaniko를 사용한다. GCP Artifact Registry와 Harbor를 상황에 맞게 사용할 수 있는 Gitlab Ci를 작성해본다.

 

 

Harbor & GCP ArtifactRegistry

 

Namespace에 `somaz-` 가 들어가면 GCP로 Upload 하고, 그 이외의 값이 들어가면 Harbor로 업로드 하게 된다. Predefined 변수를 제외하곤 Gitlab Variables 값에 넣어줘야 한다.

stages:
  - gcloud
  - build # buld images & push to private image registry at once

# 스크립트에서 사용할 변수 설정
# CI_COMMIT_REF_NAME 파이프라인 실행하는 현재 브랜치명
variables:
  NAMESPACE:
    value: "dev1"
    description: "Select the namespace: dev1 or dev2 or staging(use deploy)"
    options:
      - "dev1"
      - "dev2"
      - "staging"
      - "qa1"
      - "somaz-dev"
  SERVICE:
    value: "game"
    description: "Select admin or game or batch or etc."
    options:
      - "game"
      - "admin"
  CI_REGISTRY_IMAGE: $CI_REGISTRY/$SERVICE
  BUILD_TAG: $CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA
  IMAGE_URL: '${CI_REGISTRY_IMAGE}:${BUILD_TAG}'
  BUILD_TAG_LATEST: $CI_COMMIT_REF_NAME-latest
  IMAGE_URL_LATEST: '${CI_REGISTRY_IMAGE}:${BUILD_TAG_LATEST}'
  GCP_CI_REGISTRY_IMAGE: '$GCP_CI_REGISTRY/${SERVICE}-fgn/${SERVICE}-fgn'
  GCP_IMAGE_URL: '${GCP_CI_REGISTRY_IMAGE}:${BUILD_TAG}'
  GCP_IMAGE_URL_LATEST: '${GCP_CI_REGISTRY_IMAGE}:${BUILD_TAG_LATEST}'  

gcloud:
  stage: gcloud
  image:
    name: gcr.io/google.com/cloudsdktool/google-cloud-cli:latest
  variables:
    CLOUDSDK_CONFIG: $CI_PROJECT_DIR/gcloud
  before_script:
    - echo [INFO] Start gcloud config setting.
    - echo [INFO] GCP_SERVICE_ACCOUNT is $GCP_SERVICE_ACCOUNT
    - echo [INFO] CLOUDSDK_CONFIG is $CLOUDSDK_CONFIG
    - echo [INFO] GCP_CI_REGISTRY is $GCP_CI_REGISTRY
    - mkdir -p ${CLOUDSDK_CONFIG}
  script:
    - echo $GCP_SERVICE_ACCOUNT_KEY_BASE64 | base64 --decode > ${CLOUDSDK_CONFIG}/gcloud-service-key.json
    - gcloud auth activate-service-account --key-file=${CLOUDSDK_CONFIG}/gcloud-service-key.json
    - token=$(gcloud auth print-access-token)
    - docker_token=$(echo -n "gclouddockertoken:$token" | base64 | tr -d "\\n")
    - echo "{\\"auths\\":{\\"$GCP_CI_REGISTRY\\":{\\"auth\\":\\"$docker_token\\",\\"email\\":\\"admin@nerdystar.io\\"}}}" > gcloud/config.json
  artifacts:
    paths:
      - gcloud/config.json
  rules:
    - if: '$NAMESPACE =~ /^somaz-/'
      when: on_success
    - when: never
  tags:
    - build-image

# web에서 수동 빌드 시 사용
build_manual_image:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:v1.22.0-debug
    # entrypoint 는 명시적으로  "" 빈 스트링 지정해야함.
    entrypoint: [""]
  before_script:
    - echo [INFO] Start build image.
    - echo [INFO] CI_REGISTRY is $CI_REGISTRY
    - echo [INFO] CI_REGISTRY_IMAGE is $CI_REGISTRY_IMAGE
    - echo [INFO] CI_COMMIT_REF_NAME is $CI_COMMIT_REF_NAME
    - echo [INFO] BUILD_TAG is $BUILD_TAG
    - echo [INFO] IMAGE_URL is $IMAGE_URL
    - echo [INFO] BUILD_TAG_LATEST is $BUILD_TAG_LATEST
    - echo [INFO] IMAGE_URL_LATEST is $IMAGE_URL_LATEST
    - echo [INFO] CI_PROJECT_DIR is $CI_PROJECT_DIR
    - echo [INFO] SERVICE is $SERVICE
    - echo [INFO] GCP Config
    - echo [INFO] GCP_CI_REGISTRY is $GCP_CI_REGISTRY
    - echo [INFO] GCP_CI_REGISTRY_IMAGE is $GCP_CI_REGISTRY_IMAGE
    - echo [INFO] GCP_IMAGE_URL is $GCP_IMAGE_URL
    - echo [INFO] GCP_IMAGE_URL_LATEST is $GCP_IMAGE_URL_LATEST
    - echo [INFO] NAMESPACE is $NAMESPACE
    # registry 접속 정보를 저장하기 위한 디렉토리 생성
    - mkdir -p /kaniko/.docker
    # private 레지스트리에 대한 접속 정보 지정
    - >
      if [[ "$NAMESPACE" =~ ^somaz- ]]; then
        echo "Configuring registry for special namespace $NAMESPACE"
        # echo $GCP_SERVICE_ACCOUNT_KEY_BASE64 | base64 -d > /kaniko/.docker/config.json
        cp gcloud/config.json /kaniko/.docker/config.json
      else
        echo "{\\"auths\\":{\\"$CI_REGISTRY\\":{\\"auth\\":\\"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64)\\"}}}" > /kaniko/.docker/config.json
      fi
  script:
    - >
      if [[ "$NAMESPACE" =~ ^somaz- ]]; then
        # somaz-가 포함된 NAMESPACE용 설정
        echo "Using special build settings for $NAMESPACE"
        /kaniko/executor --cache=true --cache-ttl=24h --snapshot-mode=redo --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/$SERVICE.Dockerfile --destination $GCP_IMAGE_URL --destination $GCP_IMAGE_URL_LATEST --build-arg NODE_ENV=$CI_COMMIT_REF_NAME --skip-tls-verify
      else        
        /kaniko/executor --cache=true --cache-ttl=24h --snapshot-mode=redo --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/$SERVICE.Dockerfile --destination $IMAGE_URL --destination $IMAGE_URL_LATEST --build-arg NODE_ENV=$CI_COMMIT_REF_NAME --skip-tls-verify
      fi
  rules:
    - if: '($CI_PIPELINE_SOURCE == "web")'
  tags:
    - build-image

 

 

Gitlab Runner 관련해서는 아래의 게시물 참고하면 된다.

2023.04.18 - [IaC/CI CD Tool] - 2. GitLab이란? / GitLab Runner 개념 및 설치

 

2. GitLab이란? / GitLab Runner 개념 및 설치

Overview오늘은 GitLab Runner의 개념과 설치 방법에 대해 알아보려고 한다. 다음시간에는 GitLab CI/CD 구동방식과 GitLab 문법에 대해 자세히 공부해보려고 한다. GitLab 설치는 아래의 페이지를 참고하기

somaz.tistory.com

 

 

 


Reference

https://docs.gitlab.com/ee/ci/docker/using_kaniko.html

728x90
반응형