맥북을 Self-hosted Github action runner로 만들기

오늘은 Github action의 runner에 대한 이야기를 하려고 합니다.

글을 쓰기 앞서 잠깐 이야기를 풀자면 제 자동화 환경의 대다수는 Github action으로 동작합니다. Golang과 Ruby로 만들어진 Application 들과 Zest script 들이죠. 다만 Github action의 경우 github의 runner에서 동작하기 때문에 내 서버가 아닌 Github의 서버, 즉 해외에서 동작하게 됩니다. 물론 크게 상관은 없겠지만, 때때로 국내 환경들은 해외 접근에 대해 차단하는 경우가 있어서 정상적으로 동작하지 않습니다.

그래서 지난달에 Self-hosted runner를 세팅했었고 내용을 공유해봅니다.

Self-hosted Runner란?

Self-hosted runner는 Github action이 사용자가 지정한 PC 또는 서버에서 동작할 수 있도록 제공되는 기능입니다. 마치 집에 있는 피씨가 Agent가 되는거죠. 그리고 Self-hosted runner는 Agent가 Listen 하는 형태가 아니라 Agent가 Github 서버쪽으로 접근하는 형태입니다. 그래서 개인 환경을 공인 IP로 노출할 필요가 없는건 정말 좋습니다 :D

Installation actions-runner

설치는 간단합니다. runner 압축 파일을 다운로드 및 압축해제 후 run.sh를 실행하면 runner가 동작합니다.

mkdir actions-runner && cd actions-runner
curl -o actions-runner-osx-x64-2.293.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.293.0/actions-runner-osx-x64-2.293.0.tar.gz
tar xzf ./actions-runner-osx-x64-2.293.0.tar.gz
cd actions-runner
./run.sh

run.sh 실행 시 interactive-shell로 몇가지 설정을 진행합니다. 모두 완료하면 Github repo(Repo > Settings > Actions > Runners)에서 해당 runner를 확인할 수 있습니다.

그리고 등록한 runner는 workflow 파일 작성 시 아래와 같이 runs-on 을 통해 명시하여 사용할 수 있습니다.

  SecretSecret:
    runs-on: macOS
    needs: [Events]
    steps:
    - uses: actions/checkout@v2
    - name: Run Zest
    # ....

Make service(daemon)

svc.sh

매번 Action 실행마다 runner를 켜주는 일은 번거롭습니다. 다행히 run.sh와 동일 경로에 있는 svc.sh 스크립트를 이용해서 OS 별 서비스 등록을 쉽게 진행할 수 있습니다.

./svc.sh install
./svc.sh start

이후에 리부팅 되어도 자동으로 실행하여 Agent가 등록되기 때문에 workflow 구동 시 해당 runner를 사용하게 됩니다. 로그를 보면 Self-hosted runner 가 잘 동작하는 것을 볼 수 있습니다.

사실 세팅 초기에는 svc.sh의 존재를 몰라서 여러가지 방법을 고민 했었습니다. 위 svc.sh 말고도 가능한 방법은 있어 작성해봅니다.

More

로그인 항목

macOS에선 시스템 환경설정 > 사용자 및 그룹 > 로그인 항목 에서 계정 로그인 시 실행할 어플리케이션을 지정할 수 있습니다. 전 그냥 run.sh 를 이곳에 등록하면 해결될 줄 알았으나 문제가 약간 있었습니다.

로그인 항목에 등록된 어플리케이션은 run.sh; exit 형태로 동작하기 떄문에 부팅 시 터미널이 열리며 꺼지지 않는 이슈가 있었습니다. 그래서 백그라운드로 동작시키도록 별도의 sh를 파일을 만들어서 등록했었죠.

/Users/<PATH>/actions-runner/run.sh&
sleep 10

우선 runner 리스트에 idle로 나타났지만, 저의 경우는 실제로 action 동작 시 잘 되진 않았습니다 😭

LaunchDaemons

macOS는 LaunchDaemons, 즉 launchd 라고 해서 daemon을 생성하고 관리할 수 있는 도구를 제공하고 있습니다. 마치 systemctl과 비슷하죠. 그래서 /Library/LaunchDaemons 경로 하위에 관련 plist 파일을 만들어주면 daemon으로 동작시킬 수 있습니다.

폴더 용도
/System/Library/LaunchDaemons Apple 시스템 데몬
/System/Library/LaunchAgents 개별 사용자 기반으로 모든 사용자에게 적용되는 Apple 에이전트
/Library/LaunchDaemons 3rd Party 시스템 데몬
/Library/LaunchAgents 개별 사용자 기반으로 모든 사용자에게 적용되는 3rd Party 에이전트
~/Library/LaunchAgents 로그인된 사용자에게만 적용되는 3rd Party 에이전트

plist 샘플

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>com.testapp</string>
        <key>LimitLoadToSessionType</key>
        <string>Background</string>
        <key>ProgramArguments</key>
        <array>
          <string>실행할 경로</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StartInterval</key>
        <integer>0</integer>
        <key>StandardErrorPath</key>
        <string>/dev/null</string>
        <key>StandardOutPath</key>
        <string>/dev/null</string>
</dict>
</plist>

작성/저장 후 launchctl 명령을 통해 로드합니다.

launchctl load -w ~/Library/LaunchDaemons/com.testapp.plist

이 방법으로 runner를 daemon화 하던 중 svc.sh 를 존재를 알게되어 더 이상의 삽질은 없었네요.

References

  • https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners
  • https://support.apple.com/ko-kr/guide/terminal/apdc6c1077b-5d5d-4d35-9c19-60f2397b2369/mac