はじめに
Azure Developer CLIをCI/CD(Github Actions)に組み込み、開発/本番環境にデプロイさせたいと考えています。
Azure Developer CLIとは
Azure Developer CLI (azd) は、Azure の使用を開始するのにかかる時間を短縮するオープンソース ツールです。 azd には、ワークフローの主要なステージ (コード、ビルド、デプロイ、監視) にマップする開発者向けコマンドのセットが用意されています。 CLI を使用すると、ターミナル、エディター/統合開発環境、GitHub Actions パイプラインなど、繰り返しが可能な方法で一貫して作業できます。
上記のように謳っており、本ツールを使用することで以下の簡単なコマンド操作でインフラ、アプリケーションのデプロイおよび削除を実施することができます。
$ azd up # インフラ/アプリケーションをデプロイ
$ azd provision # インフラのみデプロイ
$ azd depoy # アプリケーションのみデプロイ
$ azd down # インフラ/アプリケーションを削除
今回はこのコマンドをCI/CDに組み込んでいきます。
CI/CD
公式ドキュメントで紹介されているCI/CD
ドキュメントで紹介されている方法では以下のようなGithub Actionsを組み込むことでCI/CDの導入が可能です。
on:
workflow_dispatch:
push:
# Run when commits are pushed to mainline branch (main or master)
# Set this to the mainline branch you are using
branches:
- main
- master
# GitHub Actions workflow to deploy to Azure using azd
# To configure required secrets for connecting to Azure, simply run `azd pipeline config`
# Set up permissions for deploying with secretless Azure federated credentials
# https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#set-up-azure-login-with-openid-connect-authentication
permissions:
id-token: write
contents: read
jobs:
build:
runs-on: ubuntu-latest
env:
AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install azd
uses: Azure/setup-azd@v0.1.0
- name: Log in with Azure (Federated Credentials)
if: ${{ env.AZURE_CLIENT_ID != '' }}
run: |
azd auth login `
--client-id "$Env:AZURE_CLIENT_ID" `
--federated-credential-provider "github" `
--tenant-id "$Env:AZURE_TENANT_ID"
shell: pwsh
- name: Log in with Azure (Client Credentials)
if: ${{ env.AZURE_CREDENTIALS != '' }}
run: |
$info = $Env:AZURE_CREDENTIALS | ConvertFrom-Json -AsHashtable;
Write-Host "::add-mask::$($info.clientSecret)"
azd auth login `
--client-id "$($info.clientId)" `
--client-secret "$($info.clientSecret)" `
--tenant-id "$($info.tenantId)"
shell: pwsh
env:
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
- name: Provision Infrastructure
run: azd provision --no-prompt
- name: Deploy Application
run: azd deploy --no-prompt
Log in with Azure (Federated Credentials)
からOIDCが可能なのは嬉しいポイントです。
やりたいことに合うようにこのコードを改造していきます。
やりたいことを実現するための問題
-
やりたいこと
- インフラとアプリケーションでワークフローを分ける
- 片方だけ更新がある際にも対応するため
- 開発/本番等の環境ごとに制御する
- 各種環境で同じコードを流用したいため
- インフラとアプリケーションでワークフローを分ける
-
問題
- インフラとアプリケーションでワークフローを分離した場合、インフラで扱った環境変数をアプリケーションのワークフローでは使えない
- azdはコマンド実行した際にローカル上の.azure配下にazdコマンドで扱う環境変数群(
.env
)を構築をします。この環境変数はBicepコードやhooks
のスクリプト等で参照することができます。また、azd provision
によって新しく環境変数が追加されたります。そのため、インフラとアプリケーションでワークフローを分離した場合、インフラ構築時に値が追加された.env
をアプリケーションのワークフローでは使用することができません。.env
を各ワークフローで共有する必要があります。 - これを解決するために、azdのリモート環境の設定を実施します。
- azdはコマンド実行した際にローカル上の.azure配下にazdコマンドで扱う環境変数群(
- 環境ごとに値の制御ができない
- 現状は
AZURE_ENV_NAME
でazdのデプロイ先の制御が可能だが、azd auth loginで使用するサービスプリンシパルも環境ごとに変更したいと考えています。 - これを解決するために、Github Environment等を駆使して
AZURE_CLIENT_ID
等の値を制御します。(本ドキュメントでは特に説明なし)
- 現状は
- インフラとアプリケーションでワークフローを分離した場合、インフラで扱った環境変数をアプリケーションのワークフローでは使えない
上記の問題に対する解決策にしたがって、既存コードを改造していきます
リモート環境
この方法を使用することで、azdで構築される環境変数群(.env
)をAzure Blob Storageに保存することができます。azure.yaml
に以下を書き込むことで設定完了です。
name: azd-project-name
state:
remote:
backend: AzureBlobStorage
config:
accountName: saazdremotestate
containerName: myproject
上記設定後、以下のコマンドが実行可能になります。
$ azd env list # ローカル or リモート環境に登録されている環境名を表示
NAME DEFAULT LOCAL REMOTE
dev true false true
prod true false true
$ azd env select dev # 選択したリモート上の環境名をローカル上に構築します
リモート設定をCI/CDに組み込むことで、アプリケーションのワークフローでもインフラのワークフローで扱った環境変数を使用することが可能になります。
公式ドキュメントで記載がないことは以下です。
-
azd auth login
でログインするユーザーには指定したAzure Blob Storageへのストレージ BLOB データ共同作成者
の権限を与える必要があります。 - ローカル上の
.env
をリモート環境に反映させるには、明確なコマンドはなく、azd provision
,azd deploy
といったデプロイコマンドを実行すると自動的にリモートに反映されます。
完成したCI/CD
改造して構築したコードは以下になります。
インフラ
name: Provision Infrastructure
on:
workflow_dispatch:
inputs:
environment:
description: 'environment'
required: true
type: environment
is_apply:
description: 'is apply'
required: true
default: false
type: boolean
permissions:
id-token: write
contents: read
jobs:
provision:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }} # Github Environmnet設定
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_ENV_NAME: ${{ inputs.environment }}
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install azd
uses: Azure/setup-azd@v0.1.0
- name: Log in with Azure (Federated Credentials)
run: |
azd auth login `
--client-id "$Env:AZURE_CLIENT_ID" `
--federated-credential-provider "github" `
--tenant-id "$Env:AZURE_TENANT_ID"
shell: pwsh
- name: Set Remote azd env # リモート環境の環境変数をローカル上に格納
run: azd env select ${{ inputs.environment }}
- name: Provision Infrastructure Preview
run: azd provision --preview
- name: Provision Infrastructure
if: ${{ inputs.is_apply }}
run: azd provision --no-prompt
アプリケーション
name: Deploy Application
on:
workflow_dispatch:
inputs:
environment:
description: 'environment'
required: true
type: environment
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }} # Github Environmnet設定
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_ENV_NAME: ${{ inputs.environment }}
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install azd
uses: Azure/setup-azd@v0.1.0
- name: Log in with Azure (Federated Credentials)
run: |
azd auth login `
--client-id "$Env:AZURE_CLIENT_ID" `
--federated-credential-provider "github" `
--tenant-id "$Env:AZURE_TENANT_ID"
shell: pwsh
- name: Set Remote azd env # リモート環境の環境変数をローカル上に格納
run: azd env select ${{ inputs.environment }}
- name: Deploy Application
run: azd deploy --no-prompt
補足
- 説明のため
workflow_dispatch
で組んでいます - Github Environment名とazdの環境名は同名で組んでいます
- Github EnvironmentとAzureのサービスプリンシパルは事前に作成してください
- AzureでのOIDCの設定方法はこちらを参照してください
まとめ
Azure Developer CLIをCI/CDに組み込み、開発/本番環境にデプロイする方法を紹介しました。Azure Developer CLIはまだまだ新しいツールではありますが、かなり便利ですのでAzureでシステムを組む際は積極的に使っていきましょう!