정글에서 온 개발자
웹앱 Delivery 자동화. Github Action - Self Hosted Runner 본문
도입 이유
- 기존의 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를 클릭
실행 결과
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의 장점을 살리면 공통 레이어는 공유되기 때문에 이미지 저장 크기도 많이 아낄 수 있다.