GitHub-hostedライクにAmazon ECSとAWS Lambdaでself-hosted runnerを管理するツールを作った
こんにちは、whywrite.it CI班のwhywaitaです。
この記事は AWS Lambda と Serverless Advent Calendar 2023 4日目の記事です。
普段は株式会社サイバーエージェントという会社でGitHub Actions向け self-hosted runner 基盤の開発者兼PdMをやっています。業務としてはプライベートクラウドと呼ばれる社内向けのクラウド基盤を開発しつつ、その上で稼働する安価に拡張性の高いCI基盤を提供しています。
そこで利用しているコアソフトウェアが whywaita/myshoes です。GitHubから送信されるwebhookをベースに毎回クリーンアップされたself-hosted runnerを作成・登録するツールです。
類似のソフトウェアで最も有名なものに actions/actions-runner-controller というものがあるのですが、ソフトウェア自体とrunnerの実行環境がKubernetes上に限定されていることに対して、myshoesは動作環境も自由(Go製のバイナリをポン置きでOK)、runnerの作成環境も動的に差し替えることが可能(providerアーキテクチャを取って別バイナリで切替)なことが利点です。
基本的には社内で利用するために開発を進めていましたが、ふとインターネットを漁っているとこんな記事を見つけました。
Amazon ECS Task上で比較的簡易にself-hosted runnerを起動させることができるようです。これは良さそう。というわけでインスパイアされ出来たのが今回ご紹介する whywaita/myshoes-serverless-aws です。
アーキテクチャについて
大枠については前述したCookpadさんのブログ記事を大きく踏襲しているのですが、一部異なる部分やそれぞれの環境でカスタマイズ可能な部分もあるので(重複も許容しつつ)ご紹介します。
リポジトリ名のとおりフルサーバレスで動作するように実装されています。タイトルにもあるとおりAWS Lambdaを用いてイベントを受け取り、Amazon SQSでキューイング、AWS LambdaがECS Taskを実行するオーソドックスなアーキテクチャです。1度設定さえしてしまえば基本的にはほぼノーメンテナンスで動作することを想定しています。
また、前述したとおりproviderアーキテクチャを採用することでrunnerの実行環境は自由にカスタマイズすることができます。Amazon ECS on Fargate や on EC2 であれば whywaita/shoes-ecs-task を利用することができますし、EC2の上で動作させたLXD上であれば whywaita/shoes-lxd-multi なども利用可能です(社内で利用しています)。 Terraformのプラグインモデルで利用されている hashicorp/go-plugin を利用しているのでgRPCを喋ることのできる言語ならなんでも実装できます。
Amazon ECSを利用する場合でも、実行するrunnerのDocker imageやTaskのサイズ、Security Groupを切り替えたい場合などもあるでしょう。runnerを利用しているSecurity Group内部で実行させることでセキュアなデプロイを実現することができますし、GitHub-hosted Large runnerよりも大きなサイズを必要なときに利用することもできます。(しかも、Spot Instanceの価格で!)
ちなみにCookpadさんでは runs-on で記載されたラベルをベースにOverride することで実現しているようです。実現は可能なアーキテクチャになっているので、今後の shoes-ecs-task の課題ですね。
お試し方法
ここまで聞いたあなたはぜひ試したい気持ちでいっぱいになっていることかと思います。そんな方のために全てをエイヤで作るTerraformのサンプルを用意しています。
GitHub Appsの設定なども含めてドキュメントに記載してある(つもり)ので、ぜひご利用いただければと思います。もし分かりにくいなどあればぜひXやIssueなどでご連絡ください。
おまけ: 内部実装について
前述もしましたが self-hosted runner を良い感じに作成するコアの実装については whywaita/myshoes のほうにあり、 whywaita/myshoes-serverless-aws 側にはAWS LambdaやSQSのドライバーとしての実装ぐらいしか書かれていません。clocコマンドで見ると分かりやすいですが全部ひっくるめてもGoのファイルが4つで400行程度というコンパクトさ。
$ cloc . 21 text files. 16 unique files. 14 files ignored. github.com/AlDanial/cloc v 1.98 T=0.02 s (873.5 files/s, 53775.2 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- Go 4 76 4 411 HCL 1 31 2 162 XML 5 0 0 109 Markdown 3 33 0 65 make 1 11 0 27 PlantUML 1 7 0 24 YAML 1 1 0 22 ------------------------------------------------------------------------------- SUM: 16 159 6 820 -------------------------------------------------------------------------------
また他のクラウドでも書いてみようかと思いますね。
謝辞
本ソフトウェアのインスピレーション元となったCookpadさんと筆者の @s4ichi さん、また CI/CD Test Night #6 にて「self-hosted runnerを動的に生成することを生業にしているメンバー」というあまりにニッチな人々を集めてくれた @Kesin11 さんにお礼申し上げます。