GitHub Actions のセルフホステッドランナーを AWS で動かす際のインフラ構成選定

GitHub Actions のセルフホステッドランナーを AWS で動かす際のインフラ構成選定

掲題を選定したときの調査メモです。備忘として。

前提 #

  • CI として GitHub Actions を使用している。
  • GitHub Actions はセルフホステッドランナーで AWS 上で動かす。
  • 大規模開発の CI である。
    • 1日に数万〜数十万件のジョブ(=ランナー)が実行される。
    • ジョブの実行時間は最長で数時間に及ぶものもある。
  • Action のなかには jobs.<job_id>.container 指定を使用するものもある。そのため Docker in Docker (DinD) が実行できる環境が必要である。
  • AWS の費用は可能な限り低く抑えること。

選択肢 #

No. コントロールプレーン データプレーン データプレーンのスケーリング  GitHub からのジョブ取得 判定 メモ
1 EKS on EC2 / self-managed nodes Cluster Autoscaler ARC 🔺1 後発の managed node groups のほうが上位互換
2 Karpenter ARC 🔺1 後発の managed node groups のほうが上位互換
3 on EC2 / managed node groups Cluster Autoscaler ARC 🔺1 後発の Karpenter のほうが上位互換
4 Karpenter ARC ⭕️ 採用
5 on Fargate 自動 ARC ❌️ Fargate は Docker の privileged = true が不可であり DinD 不可
6 Auto Mode 自動 ARC 🔺2 機能は Karpenter と同等だが追加料金がかかる(EC2 の料金が約 12% 増し)
7 Hybrid Nodes ❌️ オンプレ用なので検討対象外
8 ECS on EC2 / self-managed nodes Cluster Auto Scaling ARC 🔺2 EKS Karpenter のほうが bin packing が働くため費用が安く済む
9 Managed Instances 自動 ARC 🔺2 機能は EKS Karpenter と同等だが追加料金がかかる(EC2 の料金が約 12% 増し)
10 on Fargate 自動 ARC ❌️ Fargate は Docker の privileged = true が不可であり DinD 不可
11 Anywhere ❌️ オンプレ用なので検討対象外
12 CodeBuild EC2 自動 自動 ⭕️
13 Lambda 自動 自動 ❌️ Lambda の最大実行時間 15 分まで
14 独自で実装する EC2 独自で実装する 独自で実装する(Runner Scale Set Client を用いる) ⭕️
15 Lambda 独自で実装する 独自で実装する(Runner Scale Set Client を用いる) ❌️ Lambda の最大実行時間 15 分まで

用語補足 #

メモ #

  • 「EKS on EC2 / self-managed nodes」:自分で個別に EC2 を作成してクラスタに登録する。基本的には自分で EC2 Auto Scaling Group(ASG)を定義しておき、そこで生成される EC2 をクラスタに参加させるという形をとる。現在この選択肢を積極的に採用する理由はなく、managed node groups を使うのが良い。
  • 「EKS on EC2 / managed node groups」:EKS が自動で ASG を作成してくれる。その ASG が作成した EC2 がクラスタに登録される。
  • 「EKS or ECS on Fargate」:サーバレス
  • 「EKS Auto Mode」:実質的には「EKS on EC2 / managed node groups & Karpenter」をワンセットにして提供してくれているもの。ただし Auto Mode を利用することで追加料金がかかることに注意。
  • 「EKS Hybrid Nodes」:オンプレミスのノードを EKS のクラスタに登録する。
  • 「ECS on EC2 / self-managed nodes」:EKS の「EKS on EC2 / self-managed nodes」相当
  • 「ECS on EC2 / ECS Managed Instances」:EKS の「EKS Auto Mode」相当
  • 「ECS Anywhere」:EKS の「EKS Hybrid Nodes」相当

選定 #

最終的に「No.4 - EKS on EC2 / managed node groups & Karpenter」を採用することとした。

ステップ1:機能要件を満たさない構成の除外 #

機能要件を満たさない構成は判定欄に「❌️」を記載した。判定理由はメモ欄を参照。

ステップ2:下位互換にあたる構成の除外 #

下位互換にあたる構成は判定欄に「🔺1」を記載した。判定理由はメモ欄を参照。

ステップ3:費用比較で劣後する構成の除外 #

同等の機能を実現できる構成同士で比較したときに、費用面で劣る(高くなる)構成は判定欄に「🔺2」を記載した。判定理由はメモ欄に記載。

ステップ4:最終選定 #

ここまでで残った、選択肢が「⭕️」となっている以下の3つから検討する。

  • No.4:EKS on EC2 & Karpenter
  • No.12:CodeBuild on EC2
  • No.14:独自実装コントロールプレーン on EC2

まずは「No.4:EKS on EC2 & Karpenter」と「No.12:CodeBuild on EC2」で優位な選択肢を決める。

両者では CPU、メモリ等のリソースサイズの区切り方に違いが出る。

前者の場合、Karpenter の bin packing の仕組みにより、好きな粒度でリソースをジョブに割り当てることが可能である。あるジョブには 1 CPU を、あるジョブには 6 CPU を、といった具合である。

後者は bin packing の仕組みは用いない。1ジョブ =1つの EC2 インスタンスという関係になる。つまり CPU の区切り方は AWS が用意しているインスタンスタイプに従う。

たとえば CPU では、EC2 の CPU サイズは、1, 2, 4, 8, 16 … といった区切りで用意されている。(参考:AWS EC2 m9g インスタンスタイプ一覧 - なお、m9g 以外でも CPU サイズの区切り方は同じである)

あるジョブにとっては 6 CPU が必要十分なリソースサイズだとしても、EC2 のインスタンスタイプの区切りに従って、8 CPU のインスタンスを使うことになる。

より必要十分なリソース割り当て(=費用最適化)が可能になるのは前者であるため、前者を優位と判断した。

最後に「No.14:自前実装」だが、自前実装の目指すものは結局のところ「No.4:EKS on EC2 & Karpenter」と同等である。要するに単なる車輪の再発明になることから自前で実装する意義がなく、すでにパッケージ化されているものを使用するほうが得策である。

「No.4 - EKS on EC2 / managed node groups & Karpenter」を採用する。

参考:GitHub Actions で EKS & Karpenter を使っている事例 #

EKS on EC2 & Karpenter #

EKS Auto Mode #