Azure App Spaces と Azure Developer CLI

## はじめに
こんにちは、Datadog で Sales Engineer をしているAoTo(@AoTo0330)です。

今回は [Microsoft Build 2023](https://news.microsoft.com/build-2023/)で発表された [Azure App Spaces](https://learn.microsoft.com/ja-jp/azure/app-spaces/overview) を使って簡単な Todo List アプリケーションを作成し、Azure App Spaces と その裏側で利用されている Azure Developer CLI の関係についてまとめてみました。

また、この続編として App Spaces の Observability について、Azure Monitor を中心とした Azure の監視ソリューションについてまとめています。ご興味があればぜひご覧ください。

https://qiita.com/AoTo0330/items/3fcfe310c3edb7dcceb3

## Azure App Spaces を使ってみる
Azure App Spaces はプレビュー版が提供されており、Azure Portal 上からすぐに利用できます。

今回は公式のガイドを元に、React と Python で書かれた Todo List のサンプルアプリケーションを作成してみます。

https://learn.microsoft.com/ja-jp/azure/app-spaces/deploy-app-spaces-template

Azure App Spaces は指定の GitHub リポジトリと連携し、裏側で GitHub Actions を利用してさまざまな Azure リソースを作成しアプリケーションをデプロイします。デプロイ先のインフラストラクチャとして、App Services, Container Apps, Static Web Apps が選択できます。

今回のサンプルアプリケーションは、フロントエンドと API 用に2つの　Azure App Services(Web Apps)が利用されています。他にも、データ保管用の CosmosDB、シークレットの保存に KeyVault、アプリケーションの監視に Azure Monitor が利用できます。

https://github.com/AoTo0330/AppSpacesPython/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/0261d0e2-0b1e-5d8c-063e-aedbdbc3bc68.png)

App Spaces のデプロイはとても簡単で、接続先の GitHub の情報と App Spaces の名前、デプロイする先のサブスクリプションとリージョンを指定するだけです。これにより、GitHub 上で用意されたアプリケーションが`azure.yml`の内容に従ってデプロイされます。

![AppSpacesDeploy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/fb874025-9047-8d8a-1bc8-77b54745d048.png)

:::note info
サンプルアプリケーションを選択すると、接続先の GitHub アカウント上に新規のリポジトリを作成し、同時に App Spaces のリソースの作成を開始します。
![AppSpacesSample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/75679243-c8b3-5b9c-a457-3ca35fc38730.png)
:::


今回はリポジトリの`src`配下にある JavaScript の Web アプリケーションと　Python の API アプリケーションが、それぞれ App Service(Web Apps)にデプロイされるように`azure.yml`に定義されています。

<details><summary>azure.yml の詳細</summary>

```azure.yml
name: todo-python-mongo
metadata:
  template: todo-python-mongo@0.0.1-beta
services:
  web:
    project: ./src/web
    dist: build
    language: js
    host: appservice
  api:
    project: ./src/api
    language: py
    host: appservice
```
</details>

デプロイは自動的に実行され、App Service(Web Apps)を中心としたリソースが同一の Resource Group に設定されます。作成されたリソースは App Spaces の画面や、Resource Group の管理画面で一覧として表示可能です。

![Resouces.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/334525a9-8607-afde-f301-0a597bc335ca.png)
![ResourceGroup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/043760fb-8fb3-c180-9b95-43b728b84eca.png)

## Azure Developer CLI の利用
### 概要
サンプルアプリケーションでは GitHub Actions の [Workflow](https://docs.github.com/ja/actions/using-workflows/about-workflows) を利用できるよう、`workflows/azure-dev.yml`が定義されいます。

これにより、main・master ブランチのアプリケーションコードに変更があった際に GitHub Actions を利用してアプリケーションコードのビルドとデプロイが実現できます。この GitHub Actions の定義の中では、[Azure Developer CLI](https://learn.microsoft.com/ja-jp/azure/developer/azure-developer-cli/overview) が利用されています。
<details><summary>azure-dev.yml の中身</summary>

```workflows/azure-dev.yml
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
    container:
      image: mcr.microsoft.com/azure-dev-cli-apps:latest
    env:
      AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }}
      AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }}
      AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
      AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - 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
        env:
          AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
          AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
          AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
          AZURE_RESOURCE_GROUP: ${{ vars.AZURE_RESOURCE_GROUP }}
          AZURE_TAGS: ${{ secrets.AZURE_TAGS }}

      - name: Deploy Application
        run: azd deploy --no-prompt
        env:
          AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
          AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
          AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
          AZURE_RESOURCE_GROUP: ${{ vars.AZURE_RESOURCE_GROUP }}
```

</details>

:::note warn
初回デプロイ時は、App Spaces から自動的に [GitHub Actions の変数](https://docs.github.com/ja/rest/actions/variables)が書き込まれます。そのため、一度利用したリポジトリの App Spaces リソースを削除し、再度デプロイを行おうとすると、GitHub Actions 変数が既に存在するというメッセージが表示されます。
これは、GitHub のリポジトリ上で関連する環境変数を削除することで解消できます。

![AlreadyExistsError.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/61d23d77-181c-fca7-6a1f-33ace0a88a2f.png)
:::

### Azure Developer CLI とは
Azure Developer CLI は`azd`で始まるコマンドにより、Azure へのアプリケーションのデプロイを簡素化するための開発者ツールです。上記の`azure-dev.yml`では、`azd auth login`, `azd provision`, `azd deploy`が利用されており、App Spaces 上ではこれらの実行結果が確認できます。

[公式ドキュメント](https://learn.microsoft.com/ja-jp/azure/developer/azure-developer-cli/overview)や`azd --help`コマンドで確認できますが、`azd auth login`はデプロイ先となる Azure サブスクリプションへの認証、`azd provision`は Azure リソースの作成、 `azd deploy`はアプリケーションのデプロイを行うための操作です。

:::note info
`azd up`コマンドを利用することで、Azure リソースの作成とアプリケーションのデプロイを同時に行うことも可能です。
:::

また、App Spaces の画面を確認すると、それぞれ [Log in with Azure], [Provision Infrastructure], [Deploy Application] でこれらのコマンドの実行状況をリアルタイムで確認できます。
これらに加えて、前後でジョブを実行するためのコンテナが作成・削除されていることがわかります。

![Deploying.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/1b75e88d-cd72-8236-74fe-7ab0210f1fe4.png)

これらの定義は、`pipeline/azure-dev.yml`で確認・編集可能です。

<details><summary>azure-dev.yml の中身</summary>

```pipeline/azure-dev.yml
# Run when commits are pushed to mainline branch (main or master)
# Set this to the mainline branch you are using
trigger:
  - main
  - master

# Azure Pipelines workflow to deploy to Azure using azd
# To configure required secrets for connecting to Azure, simply run `azd pipeline config --provider azdo`

pool:
  vmImage: ubuntu-latest

# Use azd provided container image that has azd, infra, multi-language build tools pre-installed.
container: mcr.microsoft.com/azure-dev-cli-apps:latest

steps:
  - pwsh: |
      azd config set auth.useAzCliAuth "true"
    displayName: Configure AZD to Use AZ CLI Authentication.

  - task: AzureCLI@2
    displayName: Provision Infrastructure
    inputs:
      azureSubscription: azconnection
      scriptType: bash
      scriptLocation: inlineScript
      inlineScript: |
        azd provision --no-prompt
    env:
      AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
      AZURE_ENV_NAME: $(AZURE_ENV_NAME)
      AZURE_LOCATION: $(AZURE_LOCATION)
      
  - task: AzureCLI@2
    displayName: Deploy Application
    inputs:
      azureSubscription: azconnection
      scriptType: bash
      scriptLocation: inlineScript
      inlineScript: |
        azd deploy --no-prompt
    env:
      AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
      AZURE_ENV_NAME: $(AZURE_ENV_NAME)
      AZURE_LOCATION: $(AZURE_LOCATION)
```
</details>

## Azure インフラストラクチャのデプロイ
Azure Developer CLI と実際の`azure-dev.yml`ファイルを定義を覗いてみることで、App Spaces の裏側で行われていることが少し分かってきたのではないでしょうか。

ここで、App Spaces によってデプロイされるアプリケーション以外のインフラストラクチャにも注目してみましょう。

今回のサンプルアプリケーションでは、ToDo リストのデータ保管用に CosmosDB、シークレットの保存に KeyVault、アプリケーションの監視に Azure Monitor が作成されています。これらのリソースはどのように定義され、作成されるのでしょうか？

GitHub で作成されたリポジトリを確認することで、その答えを確認することができます。


### Bicep による宣言
リポジトリの`infra` 配下を見てみると、Azure リソースを宣言型の構文で定義しデプロイできる [Bicep](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/overview) によって書かれたファイルが見つけられます。[^KEY]
[^KEY]:その他にも、パラメータは JSON 形式で定義されています

これらの Bicep ファイルのテンプレートは [Azure Developer CLI の GitHub リポジトリ](https://github.com/Azure/azure-dev/tree/main/templates/common/infra/bicep/core)から確認できるため、Bicep によるデプロイを行ったことがなくてもテンプレートを参照してカスタマイズが可能です。

今回デプロイされているリソースのテンプレートは、`database/cosmos`に CosmosDB、`host`に Web Apps、`security`に KeyVault があり、これらの内容をまとめて`main.bicep`から指定してそれぞれのデプロイを実行することができます。

このように、Azure Developer CLI ではドメイン固有言語(DSL)である Bicep を利用することで Infrastructure as Code(IaC) を実現しています。これにより、インフラストラクチャとアプリケーションを同時に CI/CD に組み込み、アプリケーションをデプロイすることができるのです。

## おわりに
Azure App Spaces が単に GitHub リポジトリ上のアプリケーションコードから Azure プラットフォームにアプリケーションをデプロイするだけのサービスでないことを実感いただけたのではないでしょうか？

Azure App Spaces は Azure Developer CLI と統合されたサービスです。Azure 上のインフラストラクチャとアプリケーションをコードに定義して、デプロイする様子を App Spaces コンソールから一元的に管理できます。さらに、これらのデプロイを GitHub Actions と統合することによって、よりスムーズにアプリケーションの変更や修正を行うことができます。

Azure プラットフォームでのアプリケーション開発や Azure Developer CLI, GitHub Actions の利用を検討されている・やってみたい方は、この機会に App Spaces でデビューしてみてはいかがでしょうか？