Featured image of post Azure Container Apps Jobs を Self-hosted GitHub Actions Runner として使う

Azure Container Apps Jobs を Self-hosted GitHub Actions Runner として使う

GitHub Actions の Self-hosted Runner を安く用意する方法を探していたところ、 Azure の Container Apps Jobs というのが便利に使えるらしいというのを見つけたので試してみる。

チュートリアル:Azure Container Apps ジョブを使用してセルフホスト型 CI/CD ランナーとエージェントをデプロイする をなぞるだけです。

準備

Azure のアカウントは作成済みとする(無料で作成できる

環境は Windows 11 の WSL

Azure CLI のインストール

Azure CLI

brew install azure-cli

Azure にログイン

az login

Windows の場合はWeb アカウント マネージャーを使うと便利らしい。

Azure Container Apps 拡張機能をインストール

az extension add --name containerapp --upgrade

Azure サブスクリプションに Microsoft.App と Microsoft.OperationalInsights 名前空間を登録

ちょっとなんのことだかわからないけどコピペ

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights
az provider show -n Microsoft.App | jq '{namespace: .namespace, registrationState: .registrationState}'
az provider show -n Microsoft.OperationalInsights | jq '{namespace: .namespace, registrationState: .registrationState}'

registrationStateRegistering から Registered に変わったら OK

{
  "namespace": "Microsoft.App",
  "registrationState": "Registered"
}
{
  "namespace": "Microsoft.OperationalInsights",
  "registrationState": "Registered"
}

変数設定

後の作業で使う変数を定義しておく

RESOURCE_GROUP="github-actions-runner"
LOCATION="japaneast"
ENVIRONMENT="env-github-actions-runner"
JOB_NAME="github-actions-runner-job"

Azure のリソース作成

リソースグループの作成

リソースグループを分けておくことで不要になったときに丸っと削除することができる

az group create \
    --name "$RESOURCE_GROUP" \
    --location "$LOCATION"
response
{
  "id": "/subscriptions/*****/resourceGroups/github-actions-runner",
  "location": "japaneast",
  "managedBy": null,
  "name": "github-actions-runner",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}

Container Apps 環境の作成

az containerapp env create \
    --name "$ENVIRONMENT" \
    --resource-group "$RESOURCE_GROUP" \
    --location "$LOCATION"

The behavior of this command has been altered by the following extension: containerapp No Log Analytics workspace provided. Generating a Log Analytics workspace with name “workspace-githubactionsrunnereINU”

Log Analytics workspace も自動で作成されたっぽい。これがなんだかわからないけど。

$ az containerapp env list \
  | jq '.[] | {name: .name, endpoint: .properties.eventStreamEndpoint}'

で、こんな出力が得られる。

{
  "name": "env-github-actions-runner",
  "endpoint": "https://japaneast.azurecontainerapps.dev/subscriptions/*****/resourceGroups/github-actions-runner/managedEnvironments/env-github-actions-runner/eventstream"
}

GitHub からの webhook event をこの endpoint に送るのかな?って思ったけど違うらしい。

GitHub 側の作業

Self-hosted Runner を使いたいリポジトリはすでに存在するものとする

GitHub の Personal Access Token (PAT) を取得する

GitHub App じゃなくて個人の PAT じゃなきゃダメなのか? (GitHub App でもできることは後でわかった)

Fine-grained tokens で Generate new token をクリック

Repository access は Only select repositories で self-hosted runner の必要なリポジトリを選択

Permissions は Repository permissions で

  • Actions: Read-only
  • Administration: Read and write
  • Metadata: Read-only (mandatory)

作成された token をメモしておく

後で使うので変数に値を入れておく

GITHUB_PAT="<GITHUB_PAT>"
REPO_OWNER="<REPO_OWNER>"
REPO_NAME="<REPO_NAME>"

Runner 用の Container Image を build する

Container Image の名前を決める

CONTAINER_IMAGE_NAME="github-actions-runner:1.0"
CONTAINER_REGISTRY_NAME="<CONTAINER_REGISTRY_NAME>"

<CONTAINER_REGISTRY_NAME> を、コンテナー レジストリを作成するための一意の名前に置き換えます。 コンテナー レジストリ名は、“Azure 内で一意” であり、数字と小文字のみを含む 5 文字から 50 文字の長さにする必要があります。

registry server が <CONTAINER_REGISTRY_NAME>.azurecr.io になる。

Container Registry の作成

az acr create \
    --name "$CONTAINER_REGISTRY_NAME" \
    --resource-group "$RESOURCE_GROUP" \
    --location "$LOCATION" \
    --sku Basic \
    --admin-enabled true

Image の build と push

Azure Container Registry ってこうやって build できるのか、ちょっと便利そう

az acr build \
    --registry "$CONTAINER_REGISTRY_NAME" \
    --image "$CONTAINER_IMAGE_NAME" \
    --file "Dockerfile.github" \
    "https://github.com/Azure-Samples/container-apps-ci-cd-runner-tutorial.git"

Self-hosted runner を Job として deploy する

az containerapp job create -n "$JOB_NAME" -g "$RESOURCE_GROUP" --environment "$ENVIRONMENT" \
    --trigger-type Event \
    --replica-timeout 1800 \
    --replica-retry-limit 0 \
    --replica-completion-count 1 \
    --parallelism 1 \
    --image "$CONTAINER_REGISTRY_NAME.azurecr.io/$CONTAINER_IMAGE_NAME" \
    --min-executions 0 \
    --max-executions 10 \
    --polling-interval 30 \
    --scale-rule-name "github-runner" \
    --scale-rule-type "github-runner" \
    --scale-rule-metadata \
        "githubAPIURL=https://api.github.com" \
        "owner=$REPO_OWNER" \
        "runnerScope=repo" \
        "repos=$REPO_NAME" \
        "targetWorkflowQueueLength=1" \
    --scale-rule-auth "personalAccessToken=personal-access-token" \
    --cpu "2.0" \
    --memory "4Gi" \
    --secrets "personal-access-token=$GITHUB_PAT" \
    --env-vars \
        "GITHUB_PAT=secretref:personal-access-token" \
        "REPO_URL=https://github.com/$REPO_OWNER/$REPO_NAME" \
        "REGISTRATION_TOKEN_API_URL=https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/actions/runners/registration-token" \
    --registry-server "$CONTAINER_REGISTRY_NAME.azurecr.io"

KEDA の Github Runner Scaler というのが使われているようで --polling-interval 30 (30秒) 間隔で GitHub の API にアクセスして実行待ちの Job が無いかを探す。 GitHub App を使う方法も書いてあった。

Polling から実行が必要だと判断されてコンテナが起動されると entrypoint.sh の中で runner の登録と実行が行われるようになっている。 Runner 登録のための token 取得処理が Personal Access Token 前提になっているため GitHub App を使う場合はここの処理を書き換える必要がある。

GitHub App の場合は JWT を作ったりする必要があるのですが、先人が公開してくれていました。 Github ActionsのセルフホステッドランナーにAzure Container Apps(ACA) jobsを活用する (Qiita)

actions/setup-python が機能しない問題(解決済み)

Workflow の Job の中で python script を実行したかったので actions/setup-python を使っていたのですが、次の出力でコケてしまっていました。 前半の cache に無いというメッセージは良いのですが、インストールにも失敗しているのに理由が不明で困りました。 実行環境は Linux で x64 なので 3.12.2 はリストに存在するバージョンです。

Version 3.12.2 was not found in the local cache
Error: The version '3.12.2' with architecture 'x64' was not found for this operating system.
The list of all available versions can be found here: https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json

調べていてたどり着いたのが actions/setup-python #401 でした。 「Debian はサポートしていません」え…

Container Image は github.com/Azure-Samples/container-apps-ci-cd-runner-tutorial にある Dockerfile.github を使って build したもので Base image は ghcr.io/actions/actions-runner:2.304.0 で、これが Debian だったのです。 この actions/runner リポジトリで公開されている image なのに?! と思いましたが、最新の image を確認したら Ubuntu に変わってました。 v2.305.0 で変わったようです、Base image として使われていたやつの次のリリースですね…

Dockerfile を編集して build したら手元から push しました。この場合、az acr build コマンドではないので az acr login --name $CONTAINER_REGISTRY_NAME でログインして docker push しました。 Container Apps Job は delete して再作成しました。update コマンド調べるの面倒だったので。

az containerapp job delete -n "$JOB_NAME" -g "$RESOURCE_GROUP"

Azure リソースの削除

不要になったらリソースグループごとまるっと削除です。

az group delete \
    --resource-group $RESOURCE_GROUP

以上、引き出しに入れておこう。

Built with Hugo
テーマ StackJimmy によって設計されています。