🍎

Tartelet を使って macOS の GitHub Actions self-hosted runner を動かす

2024/12/15に公開

GitHub Actions では、自前の環境でジョブを実行できる self-hosted runner 機能が提供されています。

また、iOS アプリのビルドなど一部のジョブは macOS でしか実行できないものがありますが、この self-hosted runner を macOS で動かして運用する際は Linux と比べて色々と面倒なところがあります。その辺を Tartelet という OSS がいい感じにしてくれるということで調査&検証してみたのでその結果をまとめます。

https://github.com/shapehq/tartelet/

self-hosted runner とは

GitHub Actions のジョブを自前で用意した環境上で実行するための仕組みです。github.com 版では GitHub-hosted のランナーが利用可能なため、多くの場合自前の環境は不要です。ただし、以下のようなケースでは self-hosted runner の使用が必要となります。

  • 独自でジョブで必要なツールをプリインストールしたい場合
  • セキュリティ上の理由で自前の環境でジョブを実行したい場合
  • GitHub Enterprise Server を使用している場合(GitHub-hosted runner は github.com でのみ利用可能)

macOS で self-hosted runner を立てる際のポイント

macOS 環境での self-hosted runner の運用 (macOS に限らないものもありますが) には、以下のような考慮点があります。

仮想化について

ホストマシン上で直接ランナーのプロセスを動かすと、ジョブ間で相互に影響を与えたり、データが共有されてしまう問題が発生します。この問題を防ぐため、Linux 環境ではコンテナや Amazon EC2 などの仮想マシン(以下、VM)上でジョブを実行することが組織レベルの運用では一般的です。

macOS の場合、仮想化には VM の利用が必要ですが、クラウドサービスで手軽に利用できる環境は限られています。そのため、物理マシンを自前で管理し、その上に VM を構築する必要が出てきます。Apple 公式の Virtualization Framework を使用して macOS VM を構築できますが、設定は複雑で、Swift/Objective-C での実装が必要となります。

https://developer.apple.com/documentation/virtualization

UTM などのツールを使用すると、VM をより簡単に扱えますが(UTM は内部で Virtualization Framework を使用)、それでもランナーが稼働する VM の作成や起動・停止は手動管理が必要になります。

self-hosted runner のセットアップについて

macOS に限らず、self-hosted runner のセットアップには以下の手順が必要です。

  1. self-hosted runner のバイナリのダウンロード
  2. self-hosted runner の登録と起動
    • ランナー登録用のトークンを GitHub から取得し、ランナーに設定する

VM 上でランナーを動作させる場合は、VM 起動後にこれらの手順を実行する必要があります。

Tartelet とは

https://github.com/shapehq/tartelet/

Tartelet は、Tart という macOS の仮想化ツールをベースに、GitHub Actions のランナーを VM 上で効率的に実行するための mac アプリです。Tartelet を使用することで、前述した macOS ランナー運用の課題を解決できます。

Tartelet の主な特徴は以下の通りです。

  • ベース VM から Clone を作成し、ジョブごとにクリーンな環境を提供
  • ジョブ完了後に VM を自動的に破棄し、新しい VM を起動して新しいランナーをセットアップ
  • ランナーのラベル設定やベース VM の編集などを GUI で簡単に設定可能

以下の記事に Tartelet の開発背景が詳しく記載されています。

https://shape.dk/news-and-knowledge/tartelet

Tartelet の仕組み

Tartelet は以下の流れで動作します[1]

  1. Tartelet をホストマシン上で起動すると、Tart を使用してベース VM から Clone を作成
  2. Clone した VM を起動し、SSH 経由でランナーのセットアップを実行
    1. GitHub App 認証を使用して Registration Token を取得
    2. ephemeral ランナーとして VM 上でランナーを起動
  3. ランナーが GitHub からジョブを取得して実行
  4. ジョブ完了後、ランナープロセスが終了
  5. ランナー終了を検知して VM がシャットダウン
  6. VM のシャットダウンを(SSH 切断により)検知したホストマシンの Tartelet が VM を破棄し、新しい VM を Clone して起動

この仕組みにより、各ジョブはクリーンな環境で実行され、ジョブ間の干渉を防ぐことができます。また、VM の作成から破棄までが自動化されているため、運用の手間を削減できます。

詳細として、動作の流れを以下に示します。

内部で使用されている Tart は、前述した Apple 公式の Virtualization Framework を使用して VM の管理を行っています。macOS の仮想化ツールは商用のものが多くソースコードを公開していないものが多いため、Tart は Virtualization Framework を使用した macOS の仮想化ツールの実装例として参考になりそうです。

https://github.com/cirruslabs/tart

Tartelet を使ってみる

Tartelet を使用して macOS の self-hosted runner を構築・実行する手順を説明します。基本的に以下の Tartelet Wiki に従って進めます。

https://github.com/shapehq/tartelet/wiki#-getting-started

1. 必要なツールのインストール

https://github.com/shapehq/tartelet/wiki/Installing-Tartelet

まず、上記 Wiki に従って Tartelet とその依存ツールである Tart をインストールします。

Tart は Homebrew からインストール可能です。

$ brew install cirruslabs/cli/tart

Tartelet は GitHub の Releases から ZIP(Tartelet.zip)をダウンロードして解凍し、~/Applications に配置します。

2. 初期設定

https://github.com/shapehq/tartelet/wiki/Configuring-Tartelet

Tartelet は GitHub App 経由でランナーの登録を行うため、まず GitHub App を作成する必要があります。以下の通り、Repository レベルか Organization レベルで必要な権限が異なるので注意が必要です。

  • Repository レベルのランナーを作成する場合
    • Administration(Read and Write)
    • Repository: Metadata(Read-only)
  • Organization レベルのランナーの場合
    • Organization: Self-hosted runners(Read and write)の権限を付与

次に、Tartelet の GUI から、ランナーの並列実行数(1 または 2[2])や GitHub App の秘密鍵登録など必要な設定を行います。以下は主に操作することになる VM 設定画面、GitHub 設定画面、ランナー設定画面です。

VM設定画面
VM 設定

GitHub設定画面
GitHub 設定

ランナーの設定画面
ランナー設定

その後、ベースとなる VM をメニューバーの「Edit Virtual Machine」から起動して初期設定を行います。macOS の基本設定(ユーザーアカウント作成、言語設定など)を行います。

3. 開発ツールのプリインストール

https://github.com/shapehq/tartelet/wiki/Configuring-the-Virtual-Machine-to-Build-iOS-Apps

ベース VM に対して、ジョブで必要となるツールを事前にインストールしておくことで、ジョブ実行のたびにインストールする必要がなくなり、実行時間を短縮できます。

4. ランナーの起動と動作確認

設定完了後、Tartelet の GUI から「Start」をクリックすることで、ランナーが VM 上で自動的に起動します。

これでランナーがジョブを待ち受ける状態になりました。GitHub Actions のワークフローで runs-on に、Tartelet 上で設定したラベルを指定することで、起動したランナー上でジョブを実行できます。以下のように自動で VM 上で起動されたターミナル上でランナーが起動し、ジョブを待ち受ける状態になっています。

Tartelet を扱う際の注意点

Tartelet の使用にあたって、以下の点に注意が必要です。

ライセンスについて

Tartelet 自体は MIT ライセンスですが、依存している Tart は Fair Source License となっています。この Fair Source License では、利用する環境の CPU コア数の合計が 100 を超える場合、ライセンス費用が発生します。

2024 年 12 月現在、最も低価格な Gold Tier($1,000/月) では 500 コアまで利用可能です。そのため、大規模な環境での導入を検討する場合は、必要なマシン数とコア数を考慮してライセンスコストを見積もる必要があります。

GitHub Enterprise Server 対応について

現時点では、github.com のみをサポートしており、GitHub Enterprise Server(GHES)には対応していません。IssuePR を見ると、メンテナが GHES 環境でのテストを行えず、動作確認はコミュニティに頼っていることからなかなかマージまで辿り着かないようです。

GUI での設定が必要

Tartelet は mac アプリであるため、設定は GUI で行う必要があり、CLI での設定や操作ができないため、自動化やスクリプト化が難しいという制約があります。数台程度のマシン運用であれば大きな問題はなさそうですが、大規模な環境での運用を考える場合は注意が必要です。

まとめ

Tartelet は、macOS での self-hosted runner の構築と運用におけるいくつかの課題を解決するツールです。VM の管理やランナーのセットアップを自動化することで、運用の手間を大幅に削減できます。

一方で、初回セットアップやベース VM の更新には手作業が必要な部分が残っており[3]、また Tart のライセンス形態や GHES 未対応といった制約もあります。組織での導入を検討する際には、これらの点を踏まえる必要があります。

脚注
  1. Tartelet の実際の挙動とソースコード(Swift)から確認しています。 ↩︎

  2. macOS のライセンスにより、ひとつのマシン上で同時に起動できる VM は最大 2 つまでとなっています。 ↩︎

  3. macOS 初期設定に関しては Tart CLI を利用した Packer Template で自動化できるみたいですが試せていません、、 ↩︎

Discussion