6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Github ActionsのセルフホステッドランナーにAzure Container Apps(ACA) jobsを活用する

Last updated at Posted at 2023-11-02

はじめに

 Azure Container Apps jobs(以降、ACA jobsとする)が8月末にGAされました。
個人的に使ってみて感じた強みとして、Azure PipelinesやGithub Actionsのセルフホステッドランナーとして活用できる点です。
 本記事では、Github ActionsのセルフホステッドランナーにACA jobsを活用する方法を書いていきます。

ACA jobsについて

Azure Container Apps

 ACA jobsはAzure Container Apps(ACA)の新しい機能です。ACAは公式ドキュメントの説明では以下のように謳っています。

サーバーレス プラットフォームでコンテナー化されたアプリケーションとマイクロサービスを実行できるフル マネージド環境です。

 文字だけ読むとなんか凄そうなサービスですね!実はこのサービスの下側はk8sが動いています。一般的にk8sをシステムに採用する場合、高い学習コストや半年に1度の重たいメンテを課せられます。そういった煩わしい運用面のコストや責任をユーザから取り除いて使いやすくしたというのがACAとうサービスです。今回紹介するのはその新機能となるACA jobsです。

ACA jobsの概要

 ACA jobsは手動、スケジュール、イベントドリブンの3つタイプのトリガーをサポートしており、そのトリガーによって処理を実行することができます。k8sを使ったことある方ならピンときた方もおられると思いますが、k8sのjobsの機能をACAで使えるようにした感じだと思われます。

ACA jobsによるセルフホステッドランナー

 ACA jobsのもう1つの機能として、Azure PipelinesやGithub Actionsのセルフホステッドランナーとして活用できます。セルフホステッドランナーの注意点として、VMをランナーとする場合、使っていないときでも維持費が掛かってしまいます。

Azure Pipelines

 Azure PipelinesのセルフホステッドランナーはVMSSと呼ばれるVMをスケールさせるAzureサービスを使用することでゼロスケールが可能になり、その費用は掛からなくなります。
VMSSをACA jobsに置き換えることでVMからコンテナにすることができるので、起動時間が圧倒的に早くなります(体感)。

Github Actions

 Github Actionsの場合は公式ではk8s等で構築するactions-runner-controllerで自動スケーリングする機構を作る方法が紹介されています。ただ、前述の方法は学習コストが重いk8sを扱えることを前提としたり、半年に1度アプデ更新等の重たいメンテナンス作業が必須になったりします。しかしながら、ACAはk8sをラップしたサービスのため、その問題は解消されます。

Github ActionsのセルフホステッドランナーにACA jobsを活用する

利点

 個人的にGithub Actionsのセルフホステッドとして、ACA jobsを利用する利点は以下です。

  • Github Actionsより価格が安い
    • 最低ラインぐらいスペックを価格比較
  • Azure Subscriptionにお財布を統合できる
  • ゼロスケール可能 (使っていなくても課金されない)
  • k8sを意識しなくて良い

構築

 基本的にはチュートリアル:Azure Container Apps ジョブを使用してセルフホスト型 CI/CD ランナーとエージェントをデプロイするを実施することでほぼ構築することができます。

スケールについて

 ACA jobsを使用する以上、どこまでスケールするのかは気になるところです。公式ドキュメントでは最大300と記載されていますが、実際触るとAzure Portalから最大100まで設定可能であることは確認できています。ただ、1コンテナに割り当てるCPU/メモリによってクォータ制限に引っかかる可能性があるため、ちゃんと最大数が知りたい場合は負荷検証等が必要になるかと思います。

セルフホステッドランナーのイメージについて

 前述のチュートリアルを実施しているではこちらのイメージを使用しており、actions-runnerのベースイメージに縛られるので、おそらく自由度はそれほど高くないと思います。

 今回はこのイメージを改造して、Azure CLIやPowershellを実行可能なセルフホステッドランナーを紹介します

# https://github.com/Azure-Samples/container-apps-ci-cd-runner-tutorial/blob/main/Dockerfile.github
# 上記のGithubのファイルをカスタマイズしています

FROM ghcr.io/actions/actions-runner:latest

USER root

# install curl and jq
RUN apt update && apt-get install -y curl jq wget apt-transport-https software-properties-common && \
    apt clean && \
    rm -rf /var/lib/apt/lists/*

# install Azure CLI
# https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli-linux?pivots=apt#option-1-install-with-one-command
RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash

# install PowerShell
# https://learn.microsoft.com/ja-jp/powershell/scripting/install/install-ubuntu?view=powershell-7.3#installation-via-package-repository-the-package-repository
RUN wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" \
    && dpkg -i packages-microsoft-prod.deb \
    && rm packages-microsoft-prod.deb \
    && apt update \
    && apt install -y powershell \
    && apt clean \
    && rm -rf /var/lib/apt/lists/*

# install Bicep
# https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/install#linux
RUN curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-linux-x64 \
    && chmod +x ./bicep \
    && mv ./bicep /usr/local/bin/bicep

COPY ./entrypoint.sh ./entrypoint.sh
RUN chmod +x ./entrypoint.sh

USER runner

ENTRYPOINT ["./entrypoint.sh"]

entrypoint.shはこちらから変更はないです。

 チュートリアルのコンテナイメージを使用する場合、Github Actionsをキックして、10秒ぐらいでコンテナが立ち上がります。なかなか早いです。

Github Appを使用する

 紹介されているチュートリアルではGithub PATを使用しており、ニーズとしてGithub Appも使用したいという方がおられると思うので、その方法をこちらで紹介します。

コンテナイメージを改修

 PATを使用している箇所はentrypoint.shのため、このスクリプトを以下のように改造することで対応できます。

#!/bin/sh -l

# download Github App private key
az config set auto-upgrade.enable=no
private_key="github_app_private_key.pem"
az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET --tenant $AZURE_TENANT_ID
az storage blob download --account-name $AZURE_STORAGE -c $AZURE_STORAGE_CONTAINER -n $AZURE_STORAGE_BLOB -f $private_key
az logout

# get token from Github App
# https://zenn.dev/tmknom/articles/github-apps-token#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB
# 上記のスクリプトを参考にしました
base64url() {
  openssl enc -base64 -A | tr '+/' '-_' | tr -d '='
}

sign() {
  openssl dgst -binary -sha256 -sign "./$private_key"
}

header="$(printf '{"alg":"RS256","typ":"JWT"}' | base64url)"
now="$(date '+%s')"
iat="$((now - 60))"
exp="$((now + (3 * 60)))"
template='{"iss":"%s","iat":%s,"exp":%s}'
payload="$(printf "$template" "$GITHUB_APP_ID" "$iat" "$exp" | base64url)"
signature="$(printf '%s' "$header.$payload" | sign | base64url)"
jwt="$header.$payload.$signature"
rm ./$private_key

installation_id="$(curl --location --silent --request GET \
  --url "https://api.github.com/repos/$GITHUB_OWNER/$GITHUB_REPO/installation" \
  --header "Accept: application/vnd.github+json" \
  --header "X-GitHub-Api-Version: 2022-11-28" \
  --header "Authorization: Bearer $jwt" \
  | jq -r '.id'
)"

token="$(curl --location --silent --request POST \
  --url "https://api.github.com/app/installations/$installation_id/access_tokens" \
  --header "Accept: application/vnd.github+json" \
  --header "X-GitHub-Api-Version: 2022-11-28" \
  --header "Authorization: Bearer $jwt" \
  | jq -r '.token'
)"

# https://github.com/Azure-Samples/container-apps-ci-cd-runner-tutorial/blob/main/github-actions-runner/entrypoint.sh
# 上記のGithubのファイルを流用しています
registration_token="$(curl -X POST -fsSL \
  -H 'Accept: application/vnd.github.v3+json' \
  -H "Authorization: Bearer $token" \
  -H 'X-GitHub-Api-Version: 2022-11-28' \
  "https://api.github.com/repos/$GITHUB_OWNER/$GITHUB_REPO/actions/runners/registration-token" \
  | jq -r '.token')"

./config.sh --url https://github.com/$GITHUB_OWNER/$GITHUB_REPO --token $registration_token --unattended --ephemeral && ./run.sh

この構成では、以下の環境変数を使っています。

環境変数 説明
AZURE_CLIENT_ID サービスプリンシパルのClinet ID
AZURE_CLIENT_SECRET サービスプリンシパルのClient Secret
AZURE_TENANT_ID サービスプリンシパルのテナント ID
AZURE_STORAGE Blob Storage名
AZURE_STORAGE_CONTAINER Blob StorageのContainer名
AZURE_STORAGE_BLOB Blob名
GITHUB_APP_ID Github AppのID
GITHUB_OWNER Github Owner名
GITHUB_REPO Github リポジトリ名

 Github Appを使ったtoken取得にはこちらのドキュメントから流用しています。
また、この例ではGithub Appの秘密鍵をAzure Blob Storageから取得するようにしていますが、取れれば何でも良いです。

Azure Container Apps Jobsの設定変更

 2023年12月頃にこちらのissueがCloseされ、Azure Container Apps JobsにGithub Appの設定を追加することができるようになりました。

$ az containerapp job update -n MyContainerAppJob -g MyResourceGroup --scale-rule-auth "appKey=app-key"

$ az containerapp job secret set -n MyContainerappjob -g MyResourceGroup --secrets "app-key=keyvaultref:$KEY_VAULT_PEM_URL,identityref:$USER_ASSIGNED_IDENTITIE"

 上記のように、--scale-rule-authの設定と--secretsの設定を変更することでGithub Appを使用することができます。設定するにはGithub Appの秘密鍵をAzure Key Vaultに登録とAzure KeyVaultにアクセスするためのマネージドIDを発行が必要になります。

まとめ

 個人的にGithub Actionsでのゼロスケールを簡単に実現できるため、非常に素晴らしいサービスだと感じました。コンテナイメージの制約はありますが、要件に合致する場合は是非使用すると良いと感じました。
 弊社の場合は、Visual Studioのライセンスを保有している方は月6000クレジット分のAzureリソースを使用できるため、個人での検証/開発等でGithub Actionsを使用できるのは良い点だと考えています。一方で、Azure Pipelins経由でゲームのビルドとかで利用している方はGPU等を積んだVMでビルドしたほうが早いのでACA jobsを無理に使用しない方が良いです。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?