APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Actions Runner Controller Deep Dive!- アーキテクチャ編 -

こんにちは!ACS事業部の谷合です。
今日から私の大好物であるGitHub、CI/CD、Kubernetes、Operatorを絡めてシリーズで投稿していこうと思います。

はじめに

皆さん、GitHub Actions使っていますか?
GitHub ActionsとはCI/CDパイプラインをyaml形式で宣言的に定義し、Workflowとしてまとめて実行できるなんとも便利なサービスです。
なんと、GitHub Actionsは全世界で毎月1億3千万以上ものジョブが実行されています!!
すごいですよね!実質CI/CDでのデファクトスタンダードと呼んでもいいのではないでしょうか?

そんなGitHub Actionsですが、実行環境を大きく分けて2つあります。

  • GitHub社がホストするVMのGitHub-hosted runner docs.github.com

  • ユーザが独自にホストする環境(コンテナ含む)のSelf-hosted runner docs.github.com

今回よりご紹介するのは後者で、Kubernetes PodをSelft-hosted runnerとして動作させることができる、GitHub社公式のKubernetes OperatorであるActions Runner Controllerです。 github.com

先日Actions Runner Controllerのコードリーディングをしたので最新の機能であるAutoscaling Runner Scale Setsモードを、今回より以下のように複数回に渡ってシリーズとして紹介していきたいと思います。 なお、Autoscaling Runner Scale Sets mode登場以前のモードはレガシーモードとされていますので、今回はスコープ外とします。

  • アーキテクチャ紹介(今回)
  • インストール方法および動作紹介(次回)
  • 各ControllerのコードレベルでのDeep Dive

アーキテクチャ

Autoscaling Runner Scale SetsモードはGitHub Actionsのジョブ数に応じて、Selft-hosted runnerであるPodを自動スケールさせるJob実行の信頼性を高めるモードです。このAutoscaling Runner Scale Setsモード、実はレガシーモードでも実装されていました。Autoscaling Runner Scale Setsモードが導入されてからは以下の機能追加がなされています。

  • No longer require cert-manager as a prerequisite for installing actions-runner-controller
  • Reliable scale-up based on job demands and scale-down to zero runner pods
  • Reduce API requests to api.github.com, no more API rate-limiting problems
  • The GitHub Personal Access Token (PAT) or the GitHub App installation token is no longer passed to the runner pod for runner registration
  • Maximum flexibility for customizing your runner pod template

また、レガシーモードではスケーリングメトリクスやWebhookを契機にスケールさせていますが、Autoscaling Runner Scale SetsモードではGitHubとロングポーリングを行い、Jobの状態をメッセージとして受け取り、JobAvailableメッセージ受信を契機にスケールさせています。

アーキテクチャは以下の通りとなっています。

  1. ARC is installed using the supplied Helm charts, and the controller manager pod is deployed in the specified namespace. A new AutoScalingRunnerSet resource is deployed via the supplied Helm charts or a customized manifest file. The AutoScalingRunnerSet controller calls GitHub's APIs to fetch the runner group ID that the runner scale set will belong to.
  2. The AutoScalingRunnerSet controller calls the APIs one more time to either fetch or create a runner scale set in the Actions Service before creating the Runner ScaleSet Listener resource.
  3. A Runner ScaleSet Listener pod is deployed by the AutoScaling Listener Controller. In this pod, the listener application connects to the Actions Service to authenticate and establish a long poll HTTPS connection. The listener stays idle until it receives a Job Available message from the Actions Service.
  4. When a workflow run is triggered from a repository, the Actions Service dispatches individual job runs to the runners or runner scalesets where the runs-on property matches the name of the runner scaleset or labels of self-hosted runners.
  5. When the Runner ScaleSet Listener receives the Job Available message, it checks whether it can scale up to the desired count. If it can, the Runner ScaleSet Listener acknowledges the message.
  6. The Runner ScaleSet Listener uses a Service Account and a Role bound to that account to make an HTTPS call through the Kubernetes APIs to patch the EphemeralRunner Set resource with the number of desired replicas count.
  7. The EphemeralRunner Set attempts to create new runners and the EphemeralRunner Controller requests a JIT configuration token to register these runners. The controller attempts to create runner pods. If the pod's status is failed, the controller retries up to 5 times. After 24 hours the Actions Service unassigns the job if no runner accepts it.
  8. Once the runner pod is created, the runner application in the pod uses the JIT configuration token to register itself with the Actions Service. It then establishes another HTTPS long poll connection to receive the job details it needs to execute.
  9. The Actions Service acknowledges the runner registration and dispatches the job run details.
  10. Throughout the job run execution, the runner continuously communicates the logs and job run status back to the Actions Service.
  11. When the runner completes its job successfully, the EphemeralRunner Controller checks with the Actions Service to see if runner can be deleted. If it can, the Ephemeral RunnerSet deletes the runner.

引用元:actions-runner-controller/docs/gha-runner-scale-set-controller at f1d7c52253b89f0beae60141f8465d9495cdc2cf · actions/actions-runner-controller · GitHub

要約すると、以下のような動作となります。

  1. AutoScalingRunnerSet CustomResourceのデプロイ
  2. AutoScalingRunnerSet ControllerによってEphemeralRunnerSetとAutoScalingListener CustomResourceが順番にデプロイ
  3. AutoScalingListener ControllerによってAutoScalingListener Podが作成され、GitHubとのロングポーリングが開始されます。
  4. CI/CD jobが開始されると、AutoScalingListener Podに通知され、EphemeralRunnerSetの.spec.replicasを0からターゲットの数まで増やす
  5. EphemeralRunnerSet Controllerによって.spec.replicasの数だけEphemeralRunner CustomResourceが作成される。
  6. EphemeralRunner Controllerによって、EphemeralRunner Podが作成され、Self-hosted runnerとして動作する
  7. CI/CD job終了後は自動でGitHub上のRunnerと、EphemeralRunner Podが削除される

上記の流れをKubernetesリソースのみに注目すると、以下のように各リソースが作成されます。

とまあ、今までご紹介してきましたが、実際に動いているものを見た方がいいと思います。
次回はインストールおよび動作を実際のターミナルログ付きでご紹介します。
是非次回も楽しみにしていただければ嬉しいです!

では!!!

2023/09/08 追記: 第二回動作解説編は以下を参照ください。 techblog.ap-com.co.jp

ACS事業部のご紹介

私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化やGitHub Enterpriseの導入のご支援をしております。
www.ap-com.co.jp www.ap-com.co.jp また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。 www.ap-com.co.jp

本記事の投稿者: 谷合純也
AKS/ACA、GitHubをメインにインフラ系のご支援を担当しています。
junya0530さんの記事一覧 | Zenn