LoginSignup
3
1

GitHub Actionsをどこでも!self-hosted runnersがアツかった

Last updated at Posted at 2023-12-03

はじめに

こちらは長野高専 Advent Calendar 2023 4日目の記事です!
@shun-shobon さんが開催するNNCTアドカレもこれで3回目の参加ですね〜。現在後続の主催者を探しているみたいなので、来年度以降も在籍予定の方はぜひ!

自己紹介

卒業してしまった身なので書いておきます!
18sで昨年電子情報工学科を卒業したBony_Chopsと申します!現在は大学に3年次編入して、各所でインターン等々をやっています。

宣伝

同日付で別のアドカレ記事を書いているので、ぜひそちらもご覧ください!以下の記事ではこの記事の内容を実際に使っています。

前置き

突然ですが皆さんはGitHub Actionsを使っていますか? GitHubに高度にインテグレートされたActionsは2018年にリリース1されて以来、その手軽さから様々なCI/CDに取り込まれていきました。
そんなActionsですが、実は持ち前の環境でも実行できることをご存知でしたか?「あーはいはい、actのことでしょ?」と思ったそこのあなた、実はGitHubが公式に提供する仕組みがあります!それが、self-hosted runnersです。

actself-hosted runnersは似ていますが、両者趣旨が異なるものです。

  • act: ローカルでActionsをテストする
  • self-hosted runners: GitHubで実行されるActionsの環境の一つとして任意の環境を使えるようにしたもの

self-hosted runners

前述しましたが、self-hosted runnersはGitHubで実行されるActionsの環境の一つとして任意の環境を使えるようにしたものです。つまり...

image.png

一見普通のGitHub Actionsに見えると思いますが、

image.png

これ全部自前環境で動かしました

メリット

自前で発動させられるActionsには、次のようなメリットがあります。

  • 自前IPでリクエストを飛ばせる
    • ワークフローによっては外部にアクセス/リクエストを通したい、けどgithub.comから出るリクエストだとアクセスできない...みたいなケースがあると思います。self-hostedを使えば、そういった制限を回避できます。
  • ケースによっては格段にフローを早くできる
    • 大きいモデル等を使ってビルドしている、みたいなケースのとき、それを落とすのにすごい時間がかかることがあると思います。self-hostedはインストールされた環境でそのまま動くため、環境に予めモデルを置いておけば、モデルをダウンロードする時間をスキップできます
  • レートリミットを回避できる
    • フローがどれほど時間がかるものであっても、持ち前の環境の電気代やらを負担すれば良いだけなので、気兼ねなく重めのフローを組めます
  • ポート開放不要
    • 後述するセットアップ方法を見ればわかるとおり、設定がめちゃくちゃ楽ですポート開放が不要なので、自分みたいに集合住宅に住んでいる民でも使うことができます(とても嬉しい)。

セットアップ

「セットアップ、大変なんでしょ」というそこのあなた!設定はめちゃくちゃ楽です。

後述しますが、self-hostedはDocker環境ではないので、フローを試す際は気をつけてください。実行するコマンドは実行環境に直接影響します2
不安な方は後述のDocker化をお試しください。

リポジトリのSettings -> Actions -> Runnersに移動します

image.png

使いたいOSとアーキテクチャを選択します。もちろんM1(macOS arm64)やラズパイ4-(Linux arm64)にも対応してますし、Linux armに対応しているのでラズパイZeroや3などでも(おそらく)実行できます。
Windowsを選べるのも、人によってはかなりありがたいんじゃないでしょうか。
image.png

あとは表示されているコマンド郡を実行すればOKです。登録用のTOKENも含まれているので、実行するだけで勝手にアカウントにひも付きます。
image.png

最後に、使いたいWorkflowのruns-onを書き換えれば完了です。

  jobs:
    node-build-and-deploy:
-     runs-on: ubuntu-latest
+     runs-on: self-hosted

Docker化3

前述した通り、self-hosted runnersはデフォルトだと環境でそのままコマンドを実行します。それだと困るという人もいると思うので、Docker化していきます。

以下はLinux arm64での例です。それ以外の人は #セットアップ で提示されるコマンド郡を参考に直してください^^;

Docker環境でのLinux arm64ですので、アーキテクチャが同じ人(ラズパイ4-, Apple Siliconなど)はそのまま使えます。

Dockerfile
FROM ubuntu:22.04

RUN apt-get update && \
    apt-get install \
    curl \
    expect \
    jq \
    ssh \
    rsync \
    gettext-base \
    -y

# Linux arm64向け、それ以外の人は #セットアップ で提示されるコマンド郡を参考に直してください^^;
RUN mkdir actions-runner && cd actions-runner && \
    curl -o actions-runner-linux-arm64-2.311.0.tar.gz -L \
    https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-arm64-2.311.0.tar.gz && \
    echo "5d13b77e0aa5306b6c03e234ad1da4d9c6aa7831d26fd7e37a3656e77153611e  actions-runner-linux-arm64-2.311.0.tar.gz" | sha256sum -c - && \
    tar xzf ./actions-runner-linux-arm64-2.311.0.tar.gz && \
    ./bin/installdependencies.sh

COPY exec-runner.sh /actions-runner/exec-runner.sh
RUN chmod +x /actions-runner/exec-runner.sh
WORKDIR /actions-runner

CMD ["/actions-runner/exec-runner.sh"]

デフォルトでは1フローを実行したらコンテナを停止/削除する設定になっているため、不要であればexec-runner.sh内の--ephemeralを削除してください

exec-runner.sh
#!/bin/bash

# repo scopeのあるアクセストークン
if [ -z "${GITHUB_ACCESS_TOKEN}" ]; then
  echo "GITHUB_ACCESS_TOKEN must be set" 1>&2
  exit 1
fi

if [ -z "${GITHUB_API_DOMAIN}" ]; then
  echo "GITHUB_API_DOMAIN must be set" 1>&2
  exit 1
fi

if [ -z "${GITHUB_DOMAIN}" ]; then
  echo "GITHUB_DOMAIN must be set" 1>&2
  exit 1
fi

if [ -z "${GITHUB_REPOSITORY_NAME}" ]; then
  echo "GITHUB_REPOSITORY_NAME must be set" 1>&2
  exit 1
fi

if [ -z "${GITHUB_REPOSITORY_OWNER}" ]; then
  echo "GITHUB_REPOSITORY_OWNER must be set" 1>&2
  exit 1
fi

# ランナー設定用トークンを取得する
export GITHUB_RUNNER_REGISTRATION_TOKEN=$(curl \
    -X POST \
    -H "Accept: application/vnd.github+json" \
    -H "Authorization: Bearer $GITHUB_ACCESS_TOKEN" \
    -H "X-GitHub-Api-Version: 2022-11-28" \
    https://$GITHUB_API_DOMAIN/repos/$GITHUB_REPOSITORY_OWNER/$GITHUB_REPOSITORY_NAME/actions/runners/registration-token \
    | jq .token | sed -e 's/"//g')

export RUNNER_ALLOW_RUNASROOT=1
runnerName=`hostname`

# config.shを実行する
# 不要であれば--ephemeralを消してください
expect -c "
set timeout 10
log_user 0
spawn ./config.sh --url https://${GITHUB_DOMAIN}/${GITHUB_REPOSITORY_OWNER}/${GITHUB_REPOSITORY_NAME} --token ${GITHUB_RUNNER_REGISTRATION_TOKEN} --ephemeral
log_user 1
expect  -re \"Enter the name of the runner group to add this runner to:.*\"
send \"\n\"
expect  -re \"Enter the name of runner:.*\"
send \"${runnerName}\n\"
expect  -re \"Enter any additional labels.*\"
send \"\n\"
expect  -re \"Enter name of work folder:.*\"
send \"\n\"
expect \"#\"
exit 0
"

./run.sh

GITHUB_ACCESS_TOKENは、Settings -> Developer Settings -> Personal Access Tokens -> Fine-granted TokensからRepository permissions
AdministrationActionsを付加したTokenを生成して適用してください

.env
GITHUB_ACCESS_TOKEN=(token)
GITHUB_REPOSITORY_OWNER=(repository owner name)
GITHUB_REPOSITORY_NAME=(repository name)
GITHUB_DOMAIN=github.com
GITHUB_API_DOMAIN=api.github.com
# ビルド
docker build -t self-hosted-runner .
# 起動
docker run --rm -it --env-file=./.env self-hosted-runner

家のRaspberry Piで実行

家に転がっていたRaspberry Pi 3, 4と、ブラックフライデーで分裂させた4で起動させてみました...と言いたいのですが、設定が間に合わず現状3のみで実行しています^^; (遅い^^;)

↑ここで実際に使っています。

結論4

今年7月にActions runner controller(runners k8s管理)がGAになった5そうなので近いうちにそっちも試したいな〜
みんなもself-hosted runnersを使ってCI/CDの可能性を広げよう。

  1. https://github.blog/2018-10-16-future-of-software/

  2. 自分はこれを知らずに実行し、(WorkflowにSSHの設定を弄るものが含まれていたため)~/.ssh/configが吹き飛んで絶望しました

  3. https://note.com/shift_tech/n/n199fd81ce315

  4. 自分の記事は毎回締まりが悪いなと感じていましたが、毎回結論がないなということに気づいたので、若干適当ですが書くようにしました。

  5. https://github.blog/changelog/2023-06-30-github-actions-actions-runner-general-availability/

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1