gitlab-runner 여러 빌드 서버 구성하기 (Mac os x 추가)

junto·2024년 6월 16일
0

devops

목록 보기
6/9
post-thumbnail

gitlab-runner 여러 빌드 서버 구성하기

현재 Ubuntu 빌드 서버가 있고, CI-CD를 구축한 상태이다. 그런데 로컬 빌드 서버가 왜 필요할까? 빌드 서버가 aws ec2 freetier이기 때문에 CPU는 1코어, 스왑 메모리를 제외한 기본 메모리 1기가이다. 자동적으로 실행되는 건 좋지만, 버그가 생기거나 특정 시간에 빌드가 몰리면 굉장히 답답하다. 현재 Compile → Test → Build → Deploy 파이프라인이 있고, 완료되는 데 대략 5분~8분정도 걸린다.

M1에서 로컬로 빌드하면 1분이 채 안 걸린다! 하지만, 이 과정이 정말 순조롭지 않았다. 이제는 뚝딱하겠지만, 한 번 되기까지 삽질한 과정을 공유한다.

삽질한 시간까지 생각하면, 로컬로 빌드를 백 번 이상 해야 본전이다ㅎ_ㅎ..

Macos에서 gitlab-runner 실행하기

  • 기존 우분투 서버 환경과 환경 변수 및 설치되어 있는 의존성 위치가 다르다. dind(docker in docker)를 이용해 빌드 환경을 맞춰줄 수도 있지만, 이미 로컬에 필요한 의존성이 있고 빠르게 빌드하는 게 목표이기에 별도로 빌드 환경을 구축하지 않는다.

1. Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

  • 도커를 실행하기 위해선 리눅스가 필요하다. 단순히 docker를 설치하는 것만으로는 부족하다. 꼭 도커 데스크탑을 설치하여 경량 리눅스 VM위에서 도커 데몬을 사용할 수 있어야 한다.

2. must use ASL logging (which requires CGO) if running as root Error saving credentials: error storing credentials - err

  • build stage에서 root로 도커 로그인할 때 발생한 에러이다.
  • macos에서 root로 도커를 사용할 때 ASL 로깅, 자격 인증 시스템 설정을 해주어야 한다고 한다. 보안상 docker를 root 사용자가 아닌 계정으로 사용하는 방법을 선택했다.
sudo gitlab-runner run 
gitlab-runner run // 변경

3. 올바른 gitlab-runner tag를 등록했지만, 트리거되지 않음

  • 위에선 모두 sudo gitlab-runner run 명령어를 통해 root 권한으로 gitlab-runner가 실행되었고, 따라서 docker 또한 root 권한으로 실행되었다.
  • docker를 일반 유저로 실행하기 위해 gitlab-runner run 명령어를 사용했는데, 올바르게 서버가 설정되어 있음에도 반응이 없었다.

1) gitlab-runner Run untagged job 선택

  • 아래 스택오버플로우 답변에 gitlab 설정에서 위의 설정을 체크하면 트리거가 된다고 했는데, 나에겐 효과가 없었다.

https://stackoverflow.com/questions/56153664/gitlab-runner-listen-address-not-defined-error

2) /etc/gitlab-runner/config.toml 및 builds/ 권한 주기

  • 디버깅해 보니 config.toml 설정 파일을 아예 읽지를 못했다. 그 이유는 기본적으로 root 권한을 가진 사용자만 /etc/gitlab-runner/config.toml에 접근할 수 있었기 때문이다. 추가로 builds/ 경로에서 빌드 작업을 하게 되는데, 이 또한 root 사용자만 접근할 수 있다.
sudo chmod 755 /etc/gitlab-runner/config.toml
sudo chown ${USER} /etc/gitlab-runner/config.toml

sudo chmod -R 755 builds/
sudo chown -R ${USER} builds/
  • config.toml을 복사해서 gitlab-runner run -c ~/config.toml 실행할 때 지정할 수도 있다.

3) gitlab-runner 실행할 때 사용 권한 처음부터 변경하기 (macos)

  • 하지만, 위 방식은 깔끔하지 않다. 깃 저장소에서 파일이 추가될 때 root 권한으로 만들어지기 때문에 builds/ 에 있는 파일의 권한을 수정하지 않으면 파이프라인에서 실패하게 된다.
  • /Library/LaunchAgents/gitlab-runner.plist에서 설정을 아래와 같이 추가하면, gitlab-runner가 실행될 때 사용하는 계정을 지정할 수 있다. 해당 계정으로 파일이 새로 만들어진다.
<key>UserName</key>
<string>$USER</string>

Macos에서 Build한 이미지를 우분투 AMD/64 서버에 배포하기 (docker buildx)

이미지 호환 문제(ARM64 - AMD64)

  • 이미지를 빌드하고 서버에서 해당 이미지를 실행할 때 아래와 같은 에러가 뜬다. 즉, 빌드할 때는 ARM64 아키텍처로 이미지가 빌드되었지만, 실행하는 서버는 Ubuntu Amd64라 발생하는 문제이다.

  • WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64/v3) and no specific platform was requested

docker run --privileged --rm tonistiigi/binfmt --install all
docker buildx build --platform linux/amd64 -t $IMAGE_NAME:$IMAGE_TAG . 

빌드 머신이 환경 변수로 지정이 안 되는 문제

  • 처음엔 tags를 환경 변수로 설정하고 싶었는데, tags에 $BUILD_MACHINE 처럼 환경 변수로 지정하면 아래처럼 트리거 되지 않는다.

  • 그러면 어떻게 특정 러너를 실행할 수 있을까? rules if 를 사용하여 트리거할 로컬 머신을 설정할 수 있다. YAML 앵커 문법을 사용하면 <<: * 상속받을 부모를 정할 수 있어서 재사용성이 좋아진다.

  • 아래는 YAML 앵커 문법으로 기존 빌드 스크립트에 Mac os x 빌드 머신을 추가한 것이다.

variables:
  IMAGE_NAME: jinyhehe/spacestory
  IMAGE_TAG: $CI_COMMIT_SHA

stages:
  - compile
  - test
  - build
  - deploy

.compile_template: &compile_template
  stage: compile
  script:
    - gradle build --exclude-task test

compile_juny:
  <<: *compile_template
  before_script:
    - export PATH="/home/ubuntu/.sdkman/candidates/gradle/current/bin:$PATH"
  tags:
    - juny
  rules:
    - if: '$BUILD_MACHINE == "juny"'

compile_junylocal:
  <<: *compile_template
  tags:
    - juny-local
  rules:
    - if: '$BUILD_MACHINE == "juny-local"'

.test_template: &test_template
  stage: test
  script:
    - gradle build --exclude-task test

test_juny:
  <<: *test_template
  before_script:
    - export PATH="/home/ubuntu/.sdkman/candidates/gradle/current/bin:$PATH"
  tags:
    - juny
  rules:
    - if: '$BUILD_MACHINE == "juny"'

test_junylocal:
  <<: *test_template
  tags:
    - juny-local
  rules:
    - if: '$BUILD_MACHINE == "juny-local"'

.build_template: &build_template
  stage: build
  before_script:
    - cat $SPRING_ENV > src/main/resources/env.yml

build_juny:
  <<: *build_template
  image: docker:26.1.3
  services:
    - docker:26.1.3-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - echo $DOCKER_REGISTRY_PASS | docker login --username $DOCKER_REGISTRY_USER --password-stdin
    - docker build -t $IMAGE_NAME:$IMAGE_TAG .
    - docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:latest
    - docker push $IMAGE_NAME:$IMAGE_TAG 
    - docker push $IMAGE_NAME:latest
  tags:
    - juny
  rules:
    - if: '$BUILD_MACHINE == "juny"'

build_junylocal:
  <<: *build_template
  script:
    - cat $DOCKER_FILE > Dockerfile
	- gradle build --exclude-task test
    - docker login
    - docker run --privileged --rm tonistiigi/binfmt --install all
    - docker buildx build --platform linux/amd64 -t $IMAGE_NAME:$IMAGE_TAG -t $IMAGE_NAME:latest --push .
  tags:
    - juny-local
  rules:
    - if: '$BUILD_MACHINE == "juny-local"'

.deploy_template: &deploy_template
  stage: deploy
  before_script:
    - chmod 400 $SSH_KEY
    - mkdir -p ~/.ssh
    - ssh-keyscan -H 13.125.206.46 >> ~/.ssh/known_hosts
  script:
    - ssh -i $SSH_KEY ubuntu@13.125.206.46 "echo $DOCKER_REGISTRY_PASS | docker login --username $DOCKER_REGISTRY_USER --password-stdin && docker rm spring-app -f || true && docker pull $IMAGE_NAME:latest && docker run -d -p 8080:8080 --name spring-app --network juny $IMAGE_NAME:latest"

deploy_juny:
  <<: *deploy_template
  tags:
    - juny
  rules:
    - if: '$BUILD_MACHINE == "juny"'

deploy_junylocal:
  <<: *deploy_template
  tags:
    - juny-local
  rules:
    - if: '$BUILD_MACHINE == "juny-local"'

ETC: Gradle daemon disappeared unexpectedly

  • Mac os X에서 docker-dind로 빌드 환경을 구축해서 도커 멀티 플랫폼 이미지를 만들고 싶었지만, 실패했다. 위 에러가 계속 발생했는데, 구글링해서 나온 여러 방법들을 적용해봤지만 내게는 불통이었다.
// gradle.properties

org.gradle.daemon=false
org.gradle.jvmargs=-Xmx4096m
  • docker-dind 뿐만 아니라 Dockerfile 멀티스테이징 빌드할 때(gradle-openjdk 이미지 사용) gradle 빌드에서도 계속 위의 오류가 발생했다.
  • docker run --privileged --rm tonistiigi/binfmt --install all qemu provider와 gradle 호환성 문제가 발생한 거라고 생각한다. 많은 시간 들였는데 해결하지 못해서 아쉬운 부분이다.

참고 자료

profile
꾸준하게

0개의 댓글

관련 채용 정보