정글에서 온 개발자

웹앱 Delivery 자동화. Github Action - Self Hosted Runner 본문

카테고리 없음

웹앱 Delivery 자동화. Github Action - Self Hosted Runner

dev-diver 2024. 11. 22. 17:37

도입 이유

  • 기존의 local build → zip 파일을 호스팅 서버로 ftp 전송 → 압축 풀기 → systemctl 실행 의 프로세스를 단축하는 배포 자동화를 구축하고자 함
  • 버전별 아카이빙 혹은 추후 버전 롤백을 염두해 호스팅 서버가 ‘버전 스토리지’ 역할도 할 수 있도록 구성하고자 함 (docker image 스토리지 등으로도 사용 가능)

구성 후 사용 방법

  • git push 나 PR merge 등으로 배포하고 싶은 git 버전을 구성
  • 레포지토리의 Actions에 들어가서 자동 워크플로우 이름 → Run workflow → Run workflow를 클릭
  • 배포 완료 후 호스팅 서버에 접속하여 sudo systemctl restart server 실행
  • 이제 github에 올라간 새로운 버전이 호스팅 서버에서 돌아간다.

Github Action이란?

  • github에서 어떤 이벤트가 발생했을 때, 해당 이벤트를 트리거로 어떤 명령이 일어나도록 할 수 있음.
    • 예를 들어 go build, ng build 를 하도록 할 수 있음
  • 기본적으로 Github Hosted Runner 라는 깃허브에서 제공하는 서버 위에서 코드가 돌아가는 구조
  • 이에 반해  Self Hosted Runner 는 개인이 자체적으로 운영하는 서버에서도 github action이 돌아가도록 하는 서비스다.

Github Action을 사용한 배포

  • 빌드 속도가 호스팅하는 서버의 성능을 탐.

장점

  • github의 이벤트와 연계하기 쉬움 (push, pr merge 등 이벤트에 트리거 가능)
  • 초기 설정이 직접 배포 신호를 받는 서버를 구성할 때보다 쉬움
  • github action에서 제공해주는 UI로 빌드 상태를 모니터링하기 편함

단점

  • github 외의 플랫폼에서의 동일한 워크플로우를 사용하기 어려움
  • 자주 사용하면 비용이 발생할 수도 있음

Self Hosted Runner를 사용했을 때

장점

  • github hosted runner 는 매번 새로운 상태를 구성해 시간도 오래 걸리고, docker image등을 만들 때 기존의 레이어를 활용하기 힘듬.
  • self hosted runner는 이와 달리 최적화를 하기 더 편함
    • github hosted runner도 10GB 까지는 캐싱을 지원하지만, 비용이 발생할 수 있음
  • 빌드를 호스팅 하려는 서버에서 직접 하기 때문에, 빌드 이후에 전송하는 과정이 필요 없음

단점

  • 호스팅하는 서버가 필요함
  • 호스팅 서버의 스토리지를 일정 부분 차지함

구성 과정

github runner용 계정 생성

  • 계정명을 github-runner로 할 때
sudo adduser github-runner #계정 생성
sudo passwd github-runner #비밀번호 설정
sudo usermod --shell /bin/bash github-runner #터미널 bash로 변경
# 이후 github runner로 로그인

github runner 설치

  • Settings > Actions > Runners로 이동
  • New self hosted runner를 눌러 새로운 러너 추가
  • 설치하려는 시스템 선택 (현재 Linux, x86)
  • 선택시 나오는 코드를 호스트 서버에 입력
$ mkdir actions-runner && cd actions-runner
# Download the latest runner package
$ curl -o actions-runner-linux-x64-2.320.0.tar.gz -L <https://github.com/actions/runner/releases/download/v2.320.0/actions-runner-linux-x64-2.320.0.tar.gz>
# Optional: Validate the hash
$ echo "93ac1b7ce743ee85b5d386f5c1787385ef07b3d7c728ff66ce0d3813d5f46900  actions-runner-linux-x64-2.320.0.tar.gz" | shasum -a 256 -c
# Extract the installer
$ tar xzf ./actions-runner-linux-x64-2.320.0.tar.gz
  • 설정 코드 입력
# Create the runner and start the configuration experience
$ ./config.sh --url <https://github.com/dev-diver/server> --token <토큰>
# Last step, run it!
$ ./run.sh
  • 이후 run.sh를 서비스로 등록하여 관리 가능

github action 서비스로 등록 (옵션)

  • /etc/systemd/system 에 github-runner.service로 저장
[Unit]
Description=GitHub Actions Runner
After=network.target

[Service]
ExecStart=/path/to/actions-runner/run.sh
WorkingDirectory=/path/to/actions-runner
Restart=always
User=github-runner
Group=github-runner

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload # 새 서비스 인식시키기
sudo systemctl start github-runner # 서비스 시작

action yaml 파일 작성

.github/workflows/액션이름.yaml 로 저장

아래와 같은 간단한 걸 테스트 해볼 수도 있고

on:
  workflow_dispatch:

jobs:
  test:
    runs-on: self-hosted
    steps:
      - name: Create a file
        run: echo "Hello, World!" > testfile.txt

      - name: List directory contents
        run: ls -la

      - name: Read the file
        run: cat testfile.txt

go 와 angular로 구성했다면 아래 workflow를 변형해서 써도 된다.

name: Build & Archive

on:
  workflow_dispatch:

jobs:
  service_build:
    runs-on: self-hosted

    steps:
      # github 소스 다운로드
      - name: Checkout code
        uses: actions/checkout@v3

      # go 빌드
      - name: Add Go to PATH
        run: |
          export PATH=$PATH:/usr/local/go/bin
          echo "PATH updated for Go"
          go version

      - name: Build Go application
        run: |
          go mod tidy
          go build -o server .

      # 앵귤러 빌드
      - name: Install Angular dependencies
        run: npm install
        working-directory: web_src

      - name: Build Angular application
        run: npx ng build
        working-directory: web_src

      # 서비스용 파일 이동
      - name: Prepare build artifacts
        run: |
          mkdir -p dist
          mv ./server dist
          mv ./web dist/web

      # 아카이브
      - name: Compress build artifacts
        run: |
          DATESTAMP=$(date '+%Y-%m-%d_%H-%M-%S')
          ARCHIVE_NAME="dist_$DATESTAMP.tar.xz"
          tar -cJvf $ARCHIVE_NAME dist/
          mkdir -p ../versions
          mv $ARCHIVE_NAME ../versions/

push 후 실행

  • Build and Compress → Run workflow → Run workflow를 클릭

github의 화면 변화
호스팅 서버의 화면 변화

실행 결과

test용을 실행했을 때, 지정한 git runner의 work 디렉토리에 txt 파일이 잘 생성됐다면 성공한 것이다.

go, angular 워크플로우를 실행했을 때 에러가 난다면 다음을 참고하면 된다.

실행 전 체크 , error fix

  • workflow가 안 보임
  • → repository의 settings에서 default branch를 workflow 파일이 있는 브랜치로 지정
  • 오랜시간이 지났는데 실행이 대기중인 경우→ 호스트 서버의 runner가 잘 실행 되고 있는지 확인

  • go: command not found
    nano ~/.bashrc
    
    export PATH=$PATH:/usr/local/go/bin  #를 파일 끝에 입력후 저장
    
    source ~/.bashrc
    
  • → go 프로그램을 못 찾아서 발생하는 오류. go를 github-runner 계정에 설치해주거나, 시스템에 깔려있는 go의 path를 등록
  • nvm: command not found
  • → node가 다운로드 되지 않았거나 환경변수로 잡혀 있지 않음. 위와 같은 방법으로 해결

개선 점

npm install 시 계속 새로 받아오는 문제가 있다. 셀프 호스팅의 장점을 살려 이미 받은 패키지들은 다시 받지 않도록 설정이 필요하다.

이후 단계

스토리지 서버는 도커 이미지를 만들기 위한 발판이 될 수 있다.
각 버전별로 아카이빙 대신 도커 이미지를 만들어 놓고, 운영 서버에 이미지를 제공해 쉽게 배포할 수 있다.
이런 방법을 쓰면 이후 kubernetis 도입시에 편할 것으로 보이고 self hosted의 장점을 살리면 공통 레이어는 공유되기 때문에 이미지 저장 크기도 많이 아낄 수 있다.