APC 技術ブログ

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

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

KEDAでGitHub Actions self-hosted runnerをスケールする

はじめに

こんにちは、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のキューイングされたジョブ数 というものがあります。

keda.sh

これを利用して、コンテナ化された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をデプロイします。

keda.sh

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.com

以下マニフェスト内の <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などのクラウドネイティブ技術を活用した内製化のご支援をしております。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!

www.ap-com.co.jp

ご興味持っていただけましたらぜひお声がけください。

本記事の投稿者: 吉川 俊甫
AKS/ACAをメインにインフラ系のご支援を担当しています。 Shunsuke Yoshikawa - Credly