はじめに
こんにちは、ACS事業部の吉川です。
先日行われた 第43回 Tokyo Jazug Night にてKEDAについての発表を行いました。
今回のブログではKEDAの利用シーンの一つとして、GitHub Actionsのself-hosted runnerをスケールさせる方法をご紹介します。
self-hosted runner とは
GitHub Actionsのジョブを実行する際、通常はGitHubが管理するコンピュートリソース(GitHub-hosted runners)上で実行されます。ユーザー側でのサーバーメンテナンスの必要がなく、インフラを意識する必要がないのが大きなメリットです。
一方、クローズドなネットワーク内のサーバーにデプロイしたい、 特別なハードウェアが必要といったシーンにはGitHub-hosted runnersは不適合です。そのような場合には自分で用意したサーバーに専用のエージェントを導入することでRunnerとして利用することができます。自前で用意するRunnerを指して self-hosted runner と呼びます。
KEDAとself-hosted runnerを組み合わせる
上述のスライド内で解説していますが、KEDA はイベントに応じてKubernetesのPodをスケールさせるための機構です。
KEDAが対応しているイベントの中に Github Actionsのキューイングされたジョブ数 というものがあります。
これを利用して、コンテナ化されたself-hosted runnerを必要に応じて起動させることができます。
※注: 現状ではKEDAのGithub Runner Scalerは Experimentalなステータス です。重要な環境で使うのは止めておきましょう。
利用方法
Kubernetesクラスター上にKEDAをデプロイします。今回はAzure Kubernetes Service(AKS) v1.25.5を利用しました。オンプレミスや他クラウドのKubernetesであっても同様のことはできるはずです。
AKS上にKEDAを導入する際はアドオン機能が使えますが、現状ではアドオンで導入されるKEDAのバージョンが古くGithub Runner Scalerに対応していません。Github Runner ScalerはKEDA v2.10以上が必要です。
そのためHelmを使ってKEDAをデプロイします。
helm repo add kedacore https://kedacore.github.io/charts helm repo update kubectl create namespace keda helm install keda kedacore/keda --namespace keda helm ls -n keda
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION keda keda 1 2023-04-03 12:00:14.072465372 +0900 JST deployed keda-2.10.1 2.10.0
これで2.10.0のKEDAがデプロイされました。
次にGitHubでPersonal Access Token(PAT)を発行します。最低限必要なスコープを精査しきれていないですが、
- repo
- workflow
- write:packages
- delete:packages
あたりがあれば取りあえず十分でしょう。
PATを発行したら、Kubernetes上にSecretとして登録します。
echo -n "<発行したPAT>" | base64
apiVersion: v1 kind: Secret metadata: name: github-auth type: Opaque data: personalAccessToken: <base64でエンコードしたPAT>
このSecretをKEDAが利用するために、TriggerAuthentication
リソースを作成します。secretTargetRef
で上記のSecretリソースを参照するような設定となっています。
apiVersion: keda.sh/v1alpha1 kind: TriggerAuthentication metadata: name: github-trigger-auth spec: secretTargetRef: - parameter: personalAccessToken name: github-auth key: personalAccessToken
最後に ScaledJob
リソースを作成します。起動するself-hosted reunner用のコンテナイメージは以下のものを利用しました。ラベルとして my-label
という名前を付けています。
以下マニフェスト内の <GitHubユーザー名>
<GitHubリポジトリ名>
は適宜書き換えてください。
apiVersion: keda.sh/v1alpha1 kind: ScaledJob metadata: name: scaledjob-github-runner spec: jobTargetRef: template: metadata: labels: app: scaledjob-github-runner spec: containers: - name: scaledjob-github-runner image: myoung34/github-runner:latest imagePullPolicy: Always env: - name: EPHEMERAL value: "true" - name: DISABLE_RUNNER_UPDATE value: "true" - name: REPO_URL value: "https://github.com/<GitHubユーザー名>/<GitHubリポジトリ名>" - name: RUNNER_SCOPE value: "repo" - name: LABELS value: "my-label" - name: ACCESS_TOKEN valueFrom: secretKeyRef: name: github-auth key: personalAccessToken restartPolicy: Never minReplicaCount: 0 maxReplicaCount: 20 pollingInterval: 30 triggers: - type: github-runner metadata: owner: "<GitHubユーザー名>" repos: "<GitHubリポジトリ名>" labelsFromEnv: "LABELS" runnerScopeFromEnv: "RUNNER_SCOPE" authenticationRef: name: github-trigger-auth
これで準備は完了です。
ジョブを実行してみる
では実際にGitHub Actionsでジョブを実行してみましょう。
self-hosted runnerを利用する場合、ジョブ内の runs-on
句でランナーのラベルを指定します。今回の例だと my-label
です。
name: Sample Workflow on: workflow_dispatch: jobs: sample_job: runs-on: my-label steps: - run: hostname
こちらのジョブを動かしてみた結果が以下です。ホスト名を表示するコマンドの結果が、Kubernetes上で起動したPodの名前と同じである= Kubernetes上でself-hosted runnerが起動している ことが確認できます。
おわりに
self-hosted runnerはVMやオンプレミスのサーバーにエージェントをインストールして構築するのが一般的ですが、それをコンテナ化しKEDAでスケールさせるという例でした。
KEDAの最新バージョン(2.10)のみ対応・まだExperimentalという利用しづらい状況ではありますが、今後サポートが拡充されていったら便利に使えるのではないかと思います。
個人的にはAzure Container Appsで利用できるようになると0スケール時のコストメリットが大きく便利なので、早くサポートされることを願っています。(現状ではAzure Container AppsのKEDAはGithub Runner Scalerに未対応です)
私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。
また、一緒に働いていただける仲間も募集中です!
ご興味持っていただけましたらぜひお声がけください。