Azure Stack Development Kit に App Service をデプロイしてみた


# はじめに
この記事では、Azure Stack Development Kit (ASDK) に App Service 実行環境を作成した際の気づきなどを公開します。
ASDK での作業になりますが、機能の限定された Azure Stack Hub であり、参照しているドキュメントも Azure Stack Hub のものを使用します。

作業としては、App Service の内部で使用している仮想マシンを自分でデプロイしていく作業になります。App Service Environment に詳しい人は何となく想像が付くかも知れませんが、[Inside the Azure App Service Architecture](https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/february/azure-inside-the-azure-app-service-architecture) が参考になるでしょう。

# App Service on Azure Stack Hub のデプロイの前提条件
App Service を ASDK にデプロイするに当たって、いくつか事前準備が必要となるため、準備が整っているか確認します。


## リソース プロバイダーの前提条件
参考：[リソース プロバイダーの前提条件](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#resource-provider-prerequisites)

Azure Stack は展開するテンプレートやサービスをあらかじめ Marketplace からダウンロードしておく必要があります。
そのため、以下の手順を確認しておきましょう。Marketplace からのダウンロードに関しては後ほど実際にイメージをダウンロードするので一旦飛ばしても問題ありません。
1. [Azure Stack Hub インスタンスを Azure に登録します](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-registration?view=azs-2102)
2. [Azure から Marketplace 項目をダウンロードして Azure Stack Hub に発行する方法](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-download-azure-marketplace-item?view=azs-2102)に関するページを確認してください
3. Azure Active Directory (Azure AD) ホーム ディレクトリを更新は以下の手順で実施します。


[Azure Stack Hub Tools リポジトリ](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-powershell-download?view=azs-2102) は ASDK 導入時に、既に C:\AzureStack-Tools-az に展開されているので、パスします。
[Azure Stack Hub Azure AD ホーム ディレクトリの更新](https://github.com/Azure/AzureStack-Tools/tree/master/Identity#updating-the-azure-stack-aad-home-directory-after-installing-updates-or-new-resource-providers
) に関しては、GitHub のドキュメントに従って作業を行います。

"***outlook.onmicrosoft.com" の部分にお使いの Azure AD テナント名を入れて、以下のコマンドを実行します。コマンド実行時に、Azure へのログインを求められる場合があるので適宜確認します。

```powershell
cd C:\AzureStack-Tools-az\Identity

Import-Module ..\Connect\AzureStack.Connect.psm1
Import-Module ..\Identity\AzureStack.Identity.psm1

$adminResourceManagerEndpoint = "https://adminmanagement.local.azurestack.external"

# This is the primary tenant Azure Stack is registered to:
$homeDirectoryTenantName = "***outlook.onmicrosoft.com"

Update-AzsHomeDirectoryTenant -AdminResourceManagerEndpoint $adminResourceManagerEndpoint `
   -DirectoryTenantName $homeDirectoryTenantName -Verbose
```

[Enabling AAD Multi-Tenancy in Azure Stack](https://github.com/Azure/AzureStack-Tools/tree/master/Identity#enabling-aad-multi-tenancy-in-azure-stack) という手順もありますが、1 つの Azure Stack を複数の Azure AD テナントからアクセスを許可する場合の手順なので割愛します。

## Azure Stack Hub に Marketplace の項目をダウンロードする
参考：[Azure Stack Hub に Marketplace の項目をダウンロードする](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-download-azure-marketplace-item?view=azs-2102&tabs=az1%2Caz2&pivots=state-connected)

Azure Stack を展開するに当たり、以下の Marketplace アイテムが必要となります。ダウンロードには時間がかかるため、事前に設定することをお勧めします (127 GB ダウンロードするのにおおよそ 2時間程度は必要です)。

```
- {WS-PAYG} SQL Server 2016 SP2 Enterprise on Windows Server 2016
- Windows Server 2016 Datacenter-Pay as you go
- Windows Server 2016 Datacenter - Server Core-Pay as you go
- Custom Script Extension
- PowerShell Desired State Configuration
- SqlIaaSExtension
```

### ポータルを使用して Marketplace 項目をダウンロードする
参照：[ポータルを使用して Marketplace 項目をダウンロードする](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-download-azure-marketplace-item?view=azs-2102&tabs=az1%2Caz2&pivots=state-connected#use-the-portal-to-download-marketplace-items)

Azure Stack Hub 管理者ポータルにアクセスして、[Marketplace items] > [Add from Azure] からダウンロードすることが出来ます。
並行で複数の項目をダウンロードした場合、タイムアウトしてやり直しと言うこともあるので、必要に応じて別のマシンからのダウンロード (切断済環境での実施方法) も検討してください。

### 別のマシンでマーケットプレイスアイテムをダウンロードする
参照：[ポータルを使用して Marketplace 項目をダウンロードする](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-download-azure-marketplace-item?view=azs-2102&tabs=az1%2Caz2&pivots=state-disconnected#use-the-portal-to-download-marketplace-items)

Azure Stack Hub を実行しているマシンからのダウンロードは失敗したので、別の環境でダウンロードしてインポートしてみます。

#### ダウンロードする環境での操作
まず必要な PowerShell モジュールを管理者権限でインストールします。

```powershell
Install-Module -Name Azs.Syndication.Admin
Install-Module -Name Az.Resources　-RequiredVersion 0.11.0 -Force
```

これからは一般ユーザーで実施できます。Azure にログインして、ダウンロード項目を選択します。

```powershell
Connect-AzAccount -Environment AzureCloud -Tenant '<mydirectory>.onmicrosoft.com'
Get-AzSubscription -SubscriptionID 'Your Azure Subscription GUID' | Select-AzSubscription

Import-Module Az.Resources -RequiredVersion 0.11.0
# "Azs.Syndication.Admin" の依存関係で、Import-Module : バージョンが '0.11.0' である、必要なモジュール 'Az.Resources' が読み込まれていません。 となるため
Import-Module Azs.Syndication.Admin
$products = Select-AzsMarketplaceItem
```
ウィンドウが開くので、インストール先の Azure Stack を選ぶ。次に、ダウンロードするアイテム一覧が出てくるので選ぶ。

```powershell
参考：
PS C:\Users\shogo> echo $products
/subscriptions/d7fd6cbe-64aa-4482-bc35-935c34e01562/resourceGroups/azurestack/providers/Microsoft.AzureStack/registrations/AzureStackRegistration1/products/microsoft.windowsserver2016-datacenter-server-core-payg-14393.4651.2109130103
/subscriptions/d7fd6cbe-64aa-4482-bc35-935c34e01562/resourceGroups/azurestack/providers/Microsoft.AzureStack/registrations/AzureStackRegistration1/products/microsoft.sqlserver2016sp2enterprisewindowsserver2016-arm-13.2.20210811
/subscriptions/d7fd6cbe-64aa-4482-bc35-935c34e01562/resourceGroups/azurestack/providers/Microsoft.AzureStack/registrations/AzureStackRegistration1/products/microsoft.windowsserver2016-datacenter-payg-14393.4651.2109130103
/subscriptions/d7fd6cbe-64aa-4482-bc35-935c34e01562/resourceGroups/azurestack/providers/Microsoft.AzureStack/registrations/AzureStackRegistration1/products/microsoft.customscriptextension-arm-1.9.3
/subscriptions/d7fd6cbe-64aa-4482-bc35-935c34e01562/resourceGroups/azurestack/providers/Microsoft.AzureStack/registrations/AzureStackRegistration1/products/microsoft.dsc-arm-2.77.0.0
/subscriptions/d7fd6cbe-64aa-4482-bc35-935c34e01562/resourceGroups/azurestack/providers/Microsoft.AzureStack/registrations/AzureStackRegistration1/products/microsoft.sqliaasextension-1.3.20710
PS C:\Users\shogo>
```

ダウンロードの開始

```powershell
$products | Export-AzsMarketplaceItem  -RepositoryDir "Destination folder path in quotes"

# 実行例
$products | Export-AzsMarketplaceItem  -RepositoryDir "D:\asdk.marketplace"
```

ダウンロード前にライセンスの確認を求められる。Yes と回答するとダウンロードは行われるので、しばらく待つ。
127GB のイメージをダウンロードした際、3MB/s ぐらいでダウンロードするのでとにかく時間がかかる (1イメージあたり光回線で 2時間ぐらい)。
ただし、遅いのは前半だけで後半はかなり高速でダウンロードされるため、ディスク側の書き込み速度に依存する。おそらく、仮想マシンイメージをそのままダウンロードする際、データが記録されるところは遅いが、後半は null なのでかなり圧縮が効いてるためと考えられる。

上で保存したフォルダをポータブル HDD 等にコピーして、ASDK が動作しているマシンに移植する。


#### ダウンロードのインポートと Azure Stack Hub Marketplace への発行
参考：[PowerShell を使用したダウンロードのインポートと Azure Stack Hub Marketplace への発行](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-download-azure-marketplace-item?view=azs-2102&tabs=az1%2Caz2&pivots=state-disconnected#import-the-download-and-publish-to-azure-stack-hub-marketplace-using-powershell)

指定するパスは Export-AzsMarketplaceItem で保存したフォルダをコピーした物。個別のイメージではなく、ダウンロードフォルダに入っているイメージが全てインポートされる。

```powershell
Import-AzsMarketplaceItem -RepositoryDir "Source folder path in quotes"

# 実行例 (USB HDD)
Import-AzsMarketplaceItem -RepositoryDir "G:\asdk.marketplace"
```

インポートにもそれなりに時間がかかるのでしばらく放置しましょう。


## インストーラーとヘルパー スクリプト 
参考：[インストーラーとヘルパー スクリプト](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#installer-and-helper-scripts)

後ほど使用するファイルなのでここで入手しておきます。

```powershell
Invoke-WebRequest -Uri https://aka.ms/appsvconmashelpers -OutFile C:\AppServiceHelperScripts.zip
Invoke-WebRequest -Uri https://aka.ms/appsvconmasinstaller -OutFile C:\AppService.exe
```


## ファイル サーバーを準備する
参考：[ファイル サーバーを準備する](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#prepare-the-file-server)

App Service が使用するファイルサーバーを準備します。ASDK はクラスターが構成されていないので、[ASDK 上の Azure App Service のデプロイ用のファイル サーバーのクイック スタート テンプレート](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#quickstart-template-for-file-server-for-deployments-of-azure-app-service-on-asdk) に従って、単体構成のファイルサーバーが構成可能です。

ただし、ここでは [高可用性ファイル サーバーと SQL Server のクイック スタート テンプレート](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#quickstart-template-for-highly-available-file-server-and-sql-server) を使用して SQL サーバーと一緒にデプロイします。

ARM テンプレート "appservice-fileserver-sqlserver-ha" では Windows Server 2016, SQL Server 2016 SP2 が使用されており、Marketplace からあらかじめダウンロードしておく必要があります。

```
This template uses Azure Stack Marketplace images. These need to be available on your Azure Stack instance:

    Windows Server 2016 Datacenter Core Image (for AD and File Server VMs)
    SQL Server 2016 SP2 on Windows Server 2016 (Enterprise)
    Latest SQL IaaS Extension 1.2.x (currently 1.2.30)
    Latest PowerShell Desired State Configuration Extension (currently 2.76.0)
```


ASDK 管理ポータルで、[+ Create a resouce] > Custom > Template deployment を選択
"Load a GitHub quickstart template" で "appservice-fileserver-sqlserver-ha" を選択して、[Select template] をクリック。

基本は既定値を使用。変更したのはリソースグループ名とパスワード程度 (以下のリストの先頭が "+" になっている項目)
パスワードは大文字小文字、数字、記号のうち 3 つ以上を含む 8 ~ 123 文字。コピペを前提として、ジェネレータで 12 文字のパスワードを作成して使用しました。

```
+ Resouce group      : asdk.appsvc
- Region             : local
- Name prefix        : aps
- Domain Vm Size     : Standard_DS1_v2
- Fil Server Vm Size : Standard_DS2_v2
- Sql Server Vm Size : Standard_DS2_v2
- Domain name        : appsvc.local
- Admin Username     : appsvcadmin
+ Admin Password     : ************

- File Share Owner User Name: FileShareOwner
+ File Share Owner Password : ************
- File Share User User Name : FileShareUser
+ File Share User Password  : ************

- Sql Server Service Account User Name: svcSQL
+ Sql Server Service Account Password : ************
- Sql Login                           : sqlsa
+ Sql Login Password                  : ************
- Sofs Name                           : fs01
- Share Name                          : WebSites

- Artifacts Location           : https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/appservice-fileserver-sqlserver-ha
- Artifacts Location Sas Token :
- Location                     : [resourceGroup().location]
```

後は preview が通れば、create して、しばらく待ちます。


デプロイ時に、必要なイメージがマーケットプレイスから入手されていない場合、以下のようなエラーが返ります。
ARM テンプレートの指定は以下になっているので参考まで (表示されているイメージ名と、Marketplace Item で参照できる名前が違うというのが非常に分かりづらい)
> "defaultValue": "2016-Datacenter-Server-Core", "SQL2016SP2-WS2016"

```powershell
Error PlatformImageNotFound
MessageThe platform image 'MicrosoftWindowsServer:WindowsServer:2016-Datacenter-Server-Core:latest' is not available. Verify that all fields in the storage profile are correct. For more details about storage profile information, please refer to https://aka.ms/storageprofile
```

パスワード要件を満たしていない場合、以下のようなエラーが返ります。

```
Error InvalidParameter
The supplied password must be between 8-123 characters long and must satisfy at least 3 of password complexity requirements from the following:
 1) Contains an uppercase character
 2) Contains a lowercase character
 3) Contains a numeric digit
 4) Contains a special character
 5) Control characters are not allowed
```

## Azure での Azure App Service のデプロイメントに必要な証明書
参考：[Azure での Azure App Service のデプロイメントに必要な証明書](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#certificates-and-server-configuration-asdk)

App Service が公開するサイト、各種 API 等で使用する証明書を作成します。

```powershell
cd C:\AppServiceHelperScripts
.\Create-AppServiceCerts.ps1
```

```
PfxPassword: asdk
DomainName: local.azurestack.external
```

パスワードは設定しないと、App Service Resouce Provider の登録で先に進めないので注意が必要です。
成功すると、スクリプトを実行したフォルダに 4 つの pfx ファイルが作成されます({_, api, ftp, sso}.appservice.local.azurestack.external.pfx)


## Azure Stack Hub 用の Azure Resource Manager ルート証明書を取得する
参考：[Azure Stack Hub 用の Azure Resource Manager ルート証明書を取得する](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#retrieve-the-azure-resource-manager-root-certificate-for-azure-stack-hub)

管理者権限で実行する

```powershell
C:\AppServiceHelperScripts
.\Get-AzureStackRootCert.ps1
```

```
PrivilegedEndpoint: AzS-ERCS01
ログインプロンプトが開くので、以下を応答する
ユーザー　: AzureStack\CloudAdmin
パスワード: (ASDK Admionistorator パスワード)
```

上手く行くと、スクリプトを実行したフォルダに AzureStackCertificationAuthority.cer という名前でルート証明書が作成されます。


## 仮想ネットワーク
参考：[仮想ネットワーク](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#virtual-network)

App Service 基盤構築のために仮想ネットワークで使用するサブネット名や大きさが決められている。
先の "appservice-fileserver-sqlserver-ha" テンプレートを使用した場合、File Server, SQL Server と一緒に仮想ネットワーク aps-vnet として準備済のため割愛。


## Azure AD アプリを作成する
参考：[Azure AD アプリを作成する](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#create-an-azure-ad-app)

```powershell
cd C:\AppServiceHelperScripts
.\Create-AADIdentityApp.ps1
```

```
# 設定例
DirectoryTenantName: ***outlook.onmicrosoft.com
AdminArmEndpoint: adminmanagement.local.azurestack.external
TenantArmEndpoint: management.local.azurestack.external
CertificateFilePath: C:\AppServiceHelperScripts\sso.appservice.local.azurestack.external.pfx
CertificatePassword: asdk
```

Azure へのサインインを求められて、最後にアプリケーション ID が応答されるので、記録しておく。

```
Please note Application Id: e4bc7c3f-****-****-****-************
Sign in to the Azure portal as Azure Active Directory Service Admin -> Search for Application Id and grant permissions.
e4bc7c3f-****-****-****-************
```

Azure ポータルから [Azure Active Directory] を開いて、[エンタープライズ アプリケーション] > [すべてのアプリケーション] を開く。先に提供されたアプリケーション ID を元にアプリケーションを探す。
![20211202-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/1825a610-2f4f-3bd2-3e12-d31715dfbbf8.jpeg)

[App Service] と言う項目が見つかるため、選択して、[アクセスの許可] > [既定のディレクトリに管理者の同意を与えます] をクリック。
![20211202-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/c7c2f482-5762-30a6-3f41-789e53e52919.jpeg)


Get-AzureRmEnvironment がないと言われた場合、AzureRM.profile が必要。

```
Get-AzureStackEnvironment : The term 'Get-AzureRmEnvironment' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
correct and try again.
```

```powershell
# https://www.powershellgallery.com/packages/AzureRM.profile
Install-Module -Name AzureRM.profile -AllowClobber
```

## ADFS アプリを作成する
参考：[ADFS アプリを作成する](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#create-an-adfs-app)

```powershell
cd C:\AppServiceHelperScripts
.\Create-ADFSIdentityApp.ps1
```

```
## 設定例
AdminArmEndpoint: adminmanagement.local.azurestack.external
PrivilegedEndpoint: AzS-ERCS01
CloudAdminCredential: Azurestack\CloudAdmin

CertificateFilePath: C:\AppServiceHelperScripts\sso.appservice.local.azurestack.external.pfx
CertificatePassword: asdk
```

こちらも設定完了後に、アプリケーション ID が発行されるので記録しておく。
```
Please note Application Id: d50f3c77-f68d-4cb2-ad7f-206cc5af3069
d50f3c77-f68d-4cb2-ad7f-206cc5af3069
```

## Azure Marketplace からの項目のダウンロード
参考：[Azure Marketplace からの項目のダウンロード](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-before-you-get-started?view=azs-2102&pivots=state-connected#download-items-from-the-azure-marketplace)

App Service が内部で使用する Windows Server 等のダウンロード。先の [Marketplace 項目をダウンロードする]()でダウンロードしているため割愛。

```
 1. Windows Server 2016 Datacenter VM イメージの最新バージョン。
 2. カスタム スクリプト拡張機能 v1.9.1 以上。 この項目は VM 拡張機能です。
Windows Server Core は、Azure App Service on Azure Stack Hub で使用するためにサポートされているプラットフォーム イメージではありません。
```


# Azure Stack Hub に App Service をデプロイする
参考：[Azure Stack Hub に App Service をデプロイする](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-deploy?view=azs-2102&pivots=state-connected)

いよいよ、ASDK に App Service をデプロイします。


## App Service リソースプロバイダーのインストーラーを実行する
参考：[App Service リソースプロバイダーのインストーラーを実行する](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-deploy?view=azs-2102&pivots=state-connected#run-the-app-service-resource-provider-installer)

基本的にはドキュメントの通りで、ダウンロード済の C:\appservice.exe を管理者権限で実行してリソースプロバイダーをインストールします。
Azure サブスクリプション、デプロイ先ネットワークなどは指示に従って設定するだけです。

途中でファイルサーバや SQL Server に到達できない旨表示されますが、ファイルサーバと SQL Server は VNet 内にデプロイされており、VNet 内からのみアクセスが可能です。そのため到達できないのは問題ありません。

ファイルサーバーの設定は以下を参考にしてください(準備段階で作成したファイルサーバーの設定です)。

```
File Share UNC path      : \\fs01.appsvc.local\WebSites
File Share Owner         : appsvc.local\FileShareOwner
File Share Owner Password: ************
File Share User          : appsvc.local\FileShareUser
File Share User Password : ************

Worker Role Virtual Machine Admin   : workeradmin
Worker Role Virtual Machine Password: ************
Other Role Virtual Machine Admin    : roleadmin
Other Role Virtual Machine Password : ************
```

証明書は C:\AppServiceHelperScripts に配置されており、ドキュメントにも書かれていますが、対応関係は以下の通りです。

```
App Service default SSL certificate file (*.pfx): _.appservice.local.AzureStack.external.pfx
App Service Api SSL certificate file (*.pfx)    : api.appservice.local.AzureStack.external.pfx
App Service Publisher certificate file (*.pfx)  : ftp.appservice.local.AzureStack.external.pfx
```

SQL Server の設定は以下を参考にしてください

```
SQL Server name       : 10.0.1.100 (クラスター構成で aps-sql-lb というロードバランサーが持っている IP を使用する)
SQL sysadmin login    : sqlsa
SQL sysadmin password : ************ 
```

インストーラーに対する基本設定が完了するとデプロイが開始されます。ログを見る限り、2時間45分程かかっていたため、プロビジョニングにはそれなりに時間がかかります。

## デプロイ後の手順
参考：[デプロイ後の手順](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-deploy?view=azs-2102&pivots=state-connected#post-deployment-steps)

ファイルサーバーの通信を許可するため、NSG に送信セキュリティ規則を追加します。
aps-vnet の WorkerSubnet サブネットに設定されている NSG は ```WorkersNsg``` なので、ここに設定を追加します。


```
    ソース:Any
    送信元ポート範囲: *
    変換先:IP アドレス
    宛先 IP アドレス範囲:ファイル サーバーの IP の範囲
	  FileServerSubnet 10.0.2.0/24 
    送信先ポート範囲:445
    プロトコル:TCP
    アクション:Allow
    優先順位:700
    名前:Outbound_Allow_SMB445
```

## App Service on Azure Stack Hub インストールを検証する
参照：[App Service on Azure Stack Hub インストールを検証する](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-deploy?view=azs-2102&pivots=state-connected#validate-the-app-service-on-azure-stack-hub-installation)

[All services] > [Administration] > [App Service] へ移動
![20211203-1a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/8173971e-60fe-a3c4-04df-667600d5e433.jpeg)

Status が "All roles are ready" になっていることを確認します。
![20211203-2a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/f326fcf2-3efd-ea31-32ce-643475e17e87.jpeg)

これで App Service 事態のインストールが完了しました。


## オファーの作成
参考：[Azure Stack Hub でのオファーの作成](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-create-offer?view=azs-2102)

ASDK ユーザーが App Service を作成する前に、ASDK が提供するサービスメニューに App Service を作成する必要があります。
- 各サービスとクオータを設定したものが ***プラン***
- プランをいくつか組合わせて、サブスクリプションから使用できるようにしたものが ***オファー***

Azure Stack Hub 管理者ポータル からオファーを作成する

```
# オファーの設定例
Display name: ASDK Offering
Resouce name: asdk-offering
Resouce group: asdk.offering
```

あとはプランを作成・選択してオファーを作成する。オファーにはプランを一つ含める必要があり、[Create new plan] で新しいプランを作成する。

### オファーで提供するプランを作成する
```
# プランの設定例
Display name: plan1
Resouce name: plan1
Resouce group: asdk.offering
```
Service: 適当に選択する。ここでは App Service を含む形で選択。

Quotas: クオータを設定する。既定の物を選択する。


## サブスクリプションの作成
参考：[Azure Stack Hub でオファーのサブスクリプションを作成する](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-subscribe-plan-provision-vm?view=azs-2102)

オファーが作成されたら、実際にユーザーがリソースを作成するサブスクリプションを作成する。
管理者ポータルから作成する方法とユーザーポータルから作成することが出来る。

管理者ポータルから作成する場合は、[All Services] > [User subscription] から作成する。
ユーザー ID が上手く紐付けできない場合があるので、基本的にはユーザーポータルから操作した方が良い

- Name: azurestack
- User: live.com#***@outlook.com (ユーザーポータルにアクセスするユーザー ID)
- public offer を選択する

ユーザーポータルから作成する場合は ```https://portal.local.azurestack.external``` にログオンして作成する。
この場合指定するのは以下の 2 つだけ。

- Name: azurestack
- public offer を選択する

サブスクリプションが出来れば、リソースが作成できる状態になる。

## App Service on Azure Stack Hub を試してみる
参考：[App Service on Azure Stack Hub を試してみる](https://docs.microsoft.com/ja-jp/azure-stack/operator/azure-stack-app-service-deploy?view=azs-2102&pivots=state-connected#test-drive-app-service-on-azure-stack-hub)

パブリッククラウド版と同じく App Service Plan を作成してデプロイするだけで App Service が作成できる。既定では Shared または Free の App Service Plan しか選択できない。

このユーザーポータルを含む App Service は ASDK の外からはアクセスできないが、高度なツール (Kudu) も使える。
IE11 ではできないが、Edge や Chrome でドラッグ&ドロップで登録できるため、Visual Studio で作成したプロジェクトをフォルダに発行し、zip ファイルで持ち込んで展開する等すればアプリの実行が出来る。

# まとめ
Azure Stack Development Kit に App Service をデプロイするまでの流れを紹介しました。パブリックの Azure はより複雑ですが、基本的には似たような仕組みで構築されているといえるでしょう。

実際の App Service としてはもう少し手を加えたいポイントはありますが、Azure Stack を使用する際の参考や Azure の裏側を知りたい方の参考となれば幸いです。