概要

GitHub Actions self-hosted runnerの仕組みが面白く突貫でECS on Fargateを作ってみたときのメモ。 Step FunctionsでのECS Task起動やAPIGatewayとStep Functionsの統合など、一連の作業のなかに色々勉強できるところがあった。

まずはローカルでself-hosted runnerを動かす

self-hosted runnerは非常に簡単に実行できる。まずはローカルをrunnerに指定してみる。

https://docs.github.com/ja/actions/hosting-your-own-runners/managing-self-hosted-runners/adding-self-hosted-runners

ここの手順に従ってtar.gzをダウンロード、解凍しスクリプトを実行するだけ。 この際登録のためのトークンが必要になる。トークンは画面からも取得できるが今後自動化していくのでRESTAPIで取得することになる。

通信設定上の制約やOSの制約があるが、クラウド上のVM上でも同様に動かせる。

https://docs.github.com/ja/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#usage-limits

コスト削減を目的にした場合マシンを立てっぱなしだとあまり意味がない。実行する際に自動でホストを起動して終わったらホストを終了したい。

実行の流れ

構成はこんな感じ。見た目シンプルだけど意外と詰まる。 

  1. ジョブ実行時にWebhookでHTTPリクエストしてくれるので、その向き先をAPI Gatewayにする
  2. API GatewayはStep Functionsのステートマシンを実行する
  3. LambdaでGitHub RESTAPIを叩いてself-hosted runnerとして登録するためのトークンを取得する
    • このときWebhookのペイロードのハッシュ検証も行う
  4. Tokenを取得できたらそれを環境変数としてECSのタスク実行する
  5. ECSタスクはself-hosted runnerに登録しにいく
  6. 登録を確認しだいジョブが実行される
  7. 実行されたら自動的にself-hosted runnerの解除とタスクの終了をしてくれる

作業でつまったところ

詰まったところを書いておく。 APIGatewayをStepFunctionsで受けたことがだいぶことを大変にしている気がしないでもない。 素直にLambdaで統合したほうが楽だった。 Terraformでモジュール化したのでもう迷わないはず。

Dockerイメージを作る

注意する点はrootで実行できないのでrootとユーザーを切り替える必要があるくらい。 config.shはオプションで引数を全部渡してあげればインタラクティブに入力しながら設定しなくて良くなる。 ここで起動時に自動アップデートもできるが、Dockerで定期アップデートすればよいので実施しないオプションをつける。

ECSタスク定義を作る

ECRとタスク定義を作っておく。とくに問題なし。

Lambdaを作る

パーソナルキーをパラメータストアから取得してRESTAPIを実行する。 Webhookの検証もここで行った。サンプルコードがあるのでそのままで動くが文字列をエンコードすることに注意する。

https://docs.github.com/ja/webhooks/using-webhooks/validating-webhook-deliveries

Step Functionsを作る

Lambdaの実行とECSタスクの実行をする。 また、Webhookでqueue以外のアクションがあったときに無視する分岐もここで行う。 Webhookの検証をLambdaで行うがそのままペイロードとして渡してしまうと自動的にオブジェクトに変換されてしまうので、文字列のまま渡すことに注意する。

APIGatewayを作る

Step Functionsと統合するAPIGatewayを作る。 Webhookの検証ではヘッダとボディの両方が必要になるので、マッピングテンプレートで両方渡すようにする。 ここで、inputの値はJSONではなく文字列で渡すことに注意する。