데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      [CI/CD] GitLab-Runner 연동 가이드 (feat. Maven 빌드 시간 단축)

      dragonpipe 25.09.22
      3,785 7 1
      DEVOTEE 요약
      GitLab Runner를 활용한 CI/CD 구축 방법을 Helm Chart를 이용해 소개하며, GitLab 프로젝트와 연동 후 발생한 다양한 에러 해결 과정 및 Maven 빌드 속도 개선 방법을 공유합니다. 주요 내용으로는 GitLab Runner 설치, Maven 의존성 캐싱 및 병렬 처리 설정을 통한 빌드 최적화, 그리고 GitLab Token 기반 연동 설정 등이 포함됩니다. 이와 함께 실제 GitLab CI/CD 파이프라인 구성 예제와 문제 해결 방안들이 자세히 설명되며, 특히 CI/CD 과정에서 발생할 수 있는 오류와 대응 방법도 다루고 있습니다.
      DEVOTEE 추천 블로그

      시작하는 글

      오랜만에 글을 올립니다. 사실 작년에 작업한 내용인데, 쌍둥이 육아로 이제야 올리게 되었네요.. 그 동안 작업한 내용이 꽤 되는데 하나씩 잘 정리해서 자주 공유드리겠습니다!

      이 번 글은 Gitlab Runner 연동 관련 포스트입니다. 예전 AKS 상용기에서 Jenkins로 CI를 구성한 내용을 올렸는데요,

      Gitlab과 연동해서 쓰기에는 runner가 더 좋을 것 같아서 새로운 프로젝트의 CI/CD를 구성할 때는 Gitlab-runner로 구성하였습니다.

      어떻게 구성했는지와 구성할 때 발생했던 에러들 어떻게 해결했는지 그리고 maven 빌드가 생각보다 오래 걸려서 어떤 방법으로 빌드 속도를 개선했는지에 대한 내용을 공유드립니다.


      GitLab Runner 설치 (by Helm Chart)

      참고자료: https://docs.gitlab.com/runner/install/kubernetes.html

      Gitlab runner는 VM에도 컨테이너로도 설치가 가능합니다.

      저는 k8s에 컨테이너로 gitlab-runner를 띄워야 했고 k8s에 패키지를 설치할 때 helm 만큼 편한 툴이 없기에.. helm으로 설치하게 되었습니다.

      1. Helm Chart 및 Gitlab Repository 설치

      # Add the GitLab Helm repository:
      helm repo add gitlab https://charts.gitlab.io
      
      # If using Helm 2, you must also initialize Helm:
      helm init
      
      # If you are unable to access to the latest versions of GitLab Runner, you should update the chart. To update the chart, run:
      helm repo update gitlab
      
      # To view a list of GitLab Runner versions you have access to, run:
      helm search repo -l gitlab/gitlab-runner


      2. GitLab 프로젝트에서 Token 가져오기

      1) Gitlab 프로젝트 접속 > Settings > CI/CD > Runners expend > Project runners에서 "New project runner" 클릭 > Tags, Description 입력 > Create runner 클릭
      1.png
      2) authentication token 복사

      2.png

      3. values.yaml 작성

      아래 코드를 복사하여 values.yaml을 저장합니다. 공식 사이트에서 제공하는 values.yaml을 확인하고 싶은 경우 링크로 확인이 가능합니다.

      https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/main/values.yaml

      gitlabUrl: <GitLab server full URL>
      rbac:
        create: true
      runnerToken: <GITLAB-AUTHENTICATION-TOKEN>
      runners:
        executor: kubernetes
        tags: runner1
        config: |
          [[runners]]
            [runners.kubernetes]
              namespace = "{{.Release.Namespace}}"
              image = "alpine"
              privileged = true
              [[runners.kubernetes.volumes.pvc]]
                name = "gitlab-pvc"
                mount_path = "/mnt/share"
      securityContext:
        allowPrivilegeEscalation: true
        readOnlyRootFilesystem: false
        runAsNonRoot: true
        privileged: true
      volumeMounts:
        - name: gitlab-volume
          mountPath: /mnt/share
      volumes:
        - name: gitlab-volume
          persistentVolumeCl
            claimName: gitlab-pvc

      • gitlabUrl: GitLab Host Url

      • runnerToken: 2번에서 획득한 token

      • tags: 태그명 (자유롭게 입력)

      • executor: "kubernetes"

      • runners.config

        • namespace = "{{.Release.Namespace}}" (고정)

        • image = "alpine" (ubuntu도 가능하지만 가벼운 alpine으로 설정)

        • privileged = true (고정) ← dind 방식으로 빌드하려면 필수로 true 설정 해야 함

      • securityContext

        • allowPrivilegeEscalation: true (고정)

        • readOnlyRootFilesystem: false (고정)

        • runAsNonRoot: true (고정)

        • privileged: true (고정)


      4. PV/PVC 설치

      여기서 maven의 빌드 속도를 개선한 핵심이 등장합니다. 바로 maven 의존성 라이브러리를 caching하는 것인데요.

      runner가 매번 빌드할 때마다 의존성을 내려받는데 시간이 많이 걸리는 것을 확인하고 의존성을 caching 해두기로 결정하였습니다.

      k8s이기 때문에 영구적으로 caching 파일을 유지하기 위해 Azure BlobStorage를 Volume으로 마운트할 예정입니다.


      pv.yaml로 저장 → k apply -f pv.yaml로 설치

      apiVersion: v1
      kind: PersistentVolume
      metadata:
        annotations:
          pv.kubernetes.io/provisioned-by: blob.csi.azure.com
        name: gitlab-pv
      spec:
        capacity:
          storage: 10Gi
        accessModes:
          - ReadWriteMany
        persistentVolumeReclaimPolicy: Retain  # If set as "Delete" container would be removed after pvc deletion
        storageClassName: azureblob-fuse-premium
        mountOptions:
          - -o allow_other
          - --file-cache-timeout-in-seconds=120
        csi:
          driver: blob.csi.azure.com
          readOnly: false
          # volumeid has to be unique for every identical storage blob container in the cluster
          # character `#` is reserved for internal use and cannot be used in volumehandle
          volumeHandle: gitlab-volume
          volumeAttributes:
            containerName: gitlab-runner # container name
          nodeStageSecretRef:
            name: blob-secret
            namespace: gitlab

      pvc.yaml로 저장 → k apply -f pvc.yaml로 설치

      kind: PersistentVolumeClaim
      apiVersion: v1
      metadata:
        name: gitlab-pvc # pvc naming
        namespace: gitlab
      spec:
        accessModes:
          - ReadWriteMany  # access mode
        storageClassName: azureblob-fuse-premium # created by AKS
        volumeName: gitlab-pv
        resources:
          requests:
            storage: 10Gi


      5. GitLab-runner 설치

      드디어 gitlab-runner를 설치합니다. 저는 helm 3 기반으로 설치하였습니다.

      # Once you have configured GitLab Runner in your values.yaml file, run the following:
      
      # For Helm 2
      helm install --namespace <NAMESPACE> --name gitlab-runner-1 -f <CONFIG_VALUES_FILE> gitlab/gitlab-runner
      
      # For Helm 3
      helm install --namespace <NAMESPACE> gitlab-runner-1 -f <CONFIG_VALUES_FILE> gitlab/gitlab-runner
      
      # 예시 (Helm 3)
      helm install --namespace gitlab gitlab-runner-1 -f values.yaml gitlab/gitlab-runner


      6. GitLab-Runner 여러개 설치하는 방법

      1) values2.yaml 생성

      gitlabUrl: <GitLab server full URL>
      rbac:
        create: true
      runnerToken: <GITLAB-AUTHENTICATION-TOKEN>
      runners:
        executor: kubernetes
        tags: runner2 # 태그명은 기존과 다르게 설정해야 됨
      runners:
        config: |
          [[runners]]
            [runners.kubernetes]
              namespace = "{{.Release.Namespace}}"
              image = "alpine"
              privileged = true
      securityContext:
        allowPrivilegeEscalation: true
        readOnlyRootFilesystem: false
        runAsNonRoot: true
        privileged: true

      2) helm 설치할 때 "RELEASE name"을 변경

      helm install --namespace gitlab-runner-2-fvalues2.yaml gitlab/gitlab-runner


      7. 연동 확인

      Gitlab-Runner를 생성하면 토큰 기반으로 Gitlab에서 runner가 있는지 확인합니다.

      아래 처럼 GitLab에 UI로 접속하여 Assigned project runners에 내가 만든 runner 옆에 초록색 불이 들어왔는지 확인하여 잘 연동 되었는지를 확인합니다.

      3.png


      GitLab CI 연동 스크립트 작성 (.gitlab-ci.yaml)

      Gitlab Runner를 통해 이제 실제 소스 프로젝트를 빌드해 볼 시간입니다. 저는 Maven 기반의 Spring 프로젝트를 이용하여 빌드 테스트를 진행하였습니다.

      1. Giltab CI/CD Variables 추가

      GitLab 프로젝트 접속 > Settings > CI/CD > Variables 'Expand' 클릭

      4.png

      'Add variable' 버튼 클릭

      5.png

      추가해야 할 Variables (AZURE는 사용하시는 레지스트리에 따라 변경)

      1. AZURE_REGISTRY_URL: 컨테이너 레지스트리의 full url

      2. AZURE_LOGIN_TOKEN: 레지스트리 로그인 토큰

      3. MANIFEST_URL: k8s manifest 파일이 저장된 gitlab 경로

      4. MANIFEST_USERNAME: k8s manifest 파일이 저장된 gitlab의 액세스 토큰명

      5. MANIFEST_TOKEN: k8s manifest 파일이 저장된 gitlab의 액세스 토큰값


      2. .gitlab-ci.yaml 작성

      gitlab-runner를 빌드하기 위해서는 프로젝트 소스 최상위 디렉토리에 .gitlab-ci.yaml 파일을 생성해야 합니다.

      이 gitlab-ci.yaml을 잘 작성하는 것이 매우 중요한데요.

      yaml을 작성할 때의 주요 전략과 각 라인이 의미하는 바를 정리했으니 한 번 읽어보시고 적용 해보시면 좋을 것 같습니다.

      주요 전략
      1. stage는 'package' 단계와 'build and push and k8s_manifest_update' 단계로 나눔

      2. 원래는 하나의 단계로 합치려고 했으나 maven package 하는 것은 maven image에서 진행하고 나머지는 docker image에서 진행하기 위해 2개의 stage로 분리

      3. package 단계에서는 mvn 빌드를 하고 결과 아티팩트(jar)를 PVC로 shared storage에 저장

      4. build and push and k8s_manifest_update 단계에서는 해당 jar를 가지고 도커 빌드한 후 생성된 image를 ACR에 업로드

      5. mvn package 부분이 원래 dockerfile 안에 있었으나 gitlab-ci.yaml로 바깥으로 뺀 이유는 mvn 빌드할 때 필요한 의존성 라이브러리를 shared volume에 caching하기 위함

      6. 빌드 속도 개선을 위해 mvn 명령어에 일부 옵션 추가

      stages:
        - package
        - build and push and k8s_manifest_update
      
      variables:
        IMAGE: "${CI_PROJECT_NAME}"
        TAG: "${CI_PIPELINE_ID}"
        AZURE_REGISTRY_URL: "$AZURE_REGISTRY_URL"
        AZURE_REGISTRY_PASSWORD: "$AZURE_LOGIN_TOKEN"
        MANIFEST_URL: "$MANIFEST_URL"
        MANIFEST_USERNAME: "$MANIFEST_USERNAME"
        MANIFEST_TOKEN: "$MANIFEST_TOKEN"
        MAVEN_OPTS: "-Dmaven.repo.local=/mnt/share/.m2/repository"
          
      cache:
        key: $CI_COMMIT_REF_SLUG
        paths:
          - /mnt/share
      
      package:
        stage: package
        image: maven:3.8.4-openjdk-17-slim
        script:
          # maven 빌드 결과물(jar)을 Shared 저장소에 업로드
          - mvn -T 1C -f pom.xml clean package -Dmaven.test.skip -DskipTests -Dmaven.javadoc.skip=true
          - rm -rf /mnt/share/target
          - mkdir /mnt/share/target
          - cp ./target/$IMAGE-0.0.1-SNAPSHOT.jar /mnt/share/target/$IMAGE-0.0.1-SNAPSHOT.jar
          - echo 'package script end!'
        only:
          - develop
          - stage
          - live
      
      build and push and k8s_manifest_update:
        image: docker:24.0.5
        stage: build and push and k8s_manifest_update
        services:
          - name: docker:dind
            command: ["--tls=false"]
        before_script:
          - |
            if [[ "$CI_COMMIT_REF_NAME" == "develop" ]]; then
              echo "branch: develop"
              export ENV="dev"
            elif [[ "$CI_COMMIT_REF_NAME" == "staging" ]]; then
              echo "branch: staging"
              export ENV="stg"
            elif [[ "$CI_COMMIT_REF_NAME" == "main" ]]; then
              echo "branch: main"
              export ENV="live"
            else
              echo "Unsupported branch: $CI_COMMIT_REF_NAME"
              exit 1
            fi
        variables:
          DOCKER_HOST: tcp://docker:2375
          DOCKER_TLS_CERTDIR: ""
        script:
          # ACR 로그인
          - echo [LOGIN] ACR LOGIN START
          - echo $AZURE_REGISTRY_PASSWORD | docker login $AZURE_REGISTRY_URL -u token --password-stdin
          - echo [LOGIN] ACR LOGIN SUCCESS
          - echo "ENV ${ENV}"
      
          # Docker 빌드 & ACR PUSH
          - echo [BUILD] 'build start'
          - mv /mnt/share/target .
          - docker build -t "$IMAGE:$TAG" .
          - echo [BUILD] 'build success!'
          - docker tag "$IMAGE:$TAG" "$AZURE_REGISTRY_URL/$IMAGE/${ENV}/$IMAGE:$TAG"
          - echo [PUSH] 'push start'
          - docker push "$AZURE_REGISTRY_URL/$IMAGE/${ENV}/$IMAGE:$TAG"
          - echo [PUSH] 'push success!'
      
          # k8s manifest git 접속 & Clone
          - apk add --no-cache git
          - git config --global user.name "${GITLAB_USER_NAME}"
          - git config --global user.email "${GITLAB_USER_EMAIL}"
          - git clone https://$MANIFEST_USERNAME:$MANIFEST_TOKEN@$MANIFEST_URL
          - cd <manifest 프로젝트 이름>
      
          # docker image 버전 최신화 및 PUSH
          - sed -i "s/$IMAGE:.*\$/$IMAGE:$TAG/g" $IMAGE/${ENV}/deployment.yaml
          - git add $IMAGE/${ENV}/deployment.yaml
          - git commit -m "[UPDATE] $IMAGE $TAG image versioning"
          - git push origin main
          - echo 'build and push and K8S Manifest Update script end!'
        only:
          - develop
          - stage
          - live
      .gitlab-ci.yaml 각 라인 설명
      • variables:

        • IMAGE: "${CI_PROJECT_NAME}" ← 프로젝트명 (Gitlab 기본 환경변수)

        • TAG: "${CI_PIPELINE_ID}" ← PipelineId (Gitlab 기본 환경변수)

        • AZURE_REGISTRY_URL: "$AZURE_REGISTRY_URL"

        • AZURE_REGISTRY_PASSWORD: "$AZURE_LOGIN_TOKEN"

        • MANIFEST_URL: "$MANIFEST_URL"

        • MANIFEST_USERNAME: "$MANIFEST_USERNAME"

        • MANIFEST_TOKEN: "$MANIFEST_TOKEN"

        • MAVEN_OPTS: "-Dmaven.repo.local=/mnt/share/.m2/repository" ← maven local repository 경로 (설정 시 maven 빌드할 때 이 경로가 의존성 repo로 사용됨)

      • cache:

        • key: $CI_COMMIT_REF_SLUG ←Gitlab 기본 환경변수로 브랜치명의 lowercase 버전 (예: develop)

        • paths:

          • /mnt/share ← cache가 저장되는 경로

      • package:

        • stage: package ← stage 이름은 최상단의 stages에서 리스트로 열거한 이름과 동일해야 함

        • image: maven:3.8.4-openjdk-17-slim ← package 단계의 image

        • script: # maven 빌드 결과물(jar)을 Shared 저장소에 업로드

          • mvn -T 1C -f pom.xml clean package -Dmaven.test.skip -DskipTests -Dmaven.javadoc.skip=true

            • 속도 개선을 위해 추가한 명령어

              • T -1C: 다중 스레드 사용 (-T 1C는 Maven이 사용 가능한 코어당 하나의 스레드를 사용함을 의미)

              • Dmaven.test.skip -DskipTests: 테스트 생략

              • Dmaven.javadoc.skip=true: javadoc 생성 건너띄기

          • rm -rf /mnt/share/target ← 아티팩트를 저장할 target 폴더 삭제

          • mkdir /mnt/share/target ← target 폴더 재생성

          • cp ./target/$IMAGE-0.0.1-SNAPSHOT.jar /mnt/share/target/$IMAGE-0.0.1-SNAPSHOT.jar ← shared storage에 아티팩트 jar 저장

        • only: ← only 절이 있으면 해당 브랜치에서만 stage가 작동 (develop,  stage, live)

      • build and push and k8s_manifest_update:

        • image: docker:24.0.5 ← build/push/manifest_update 하는 단계는 docker image에서 수행

        • stage: build and push and k8s_manifest_update ← stage 이름은 최상단의 stages에서 리스트로 열거한 이름과 동일해야 함

        • services:

          • name: docker:dind ← 실제 서비스는 dind(docker in docker) image에서 수행

          • command: ["–tls=false"] ← Is the docker daemon running? 에러 해소를 위해 필요 (아래 참고)

        • before_script: ← 이 아래 절은 브랜치에 따라 env를 설정하는 구문 - | if [[ "$CI_COMMIT_REF_NAME" == "develop" ]]; thenecho "branch: develop"export ENV="dev"elif [[ "$CI_COMMIT_REF_NAME" == "staging" ]]; thenecho "branch: staging"export ENV="stg"elif [[ "$CI_COMMIT_REF_NAME" == "main" ]]; thenecho "branch: main"export ENV="live"elseecho "Unsupported branch: $CI_COMMIT_REF_NAME"exit 1fi

        • variables:

          • DOCKER_HOST: tcp://docker:2375

          • DOCKER_TLS_CERTDIR: ""

        • script:

          • ACR 로그인

            • echo $AZURE_REGISTRY_PASSWORD | docker login $AZURE_REGISTRY_URL -u token --password-stdin ← ACR 로그인 명령어

          • Docker 빌드 & ACR PUSH

            • mv /mnt/share/target . ← target 폴더 통째로 이동 (이 때 shared storage에서 삭제됩니다.)

            • docker build -t "$IMAGE:$TAG" . ← 도커 컨테이너로 빌드

            • docker tag "$IMAGE:$TAG" "$AZURE_REGISTRY_URL/$IMAGE/${ENV}/$IMAGE:$TAG" ← ACR에 PUSH할 이름으로 이미지 태그 설정

            • docker push "$AZURE_REGISTRY_URL/$IMAGE/${ENV}/$IMAGE:$TAG" ← ACR에 PUSH

          • k8s manifest git 접속 & Clone

            • apk add --no-cache git ←

            • git config --global user.name "${GITLAB_USER_NAME}"

            • git config --global user.email "${GITLAB_USER_EMAIL}"

            • git clone https://$MANIFEST_USERNAME:$MANIFEST_TOKEN@$MANIFEST_URL ← Git Clone

            • cd <manifest 프로젝트명>

          • docker image 버전 최신화 및 PUSH

            • sed -i "s/$IMAGE:.*$/$IMAGE:$TAG/g" $IMAGE/${ENV}/deployment.yaml ← deployment.yaml에서 이미지 버전 변경

            • git add $IMAGE/${ENV}/deployment.yaml

            • git commit -m "[UPDATE] $IMAGE $TAG image versioning" ← git commit

            • git push origin main ← git push

        • only: ← only 절이 있으면 해당 브랜치에서만 위 stage가 작동

      Reference

      • GitLab에서 기본적으로 정의되어 있는 환경변수: https://allroundplaying.tistory.com/55

      • maven m2 repository 캐싱: https://sh970901.tistory.com/138


      3. 빌드 속도 개선

      앞에서 말씀드린 것과 같이 maven 기반 Spring 프로젝트의 빌드 시간이 꽤 오래걸렸습니다. (처음 4분 44초)

      이것을 최종 11초로 빌드 시간을 단축 하였는데요, 아래와 같은 방법으로 진행하였습니다.

      • 최초 빌드 시간

      7.png

      • 메이븐 의존성 라이브러리 캐시 이후 (여기서 드라마틱하게 감소)

      8.png

      • maven 옵션 중 테스트 및 javadoc 생성 skip 처리 (-Dmaven.test.skip -DskipTests -Dmaven.javadoc.skip=true)

      9.png

      • 다중 스레드 사용 (-T 1C)

      10.png

      Reference


      4. Gitlab Project 관련 추가 설정

      Gitlab과 Gitlab-runner를 연동할 때, Gitlab UI를 통해서 프로젝트 관련 설정의 일부를 변경해주어야 연동이 가능합니다.

      1) "Run untagged jobs"에 체크

      gitlab 접속 → Settings → CI/CD → Runners 'Expand' 클릭 → Assigned project runners에서 수정(연필모양) 버튼 클릭 → "Run untagged jobs"에 체크 후 저장

      11.png

      2) 빌드하기를 원하는 branch(예: develop, staging, main)를 'protected branch'로 설정

      gitlab 접속 → Settings → Repository → Protected branches 'Expand' 클릭 → Add protected branch

      12.png


      5. 빌드

      develop 브랜치에서 commit하고 push하면 자동으로 Gitlab-runner에서 빌드가 구동 됨

      빌드가 시작되면 Gitlab 좌측 탭에서 Build > Pipelines를 클릭하면 실행되는 Pipeline을 볼 수 있음

      13.png

      #으로 시작하는 Pipeline ID를 클릭하면 빌드 진행상황을 자세히 볼 수 있음

      14.png

      돌아가고 있는 stage를 클릭하면 상세 로그를 확인할 수 있음

      드디어 빌드 성공!

      17.png


      6. 확인

      1. Azure Portal에 접속해서 ACR(Azure Container Registry)에 이미지가 잘 저장되었는지 확인

        docker login ACR -> docker image ls로 확인

      2. ArgoCD 접속해서 APP DIFF로 manifest 파일의 도커이미지 버전 변경됨을 확인

      16.png


      GitLab Runner 연동 할 때 발생했던 에러와 대응 방법

      Gitlab Runner 연동할 때 생각보다 많은 에러가 발생했습니다. 많은 try&error(라고 읽고 삽질이라 씀..)를 통해 빌드를 성공할 수 있었는데요..

      발생했던 에러들 어떻게 해결 했는지 공유드립니다.

      1) This job is stuck because the project doesn't have any runners online assigned to it.Go to project CI settings 에러

      해결: values.yaml 안에 있는 image를 docker에서 alpine으로 변경 후 재 설치

      runners:
        config: |
          [[runners]]
            [runners.kubernetes]
              namespace = "{{.Release.Namespace}}"
              image = "alpine" <- 이 부분 수정. ubuntu도 가능. docker는 안됨
              privileged = true

      2) ERROR: Job failed (system failure): prepare environment: setting up credentials: secrets is forbidden: User "system:serviceaccount:gitlab:default" cannot create resource "secrets" in API group "" in the namespace "gitlab". 에러

      해결: gitlab 접속 → runner edit → "Run untagged jobs"에 체크 후 저장

      3) 31flag needs an argument: 'p' in -p 에러

      $ docker login -u token -p $AZURE_LOGIN_TOKEN $AZURE_REGISTRY_URL

      해결: ci.yaml 파일에서 variable로 선언한 뒤 스크립트에서 사용하도록 변경하니 에러 해결!

      4) Error: Cannot perform an interactive login from a non TTY device 에러

      $ echo $AZURE_REGISTRY_PASSWORD | docker login $AZURE_REGISTRY_URL -u token --password-stdin

      원인: test 하던 develop 브랜치에 protected 설정이 안 되어 있었음

      해결: develop 브랜치를 protected 브랜치로 설정하니까 문제 해결

      5) Get "https://registry-1.docker.io/v2/": unauthorized: incorrect username or password 에러

      원인: privileged가 기본적으로 false로 되어 있어 true로 설정해주어야 함

      해결: values.yaml에 privileged: true 추가 후 해결

      runners:
        config: |
          [[runners]]
            [runners.kubernetes]
              namespace = "{{.Release.Namespace}}"
              image = "alpine"
              privileged = true <- 이 부분
      securityContext:
        allowPrivilegeEscalation: true
        readOnlyRootFilesystem: false
        runAsNonRoot: true
        privileged: true <- 이 부분

      6) ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 에러

      가장 해결하기 어려웠던 문제. 해결하기 위해 Runner의 구조 부터 파악.

      1. 우선 gitlab 공식 홈페이지에서 gitlab-runner 설정하는 방법에 대해 확인

        https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor

      2. 주요 팩터 1: executor

        gitlab-runner가 build할 때 어떤 방식으로 실행하느냐인데, docker, shell, kubernetes 중에서 선택 가능. 우리는 kubernetes를 사용할 수 있으므로 kubernetes로 선택

      3. 주요 팩터 2: runner의 image

        gitlab-runner가 build할 runner를 띄울 때 image를 정의할 수 있는데 기본값인 alpine 사용

      4. 주요 팩터 3: ci.yaml에서 service에 docker를 실행시키는 방법 정의

        dind (Docker in Docker)를 사용하느냐, 일반 docker socket을 사용하느냐 결정할 수 있음

        두 개의 장단점은 링크에서 확인 가능 https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/

      공식홈페이지에서 알려준대로 똑같이 설정해도 계속 Is the docker daemon running? 에러 발생하였고 문제에 대해 search하던 중 비슷한 사례를 발견했습니다.

      https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27300

      그 중 "Ilya Frolov" 의 답변을 읽고 적용 해 봤는데요. 원인과 해결방안은 아래와 같습니다.

      원인: docker:dind v20은 TLS를 명시적으로 비활성화하지 않으면 16초 동안 잠자고, 이로 인해 빌드 컨테이너가 dockerd 컨테이너보다 일찍 시작되는 경쟁 상태가 발생하는 것을 확인.

      이 경우 루프백 주소에 연결하면 즉시 오류가 발생하지만, 네트워크 주소에 간접적으로 연결하면 dockerd가 잠자기를 기다리는 활성 프로브로 작동함.

      도커가 데몬의 시작 속도를 늦춰 TLS 인증을 강제하려는 시도가 있음. 따라서 명시적으로 tls=false 설정을 하여 TLS 인증을 우회하도록 설정

      해결: gitlab-ci.yaml에 아래 내용 추가

        services:
          - name: docker:dind
            command: ["--tls=false"]


      마치는 글

      상세하게 작성하다 보니 길이 많이 길어졌네요.. Gitlab Runner 핵심 절차를 요약하자면 아래와 같습니다.

      • Gitlab-runner Helm Chart로 설치 (k8s)

      • Gitlab Token으로 Runner 연결

      • .gitlab-ci.yaml 파일 작성하여 Spring 프로젝트를 Runner에서 빌드

      • 빌드 속도 단축을 위해 maven 의존성 캐싱 및 멀티 스레드 처리

      GitLab Runner로 CI/CD를 구성하는 분께 조금이나마 도움이 되셨길 바라며 마치겠습니다. 감사합니다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      dragonpipe 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기