Azure の利用シーンが拡大してくると、検証環境が複数のテナントをまたがって管理しなければいけないことがあるかもしれません。場合によっては、テナントごとに利用する仮想マシンイメージを統一するために、何回もカスタムイメージリソースを作成する手間が生じてしまいます。もしくは、単に他の組織の誰かが作ったカスタムイメージを自分のテナントで利用したいといったことがあるかもしれません。
そのような場合、従来は AzCopy などを使ってストレージデータをコピーする手間がありました。しかし、共有イメージギャラリーの機能を使えば、イメージデータをコピーする必要なく、他テナントのイメージをもとにして自分のテナントに仮想マシンをデプロイできます。
今回は共有イメージギャラリーを使って、テナント間でカスタムイメージを共有する方法を紹介します。
共有イメージギャラリーによる共有方法
共有イメージギャラリーを利用したテナント間でのイメージ共有は執筆時点で PowerShell もしくは Azure CLI でのデプロイに限定されています。
テナント A とテナント B を用意し、テナント A で作成した共有イメージギャラリー内のイメージを使ってテナント B に仮想マシンをデプロイします。
両方のテナントのリソースを操作するためのサービスプリンシパルを作成し、その情報を持って両テナントのリソースを操作します。サービスプリンシパルは両方のテナントにあるサブスクリプションにアクセス権を付与します。
事前準備
- テナント A
- 有効な Azure サブスクリプション
- 有効な Azure サブスクリプションに「所有者」もしくは「ユーザーアクセス管理者」ロール
- Azure AD でアプリを作成できること
- 共有イメージギャラリーリソースと1つ以上のイメージ定義を作成
- テナント B
- 有効な Azure サブスクリプション
- 有効な Azure サブスクリプションに「所有者」もしくは「ユーザーアクセス管理者」ロール
構築手順
サービスプリンシパルの作成
Azure ポータルにサインインし、[Azure Active Directory]>[アプリの登録]をクリックします。上部の[新規登録]をクリックします。
- [名前]:SNY-Gallery-App(アプリを識別するための任意の名前を指定)
- [サポートされているアカウントの種類]:任意の組織ディレクトリ内のアカウントと個人の Microsoft アカウント
- [リダイレクト URI]: https://www.microsoft.com
パラメーターを入力し、[登録]をクリックします。

アプリケーションが作成されたら、[アプリケーション ID]と[ディレクトリ ID]をコピーして控えておきます。

新規にシークレット(サービスプリンシパル用のパスワードのようなもの)を発行します。メニューの[証明書とシークレット]をクリックし、[新しいクライアント シークレット]をクリックします。

[有効期限]は好きなものを選択し、[追加]をクリックします。

発行されたシークレットを忘れずに何処かへ控えておきます。このシークレットは一度他の画面に映ると二度と表示されません。

テナント A へアクセス権を付与
共有イメージギャラリーリソースが含まれるサブスクリプションもしくはリソースグループに対して、先ほど作成したサービスプリンシパルへアクセス権を付与します。[役割]は[閲覧者]で十分です。


テナント B へアクセス権を付与
今度はテナント B へサービスプリンシパルのアクセス権を付与します。
次の URL へアクセスして、サービスプリンシパルをテナント B に登録します。<Tenant B ID> にはテナント B のディレクトリ ID を、<Application ID> にはサービスプリンシパルのアプリケーション ID を入力します。
https://login.microsoftonline.com/<Tenant B ID>/oauth2/authorize?client_id=<Application ID>&response_type=code&redirect_uri=https%3A%2F%2Fwww.microsoft.com%2F
この URL にアクセスすると、サービスプリンシパルがテナント B の情報を読み取れるようにする許可を尋ねられます。内容を確認して問題なければ[承諾]をクリックします。

次はサブスクリプションにアクセス権を付与します。[役割]は[共同作成者]を選択します。

ここまでで準備は完了です。
PowerShell で仮想マシンをデプロイ
PowerShell を起動し、次のコマンドで他テナントのイメージを利用して仮想マシンをデプロイします。
# 変数の宣言 ## サービスプリンシパルのアプリケーション ID $applicationId = '<Application ID>' ## サービスプリンシパルのシークレット $appSecret = '<Application secret>' $secret = $appSecret| ConvertTo-SecureString -AsPlainText -Force ## テナント A のディレクトリ ID $tenantA = "<Tenant A ID>" ## 共有イメージギャラリーリソースが含まれるサブスクリプション ID $sigSubscription = "<Subscription ID>" ## 共有イメージギャラリーリソースが含まれるリソースグループ名 $sigResourceGroup = "<Resource group name>" ## 共有イメージギャラリーリソースの名前 $sigName = "<Shared image gallery name>" ## 利用するイメージ定義の名前 $sigImageDefName = "<Image definition name>" ## 利用するイメージのバージョン $sigImageVersion = "<Image version>" ## テナント B のディレクトリ ID $tenantB = "<Tenant B ID>" ## リソースグループの名前 $resourceGroup = "myResourceGroup" ## リソースをデプロイするリージョン $location = "South Central US" ## 仮想マシンの名前 $vmName = "myVMfromImage" # サービスプリンシパルで Azure へサインイン ## サービスプリンシパル用の資格情報を生成 $appCred = New-Object -TypeName PSCredential -ArgumentList $applicationId, $secret ## 既存の接続情報をクリア Clear-AzContext ## テナント A へサインイン Connect-AzAccount -ServicePrincipal -Credential $appCred -Tenant $tenantA ## テナント B へサインイン Connect-AzAccount -ServicePrincipal -Credential $appCred -Tenant $tenantB # 仮想マシンを作成 ## 共有するイメージリソースを指定する URI $image = "/subscriptions/$($sigSubscription)/resourceGroups/$($sigResourceGroup)/providers/Microsoft.Compute/galleries/$($sigName)/images/$($sigImageDefName)/versions/$($sigImageVersion)" ## 仮想マシンのローカル管理者の資格情報を指定 $cred = Get-Credential -Message "Enter a username and password for the virtual machine." ## リソースグループを作成 New-AzResourceGroup -Name $resourceGroup -Location $location ## ネットワーク関連の設定 $subnetConfig = New-AzVirtualNetworkSubnetConfig -Name mySubnet -AddressPrefix 192.168.1.0/24 $vnet = New-AzVirtualNetwork -ResourceGroupName $resourceGroup -Location $location ` -Name MYvNET -AddressPrefix 192.168.0.0/16 -Subnet $subnetConfig $pip = New-AzPublicIpAddress -ResourceGroupName $resourceGroup -Location $location ` -Name "mypublicdns$(Get-Random)" -AllocationMethod Static -IdleTimeoutInMinutes 4 $nsgRuleRDP = New-AzNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleRDP -Protocol Tcp ` -Direction Inbound -Priority 1000 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * ` -DestinationPortRange 3389 -Access Allow $nsg = New-AzNetworkSecurityGroup -ResourceGroupName $resourceGroup -Location $location ` -Name myNetworkSecurityGroup -SecurityRules $nsgRuleRDP $nic = New-AzNetworkInterface -Name myNic -ResourceGroupName $resourceGroup -Location $location ` -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id ## 仮想マシンの設定 $vmConfig = New-AzVMConfig -VMName $vmName -VMSize Standard_D1_v2 | ` Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $cred | ` Set-AzVMSourceImage -Id $image | ` Add-AzVMNetworkInterface -Id $nic.Id ## 仮想マシンをデプロイ New-AzVM -ResourceGroupName $resourceGroup -Location $location -VM $vmConfig
入力に問題がなければ仮想マシンの作成が始まります。

今回複製したイメージは日本語化した Windows Server 2019 のイメージだったので、サインインすると日本語設定の仮想マシンが起動していることを確認できます。

おわりに
今回は共有イメージギャラリーを利用してテナント間でカスタムイメージを共有する方法を紹介しました。現在は PowerShell だけでしか作成できませんが(Azure ポータルからは他テナントのイメージは見えません)、テナントをまたいで仮想マシンを展開できるのは非常に便利です。テナントごとにイメージ管理する必要がなくなるため、作成する時間の節約と設定ミスの削減を狙えます。
今後は Azure ポータルからも利用できるようになって、より使いやすくなることを期待しています。
コメント