エクサウィザーズ Engineer Blog

株式会社エクサウィザーズのエンジニアチームブログ

GitHub Actions の self-hosted runners を AWS ECS で動かして、CI / CD パイプラインを作る

f:id:tadashi-nemoto0713:20201019135904p:plain

DevOps エンジニアの 根本 征 です。

7月からエクサウィザーズ にジョインし、CI / CD パイプラインの改善や自動テストの布教などを行っています。

今回は GitHub Actions の self-hosted runners を AWS ECS 上に構築し運用してみたので、その試行錯誤について紹介したいと思います。

GitHub Actions と self-hosted runners

GitHub Actions は GitHub ユーザーであれば現在多くの方がご存知・ご活用されているかと思います。

GitHub Marketplace で公開されている Actions と組み合わせることによって、簡単に様々な CI / CD パイプラインを構築することができます。

そんな GitHub Actions ですが、GitHubが提供する Runner を使う代わりに自前で用意することもできます(self-hosted runners)。

セルフホストランナーについて - GitHub Docs

GitHub が提供する Runner で GitHub Actionsを利用する場合、無料利用枠 + 従量課金の課金体制になります。

しかし、self-hosted runners で GitHub Actions を利用する場合には別途料金がかかることはありません。

Repository または Organization の設定からself-hosted runners をセットアップすることができます(Linux / MacOS / Windows 毎に手順が示されます)。

f:id:tadashi-nemoto0713:20201016201036p:plain

セットアップが完了すると、Runner として追加されていることが確認できます。

Repository で設定した Runner はその Repository で、そして Organization で設定した Runner はその Organization 内の全ての Repository で実行することができます。

f:id:tadashi-nemoto0713:20201016201348p:plain

最後に GitHub Actions の設定ファイルにおいて、self-hosted runners で実行することを記述します。

f:id:tadashi-nemoto0713:20210325114741p:plain

self-hosted runners はマシン自体は自分たちで調達・メンテナンスをしないといけないですが、ワークフローを管理する部分(Jenkins でいう master)を自前で用意せず無料で利用できる点は魅力的だと感じます。

self-hosted runners を Docker で動かす

self-hosted runners 自体はオープンソースとして公開されていますが、現在 Docker イメージは提供されていません。

調べたところ、Docker・Kubernetes で self-hosted runners 動かすためにオープンソースプロジェクトで様々な試行錯誤が行われているみたいです。


本記事では AWS ECS をメインに下記の手順で解説します。

  1. self-hosted runners を Docker で動かす

  2. self-hosted runners を AWS ECS で動かす

  3. その self-hosted runners を用い、アプリケーションを AWS ECS にデプロイするパイプラインを作る


まず下記の Docker イメージを使い、手元で self-hosted runners を立ち上げてみます。

github.com

Organization に対して Runner を立ち上げるためには下記 docker コマンドを実行します。

f:id:tadashi-nemoto0713:20210325114821p:plain

GitHub Actions では Docker の操作(ビルドなど)を行うため、このコンテナ内でも Docker コマンドが使えることが必要になります。

そのため、ホストマシン上の Docker daemon を共有することで解決しています(-v /var/run/docker.sock:/var/run/docker.sock の部分、Docker outside of Docker)

Using Docker-in-Docker for your CI or testing environment? Think twice.

self-hosted runners を AWS ECS で動かす

次に先ほどの Docker イメージを使って、AWS ECSで動かしてみます。

今回は AWS CDK(Typescript) をベースに3つのポイントに絞って解説します。


1つ目に AWS ECS で Docker outside of Docker(DooD) をどう実現するかについてです(-v /var/run/docker.sock:/var/run/docker.sockの部分)。

AWS ECS だと Task 側に Volume を追加し、Container 側にその Volume をマウントすることで解決することができます。

f:id:tadashi-nemoto0713:20210325114902p:plain

f:id:tadashi-nemoto0713:20210325114933p:plain

AWS ECS では起動タイプとして Fargate と EC2 がありますが、現状 Fargate で上記を行うことがサポートされていなかったため、今回はEC2起動タイプを選択しました。


2つ目に ECS Task に与える Role についてです。

今回の GitHub Actions 上でのパイプラインでは、Docker ビルド ・ECRへのイメージのアップロード・ECSへのデプロイまで行おうとしています。

もちろん GitHub 側に AWS アクセスキーを保存し、それを GitHub Action に渡すことで上記を実現することができます。

しかし、self-hosted runners のコンテナ自体に上記に必要な Role を与えることによって、GitHub側に AWS アクセスキーを保存する必要自体をなくすことができます。

f:id:tadashi-nemoto0713:20210325115036p:plain


3つ目に、スポットインスタンスについてです。

self-hosted runners は CI / CD として使うため、スポットインスタンスを活用してコストを抑えることができます。

AWS CDK の場合、spotInstanceDraining プロパティを true にすることでスポットインスタンスを利用することができます。

f:id:tadashi-nemoto0713:20210325115131p:plain

アプリケーションを AWS ECS へデプロイする Workflow を作る

今回はこの GitHub Actions と self-hosted runners を活用して、アプリケーションを AWS ECS へデプロイする Workflow を作りたいと思います。

同じ AWS ECS なのでややこしくなってしまいますが、self-hosted runners を動かすクラスタとアプリケーションを動かすクラスタは別という想定です。

f:id:tadashi-nemoto0713:20201020153820p:plain

具体的には下記のような手順になります。

Docker build して ECR にPushする
↓
Task Definition ファイルを編集する(Dockerイメージの部分を新しくする)
↓
Task Definition を新たに登録し、Service が更新されるまで待つ

AWSで提供されている GitHub Actions の Step と組み合わせると下記のようになります。

f:id:tadashi-nemoto0713:20210325115227p:plain

先ほども述べましたが、本来は aws-actions/configure-aws-credentials の Step で下記のように AWS アクセスキーを GitHub に保存し渡してあげる必要があります。

f:id:tadashi-nemoto0713:20210325115303p:plain

しかし、今回は self-hosted runners に必要な権限を渡してあげているのでこの必要はありません。

おわりに

今回はGitHub Actions の self-hosted runners を AWS ECS 上に構築してみましたが、下記のような状況でメリットがあると考えています。

  • GitHub Action を使ってアプリケーションをAWSへデプロイする際、GitHub 側に不必要に AWS アクセスキーを渡したくない

  • スポットインスタンスや活用することによって、コストパフォーマンスよく CI / CD 環境を運用したい(特に無料枠を大幅に超えることが予想される場合)

  • GitHub が提供する Runner よりスペックの高いマシンで CI / CD 環境を運用したい


今後、この GitHub Actions をベースにより良い CI / CD パイプラインが作れたら良いと考えています。


hrmos.co