GitHub ActionsからAzureリソースを操作する

デジタル開発G 黒木です。

目次

この記事では、以下の内容についてご紹介します:

はじめに

アジャイル推進ユニットでは、Azure上に構築したMLOps1環境で機械学習モデルを運用しています。この運用作業を自動化するためにGitHub Actions2を活用していますが、Azureのネットワーク制限によって保護された一部のリソースに対しては、GitHub Actionsから直接アクセスできないという課題がありました。 本記事では、特にAzure Container Registry (ACR)3へのイメージプッシュを自動化するケースで発生した課題と解決策について取り上げ、具体的なワークフローの構築手順を紹介します。

課題:GitHub ActionsからACRにアクセスできない

ACRのネットワーク制御

ACRは不要なアクセスを防ぐために、必要なアクセスのみを許可している状態です。 ACRリソースのファイアウォール設定において、アクセス元となるIPアドレス群をアクセス許可設定に追加しています。

GitHub Actionsの実行環境

GitHub ActionsはGitHubが提供するサーバー上の仮想マシンで実行されます。そのため、上記のようなネットワーク制御が行われたACRにはアクセスができません。 アクセスを可能にするには、GitHub Actionsがアクセスに使用するIPアドレスファイアウォールの許可設定に追加する必要があります。

解決策:GitHub Actionsで一時的なアクセス許可を自動化

ワークフロー構成

以下の図のように、ACRへのアクセスを必要とする処理の前後に、ファイアウォール設定を変更する処理を追加することで解決しました。 * ACRへのアクセス前:アクセス元となるIPアドレスの許可設定を追加 * ACRへの処理完了後:追加した許可設定を削除

ワークフローの作成手順

前提条件

  • Azureアカウントがあること
  • GitHubリポジトリがあること
  • ACRが作成されていること

1. サービスプリンシパルの作成

GitHub ActionsワークフローがAzureにログインし、対象のサブスクリプションにアクセスするための認証情報が必要となります。

  1. Azure portal > Microsoft Entra ID > [アプリの登録]を開く
  2. [新規登録]を選択し、新規サービスプリンシパルを作成

2. フェデレーション資格情報の追加

Azure-GitHub間の接続許可設定を作成するため、フェデレーション資格情報の作成またはクライアントシークレットの作成が必要となります。 本手順では、フェデレーション資格情報の作成手順を記載します。

  1. Azure portal > Microsoft Entra ID > [アプリの登録] を開く
  2. 作成したサービスプリンシパルを選択し、[証明書とシークレット]タブの[フェデレーション資格情報]を開く
  3. [資格情報の追加]を選択し、以下設定をして追加

3. ロールの割り当て

対象環境-GitHub間の接続許可設定を作成するため、作成したサービスプリンシパルに対象サブスクリプションでロールの割り当てが必要になります。本手順では、「共同作成者」ロールを割り当てます。

  1. Azure portal > サブスクリプションを開く
  2. 対象のサブスクリプションを選択し、[アクセス制御(IAM)]タブの[ロールの割り当て]を開く
  3. [追加]>[ロール割り当ての追加]を選択し、以下を設定して追加
    • ロールタブ:
      • [特権管理者ロール]タブから共同作成者を選択
    • メンバータブ:
      • アクセスの割当先:ユーザー、グループ、またはサービスプリンシパル
    • メンバー:作成したサービスプリンシパルを選択

4. シークレットの作成

GitHubリポジトリにシークレットを作成することで、IDやパスワード等の情報を変数として保存し、GitHub Actionsワークフローで使用することができます。シークレットは暗号化して保存されるため、一度作成すると見ることができなくなります。実行ログにもマスキングされた形で表示されるため、安全性を高めることができます。

本手順では以下情報をシークレットに登録し、ワークフローで使用します。

シークレット名 説明
AZURE_CLIENT_ID サービスプリンシパルのクライアントID
AZURE_TENANT_ID サービスプリンシパルのテナントID
AZURE_SUBSCRIPTION_ID サブスクリプションID
REGISTRY_RESOURCE_GROUP_NAME ACRが属するリソースグループ名
REGISTRY_NAME ACRのリソース名
REGISTRY_LOGIN_SERVER ACRのログインサーバー名
REGISTRY_USERNAME ACRの管理ユーザー名
REGISTRY_PASSWORD ACRの管理ユーザーのパスワード

5. GitHub Actionsワークフローの作成

ワークフローはGitHubリポジトリ/.github/workflows パスのYAMLファイルによって定義されます。

作成するワークフローの流れは以下になります。

  1. リポジトリのチェックアウト
  2. Azureへのログイン
  3. 一時的なアクセス許可の設定
  4. ACRへのログイン
  5. Dockerイメージのビルドとプッシュ
  6. アクセス許可のリセット

1. リポジトリのチェックアウト

- name: Check out repository
  uses: actions/checkout@v4

GitHub公式のチェックアウトアクション(actions/checkout@v4)を使用し、リポジトリの内容をワークフローの実行環境に複製します。

2. Azureへのログイン

- name: Log in to Azure
  uses: azure/login@v2
  with:
    client-id: ${{ secrets.AZURE_CLIENT_ID }}
    tenant-id: ${{ secrets.AZURE_TENANT_ID }}
    subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

Azure公式のログインアクション(azure/login@v2)を使用し、Azureにログインします。

3. ファイアウォール許可設定の追加

- name: Allow ACR Firewall
  if: always()
  run: |
    set -eu
    agentIP=$(curl -s https://api.ipify.org/)
    echo $agentIP
    az acr network-rule add \
      --resource-group "${{ secrets.REGISTRY_RESOURCE_GROUP_NAME }}" \
      --name "${{ secrets.REGISTRY_NAME }}" \
      --ip-address $agentIP
    sleep 10

GitHub Actionsが実行される環境のIPアドレスをACRのファイアウォールに一時的に追加しています。

  • 詳細説明:
    • if: always():ワークフローの前のステップの成功・失敗に関わらず常に実行するように設定
    • curl -s https://api.ipify.org/GitHub Actionsが実行される環境のIPアドレスを取得
    • az acr network-rule add:取得したIPアドレスファイアウォール許可設定に追加
    • sleep 10:許可設定が完全に反映されるまで待つ

4. ACRへのログイン

- name: Log in to ACR
  uses: azure/docker-login@v2
  with:
    login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
    username: ${{ secrets.REGISTRY_USERNAME }}
    password: ${{ secrets.REGISTRY_PASSWORD }}

Azure公式のログインアクション(azure/docker-login@v2)を使用し、ACRにログインします。

5. Dockerイメージのビルドとプッシュ

- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@v3

- name: Build and push Docker image
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    file: Dockerfile
    tags: image:${{ github.sha }}
    cache-from: type=gha
    cache-to: type=gha,mode=max

Dockerのビルドツールをセットアップし、イメージのビルド・プッシュを行います。

  • 詳細説明:
    • push: true:ビルドが成功した後にDockerイメージをACRにプッシュする
    • tags: image:${{ github.sha }}:ビルドしたDockerイメージに一意のタグを付ける
    • cache-from: type=ghaGitHub Actionsのキャッシュを使用してビルド時間を短縮
    • cache-to: type=gha,mode=max:可能な限り多くのキャッシュを保存

6. アクセス許可のリセット

- name: Deny ACR Firewall
  if: always()
  run: |
    agentIP=$(curl -s https://api.ipify.org/)
    az acr network-rule remove \
      --resource-group "${{ secrets.REGISTRY_RESOURCE_GROUP_NAME }}" \
      --name "${{ secrets.REGISTRY_NAME }}" \
      --ip-address $agentIP

ビルドが完了した後、GitHub Actionsが実行される環境のIPアドレスをACRのファイアウォールから削除します。

まとめ

本記事では、ネットワーク制御が行われているAzureリソースに対して、GitHub Actionsを活用して自動的にイメージをプッシュする方法を紹介しました。 この仕組みにより、人為的な設定ミスを防ぎつつ、安全かつ効率的な運用作業が可能となりました。


  1. AI開発を高度化・効率化し、システム化や運用・保守に至る一連のプロセスを継続的に実施するための手法
  2. GitHub Actions は、ビルド、テスト、デプロイのパイプラインを自動化できる継続的インテグレーションと継続的デリバリー (CI/CD) のプラットフォームです。(公式ドキュメント
  3. Azure Container Registry (ACR) は、Dockerコンテナイメージや関連データを管理・保存できる、プライベートなレジストリサービスです。(公式ドキュメント