はじめに
こちらは長野高専 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です。
self-hosted runners
前述しましたが、self-hosted runnersはGitHubで実行されるActionsの環境の一つとして任意の環境を使えるようにしたものです。つまり...
一見普通のGitHub Actionsに見えると思いますが、
これ全部自前環境で動かしました。
メリット
自前で発動させられるActionsには、次のようなメリットがあります。
-
自前IPでリクエストを飛ばせる
- ワークフローによっては外部にアクセス/リクエストを通したい、けどgithub.comから出るリクエストだとアクセスできない...みたいなケースがあると思います。self-hostedを使えば、そういった制限を回避できます。
-
ケースによっては格段にフローを早くできる
- 大きいモデル等を使ってビルドしている、みたいなケースのとき、それを落とすのにすごい時間がかかることがあると思います。self-hostedはインストールされた環境でそのまま動くため、環境に予めモデルを置いておけば、モデルをダウンロードする時間をスキップできます
-
レートリミットを回避できる
- フローがどれほど時間がかるものであっても、持ち前の環境の電気代やらを負担すれば良いだけなので、気兼ねなく重めのフローを組めます
-
ポート開放不要
- 後述するセットアップ方法を見ればわかるとおり、設定がめちゃくちゃ楽です。ポート開放が不要なので、自分みたいに集合住宅に住んでいる民でも使うことができます(とても嬉しい)。
セットアップ
「セットアップ、大変なんでしょ」というそこのあなた!設定はめちゃくちゃ楽です。
後述しますが、self-hostedはDocker環境ではないので、フローを試す際は気をつけてください。実行するコマンドは実行環境に直接影響します2。
不安な方は後述のDocker化をお試しください。
リポジトリのSettings -> Actions -> Runnersに移動します
使いたいOSとアーキテクチャを選択します。もちろんM1(macOS arm64)やラズパイ4-(Linux arm64)にも対応してますし、Linux armに対応しているのでラズパイZeroや3などでも(おそらく)実行できます。
Windowsを選べるのも、人によってはかなりありがたいんじゃないでしょうか。
あとは表示されているコマンド郡を実行すればOKです。登録用のTOKENも含まれているので、実行するだけで勝手にアカウントにひも付きます。
最後に、使いたい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など)はそのまま使えます。
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
を削除してください
#!/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
のAdministration
とActions
を付加したTokenを生成して適用してください
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の可能性を広げよう。
-
自分はこれを知らずに実行し、(WorkflowにSSHの設定を弄るものが含まれていたため)
~/.ssh/config
が吹き飛んで絶望しました ↩ -
自分の記事は毎回締まりが悪いなと感じていましたが、毎回結論がないなということに気づいたので、若干適当ですが書くようにしました。 ↩
-
https://github.blog/changelog/2023-06-30-github-actions-actions-runner-general-availability/ ↩