インフラストラクチャを IaC テンプレートに変換する方法

サービス コネクタは、ユーザーが数回クリックするか、コマンドを実行するだけで、コンピューティング サービスをターゲット バッキング サービスに接続するのに役立ちます。 使用開始から運用ステージに移行するとき、ユーザーは、手動構成から、CI/CD パイプラインでコードとしてのインフラストラクチャ (IaC) テンプレートを使用するように移行する必要もあります。 このガイドでは、接続された Azure サービスを IaC テンプレートに変換する方法について説明します。

前提条件

ソリューションの概要

通常、インフラストラクチャから IaC テンプレートへの変換に含まれる 2 つの主要な部分は、ソースとターゲットのサービスをプロビジョニングするロジックと、接続を構築するためのロジックです。 ソースとターゲットのサービスをプロビジョニングするロジックを実装するには、2 つのオプションがあります。

  • テンプレートを最初から作成する
  • Azure からテンプレートをエクスポートして洗練させる

接続を構築するロジックを実装するには、次の 3 つのオプションがあります。

  • Service Connector を使用し、App Configuration に構成を格納する
  • テンプレートで Service Connector を使用する
  • テンプレート ロジックを使用してソースとターゲットのサービスを直接構成する

これらの異なるオプションを組み合わせて、異なるソリューションを生成できます。 サービス コネクタでの IaC の制限のため、以下に示す順序で次のソリューションを実装することをお勧めします。 これらのソリューションを適用するには、IaC ツールとテンプレート作成文法を理解している必要があります。

ソリューション ソースとターゲットをプロビジョニングする 接続を構築する 該当するシナリオ 長所 デメリット
1 最初から作成する Service Connector を使用して、App Configuration に構成を格納する ライブ トラフィックを許可する前に、クラウド リソースのライブ性チェックを行う - テンプレートはシンプルで読みやすい
- Service Connector によって付加価値が得られる
- Service Connector によって IaC の問題が発生しない
- App Configuration から構成を読み取るために追加の依存関係が必要
- クラウド リソースのライブ性をチェックするためのコスト
2 最初から作成する サービス コネクタを使用する ライブ トラフィックを許可する前に、クラウド リソースのライブ性チェックを行う - テンプレートはシンプルで読みやすい
- Service Connector によって付加価値が得られる
- クラウド リソースのライブ性をチェックするためのコスト
3 最初から作成する テンプレートでソースとターゲットのサービスを直接構成する クラウド リソースのライブ性チェックはない - テンプレートはシンプルで読みやすい - サービス コネクタの機能を使用できない
4 エクスポートして完成させる Service Connector を使用して、App Configuration に構成を格納する ライブ トラフィックを許可する前に、クラウド リソースのライブ性チェックを行う - リソースがクラウドとまったく同じである
- Service Connector によって付加価値が得られる
- Service Connector によって IaC の問題が発生しない
- App Configuration から構成を読み取るために追加の依存関係が必要
- クラウド リソースのライブ性をチェックするためのコスト
- ARM テンプレートのみをサポートする
- テンプレートを理解して完成させる作業が必要である
5 エクスポートして完成させる サービス コネクタを使用する ライブ トラフィックを許可する前に、クラウド リソースのライブ性チェックを行う - リソースがクラウドとまったく同じである
- Service Connector によって付加価値が得られる
- クラウド リソースのライブ性をチェックするためのコスト
- ARM テンプレートのみをサポートする
- テンプレートを理解して完成させる作業が必要である
6 エクスポートして完成させる テンプレートでソースとターゲットのサービスを直接構成する クラウド リソースのライブ性チェックはない - リソースがクラウドとまったく同じである - ARM テンプレートのみをサポート
- テンプレートを理解して完成させる作業がある
- サービス コネクタの機能を使用できない

テンプレートの作成

以降のセクションでは、Web アプリとストレージ アカウントを作成し、Bicep を使ってそれらをシステム割り当て ID に接続する方法について説明します。 Service Connector とテンプレート ロジックの両方を使用して、これを行う方法が示されています。

ソース サービスとターゲット サービスをプロビジョニングする

最初から作成する

テンプレートを最初から作成することは、簡単に始められ、テンプレートが簡単で読みやすくなるため、ソースとターゲットのサービスをプロビジョニングするための望ましく、推奨される方法です。 次に示すのは、最小限のパラメーター セットを使って、Web アプリとストレージ アカウントを作成する例です。

// This template creates a webapp and a storage account.
// In order to make it more readable, we use only the mininal set of parameters to create the resources.

param location string = resourceGroup().location
// App Service plan parameters
param planName string = 'plan_${uniqueString(resourceGroup().id)}'
param kind string = 'linux'
param reserved bool = true
param sku string = 'B1'
// Webapp parameters
param webAppName string = 'webapp-${uniqueString(resourceGroup().id)}'
param linuxFxVersion string = 'PYTHON|3.8'
param identityType string = 'SystemAssigned'
param appSettings array = []
// Storage account parameters
param storageAccountName string = 'account${uniqueString(resourceGroup().id)}'


// Create an app service plan 
resource appServicePlan 'Microsoft.Web/serverfarms@2022-09-01' = {
  name: planName
  location: location
  kind: kind
  sku: {
    name: sku
  }
  properties: {
    reserved: reserved
  }
}


// Create a web app
resource appService 'Microsoft.Web/sites@2022-09-01' = {
  name: webAppName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: linuxFxVersion
      appSettings: appSettings
    }
  }
  identity: {
    type: identityType
  }
}


// Create a storage account
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
}

エクスポートして完成させる

プロビジョニングするリソースが、クラウド内のリソースとまったく同じである場合は、Azure からテンプレートをエクスポートする方法もあります。 このアプローチの 2 つの前提は、リソースが Azure に存在することと、IaC に ARM テンプレートを使用することです。 [Export template] ボタンは、通常、Azure portal のサイドバーの下部にあります。 エクスポートされる ARM テンプレートには、サービス コネクタによって構成された設定など、リソースの現在の状態が反映されています。 通常、エクスポートされたテンプレートを完成させるには、リソースのプロパティについて知っている必要があります。

Azure portal のスクリーンショット。Web アプリの arm テンプレートをエクスポートしています。

接続ロジックを構築する

Service Connector を使用し、App Configuration に構成を格納する

App Configuration を使用して構成を格納すると、当然ながら IaC シナリオがサポートされます。 そのため、可能であれば、この方法を使用して IaC テンプレートを構築することをお勧めします。

簡単なポータルの手順については、この App Configuration チュートリアルを参照してください。 この機能を bicep ファイルに追加するには、Service Connector ペイロードに App Configuration ID を追加します。

resource webApp 'Microsoft.Web/sites@2022-09-01' existing = {
  name: webAppName
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = {
  name: storageAccountName
}

resource appConfiguration 'Microsoft.AppConfiguration/configurationStores@2023-03-01' existing = {
  name: appConfigurationName
}

resource serviceConnector 'Microsoft.ServiceLinker/linkers@2022-05-01' = {
  name: connectorName
  scope: webApp
  properties: {
    clientType: 'python'
    targetService: {
      type: 'AzureResource'
      id: storageAccount.id
    }
    authInfo: {
      authType: 'systemAssignedIdentity'
    }
    configurationInfo: {
      configurationStore: {
        appConfigurationId: appConfiguration.id
      }
    }
  }
}

サービス コネクタの使用

サービス コネクタの IaC の制限がシナリオに関係ない場合は、サービス コネクタを使ってソースとターゲットのサービス間の接続を作成することをお勧めします。 Service Connector を使うと、テンプレートがより簡単になり、接続の正常性検証などの追加の要素も提供されます。これは、テンプレート ロジックを使って接続を直接構築する場合は使用できません。

// The template builds a connection between a webapp and a storage account 
// with a system-assigned identity using Service Connector

param webAppName string = 'webapp-${uniqueString(resourceGroup().id)}'
param storageAccountName string = 'account${uniqueString(resourceGroup().id)}'
param connectorName string = 'connector_${uniqueString(resourceGroup().id)}'

// Get an existing webapp
resource webApp 'Microsoft.Web/sites@2022-09-01' existing = {
  name: webAppName
}

// Get an existig storage
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = {
  name: storageAccountName
}

// Create a Service Connector resource for the webapp 
// to connect to a storage account using system identity
resource serviceConnector 'Microsoft.ServiceLinker/linkers@2022-05-01' = {
  name: connectorName
  scope: webApp
  properties: {
    clientType: 'python'
    targetService: {
      type: 'AzureResource'
      id: storageAccount.id
    }
    authInfo: {
      authType: 'systemAssignedIdentity'
    }
  }
}

サービス コネクタ リソースを作成するときに必要なプロパティと値の形式については、正しいパラメーターを指定する方法に関する記事を確認してください。 Azure portal でサービス コネクタ リソースを作成するときに、ARM テンプレートをプレビューしてダウンロードし、参考にすることもできます。

Azure portal のスクリーンショット。Service Connector リソースの arm テンプレートをエクスポートしています。

テンプレート ロジックの使用

Service Connector の IaC の制限が問題になるシナリオでは、テンプレート ロジックを使って接続を直接構築することを検討します。 次のテンプレートは、システム割り当て ID を使ってストレージ アカウントを Web アプリに接続する方法を示す例です。

// The template builds a connection between a webapp and a storage account 
// with a system-assigned identity without using Service Connector

param webAppName string = 'webapp-${uniqueString(resourceGroup().id)}'
param storageAccountName string = 'account${uniqueString(resourceGroup().id)}'
param storageBlobDataContributorRole string  = 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'

// Get an existing webapp
resource webApp 'Microsoft.Web/sites@2022-09-01' existing = {
  name: webAppName
}

// Get an existing storage account
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = {
  name: storageAccountName
}

// Operation: Enable system-assigned identity on the source service
// No action needed as this is enabled when creating the webapp

// Operation: Configure the target service's endpoint on the source service's app settings
resource appSettings 'Microsoft.Web/sites/config@2022-09-01' = {
  name: 'appsettings'
  parent: webApp
  properties: {
    AZURE_STORAGEBLOB_RESOURCEENDPOINT: storageAccount.properties.primaryEndpoints.blob
  }
}

// Operation: Configure firewall on the target service to allow the source service's outbound IPs
// No action needed as storage account allows all IPs by default

// Operation: Create role assignment for the source service's identity on the target service
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  scope: storageAccount
  name: guid(resourceGroup().id, storageBlobDataContributorRole)
  properties: {
    roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', storageBlobDataContributorRole)
    principalId: webApp.identity.principalId
  }
}

テンプレート ロジックを使って接続を直接構築する場合、テンプレート ロジックは Service Connector のバックエンド操作と同等であるため、認証の種類ごとに Service Connector によって行われることを理解しておくことが重要です。 次の表では、認証の種類ごとにテンプレート ロジックに変換する必要がある操作の詳細を示します。

Auth type サービス コネクタの操作
シークレット/接続文字列 - ソース サービスのアプリの設定で、ターゲット サービスの接続文字列を構成する
- ソース サービスのアウトバウンド IP を許可するように、ターゲット サービスのファイアウォールを構成する
システム割り当てマネージド ID - ソース サービスのアプリの設定で、ターゲット サービスのエンドポイントを構成する
- ソース サービスのアウトバウンド IP を許可するように、ターゲット サービスのファイアウォールを構成する
- ソース サービスでシステム割り当て ID を有効にする
- ターゲット サービスでソース サービスの ID に対するロールの割り当てを作成する
ユーザー割り当てマネージド ID - ソース サービスのアプリの設定で、ターゲット サービスのエンドポイントを構成する
- ソース サービスのアウトバウンド IP を許可するように、ターゲット サービスのファイアウォールを構成する
- ユーザー割り当て ID をソース サービスにバインドする
- ターゲット サービスでユーザー割り当て ID に対するロールの割り当てを作成する
サービス プリンシパル - ソース サービスのアプリの設定で、ターゲット サービスのエンドポイントを構成する
- ソース サービスのアプリの設定で、サービス プリンシパルのアプリ ID とシークレットを構成する
- ソース サービスのアウトバウンド IP を許可するように、ターゲット サービスのファイアウォールを構成する
- ターゲット サービスでサービス プリンシパルに対するロールの割り当てを作成する