本番を想定したAzure Virtual Desktopのリファレンスアーキテクチャ
Preview機能などを積極的に取り入れているため、実際の本番環境で使うには十分注意が必要です。AVD環境を自社で構築、運用したり、SIでAVD環境構築を担い今後の参考アーキテクチャを求めている方に向けて公開しています。
このアーキテクチャでは、Azureにまつわるインフラ部分のみをカバーしています。Windowsのイメージ管理や各種の制御は含まれれていません。また、Azure Monitorによる監視は含まれていますが、バックアップも必要に応じて検討する必要があります。
ここで紹介するアーキテクチャは一例にすぎませんが、典型的なアーキテクチャであり、考慮するべきポイントを実例をもとにとらえることができます。
AVDをある程度知っている方向けです。初心者向けではありません。 初心者の方には
をお勧めします。
デプロイの手順については、画面ショットを含めてQiitaに「Azure Virtual Desktop (AVD)のリファレンスアーキテクチャとARMテンプレート」を公開してありますので、こちらもご参考ください。
- ネットワークはハブ & スポーク アーキテクチャ
- インターネットに直接VMを公開しない; 管理、緊急時にはBastionを利用
- インターネットアクセスはオンプレミスに引き込まず、Azure上でブレークアウトさせる; Azure Firewall Premiumを使って柔軟で詳細なアクセスコントロール
- 高可用性を考慮; Availability Zone、マネージドサービスを利用
- ログの集中管理; Azure Monitorブックで可視化
ここから、段階的に環境を構築します。
下記からデプロイすると、上記のシステムが作成されます。
補足
- 次のAD作成を行う場合は、Availability Zoneが必須となるので、東日本リージョンなどにデプロイしてください。西日本リージョンは対応していません
- Azure Firewall Premiumには、TLS Inspectionのための自己署名証明書のセット、AVDで必要とされるルールやログ取得の設定がされますが、他のインターネット向けのアクセスは許可されません
- VPN Gatewayの作成はオプションです。ExpressRouteで接続する場合はfalseのままにして、オンプレミスと接続します
- VM数に1をセットすると、Windows 10 Pro 20H2を1台、Spoke Networkに作るので、テスト用に使えます。例えばAzure Firewallのルールやオンプレミス環境との疎通確認など
下記からデプロイすると、既存環境に対してActive Directoryのドメインコントローラがデプロイされます。
補足
- ハブネットワークにデプロイします。通常、上でデフォルト値で作ったVNetに対してデプロイする場合は、ネットワークの値を変更する必要はありません
- Availability Zoneを前提としていますので、対応している東日本リージョンなどにデプロイしてください。上記で作成したVNetと同じリージョンである必要があります
- ドメイン名はAzure Active Directoryと同じものが望ましいですが、必須ではありません
- 2つのWindows Server VM、PDCとBDC、PDCに対してはAD Certificate ServicesのEnterprise Root CAがこのデプロイで構成されます
- オンプレミスでActive Directoryを運用していて、同じアイデンティティを使いたい場合は、オンプレミスとつなげる必要があるのでこのテンプレートは使わず独自に構成する必要があります
- マネージドサービスであるAzure Active Directory Domain Servicesを使うこともできますが、Active Directory Certificate Servicesがないため、Azure Firewall PremiumのTLS Inspectionで使う証明書は独自に手配する必要があり、また各仮想デスクトップイメージに対しても配布方法を考慮する必要があります
ユーザーの追加/削除などは、Azure上ではなく、構築したActive Directoryで行います。そのユーザーがAzure上のリソース(VMなど)にアクセスするにはAzureのユーザー管理を行うActive Directory(つまりAzure Active Directory)に同期している必要があり、ここでその設定を行います。
PDCにはAzure AD Connectがインストールされています。Azure Active Directoryと今ここで作ったADDCを同期するため、管理者でログインし、デスクトップ上にあるAzure AD Connectのアイコンをダブルクリックしてウィザードに従い構成します。
名前解決を統一して行うため、ネットワーク全体にわたってDNSの設定を行います。
- ハブネットワークのVNet(Azure FirewallやActive Directoryを立てたところ): PDC,BDCのIPアドレスをカスタムDNSとしてセット
- ファイアウォールポリシー: DNSプロキシを、PDC,BDCのIPアドレスで構成
- スポークネットワークのVNet: Azure Firewall Premiumのプライベートアドレスをセット
Azure Firewall PremiumのTLS Inspectionで使う証明書に、Active Directory Certificate Servicesで作成したEnterprise Root CAで署名した、Intermediate CAをセットします。
- 既存のKey Vaultに、自分のアカウントに対してアクセス権限を付与
- そのKey Vaultで、「統合されていないCAによって発行された証明書」を作成してCSRを出力
- PDCのVM内に構成されているADCSのEnterprise Root CAで、そのCSRを署名
- Key Vaultに証明書を取り込む
- ファイアウォールポリシーのTLS Inspectionで証明書を付け替え
下記からデプロイすると、既存環境に対してAzure Filesのストレージアカウントが作成され、共有ボリュームが設定されます。
補足
- AVDではWindowsのプロファイルをFSLogixを使ってローミングできるようにしますが、そのプロファイル置き場としての共有ボリュームをAzure Files上に作成します
- ストレージアカウントの名前は、Azure全体の中でユニーク(他で使われていない)なものを指定する必要があります。ストレージアカウント作成のブレードを出して事前に確認しておくのがおすすめです
- パフォーマンス上の理由(認証が終わってからデスクトップ画面が開くまでの時間)から、同時利用が100人を超えるような環境の場合は、Azure FilesではなくAzure NetApp Filesを利用検討することを推奨します
ストレージをActive Directoryの管理下に置き、各種権限設定を行います。
設定は、Microsoft Cloud Workshopのガイドをベースに行います。下記はその手順です。
AzFilesHybridモジュールのzipファイルを上で作成したADのPDC VM内などにダウンロードして展開
PowerShell ISEを管理者モードで起動し、以下の一連のPowerShellコードを実行していきます。なお、スクリプトには各種変数があり、実環境に応じて変更する必要があります。
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
# 展開したディレクトリに置き換える必要あり
cd C:\Users\ADAdmin\Documents\AzFilesHybrid
if ($PSVersionTable.PSEdition -eq 'Desktop' -and (Get-Module -Name AzureRM -ListAvailable)) {
Write-Warning -Message ('Az module not installed. Having both the AzureRM and ' +
'Az modules installed at the same time is not supported.')
} else {
Install-Module -Name Az -AllowClobber -Scope CurrentUser
}
.\CopyToPSPath.ps1
Import-Module -Name AzFilesHybrid
Connect-AzAccount
#Azure Active Directoryの管理者アカウントで認証、Active Directory Domain Serviceではなく、Azureのアカウントであることに注意
これでコンピュータオブジェクトがADに作成され、アクセスするための権限設定がADのユーザーに対してできるようになります
# 実際のサブスクリプションIDに置き換える必要あり、Get-AzSubscription で確認可能
$SubscriptionId = "00000000-0000-0000-0000-000000000000"
# ストレージアカウントがあるリソースグループ名に置き換える必要あり
$ResourceGroupName = "wvd-rg"
# 作成したストレージアカウント名に置き換える必要あり
$StorageAccountName = "takeokast"
Select-AzSubscription -SubscriptionId $SubscriptionId
Join-AzStorageAccount -ResourceGroupName $ResourceGroupName
# ストレージアカウント名を尋ねられるので、ここで入力。このスクリプトの場合、"takeokast"
$storageaccount = Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName
$storageAccount.AzureFilesIdentityBasedAuth.DirectoryServiceOptions
$storageAccount.AzureFilesIdentityBasedAuth.ActiveDirectoryProperties
# AVDを利用するユーザーをまとめたグループ (要件によって、設計する必要あり)
New-ADGroup -Name "AVD_Users" -GroupScope Global -GroupCategory Security -Description "Members of this group are AVD users"
#FSLogixに関するAzure Filesへの権限グループ
New-ADGroup -Name "AZF FSLogix Contributor" -GroupScope Global -GroupCategory Security -Description "Members of this group are FSLogix Contributor"
New-ADGroup -Name "AZF FSLogix Elevated Contributor" -GroupScope Global -GroupCategory Security -Description "Members of this group are FSLogix Elevated Contributor"
New-ADGroup -Name "AZF FSLogix Reader" -GroupScope Global -GroupCategory Security -Description "Members of this group are FSLogix Reader"
# AVDユーザーがFSLogixのプロファイルを置くAzure Filesへアクセスするための登録
Add-ADGroupMember -Identity "AZF FSLogix Contributor" -Members "AVD_Users"
# Azure AD Connectの同期を開始して、上記を即時反映
Start-ADSyncSyncCycle -PolicyType Delta
New-AzRoleAssignment -ObjectId (Get-AzADGroup -DisplayName "AZF FSLogix Contributor").Id -RoleDefinitionName "Storage File Data SMB Share Contributor" -ResourceName $StorageAccountName -ResourceGroupName $ResourceGroupName -ResourceType "Microsoft.Storage/storageAccounts"
New-AzRoleAssignment -ObjectId (Get-AzADGroup -DisplayName "AZF FSLogix Elevated Contributor").Id -RoleDefinitionName "Storage File Data SMB Share Elevated Contributor" -ResourceName $StorageAccountName -ResourceGroupName $ResourceGroupName -ResourceType "Microsoft.Storage/storageAccounts"
New-AzRoleAssignment -ObjectId (Get-AzADGroup -DisplayName "AZF FSLogix Reader").Id -RoleDefinitionName "Storage File Data SMB Share Reader" -ResourceName $StorageAccountName -ResourceGroupName $ResourceGroupName -ResourceType "Microsoft.Storage/storageAccounts"
# 異なる名前で共有名を設定している場合は置き換える必要あり
$share_name = "avdfileshare"
# Azure Portalで、ストレージアカウントのアクセスキーを確認し置き換える必要あり
# パスワードにはADのポリシーにより有効期限がある場合があり、https://docs.microsoft.com/ja-jp/azure/storage/files/storage-files-identity-ad-ds-update-passwordを事前に参照して運用を検討する必要あり
$st_key = "access_key"
# ローカルでマウントするドライブレター
$mount_drv = "Z"
$unc_path = "\\" + $StorageAccountName + ".file.core.windows.net\" + $share_name
$net_account = "Azure\" + $StorageAccountName
$securePass = ConvertTo-SecureString $st_key -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential $net_account, $securePass
New-PSDrive -Name $mount_drv -PSProvider FileSystem -Root $unc_path -Credential $cred
$mount_point = $mount_drv + ":"
# 共有ボリュームの権限設定
$folder_path = $mount_point
$aclparam = @("AZF FSLogix Contributor", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
$aclparam = @("AZF FSLogix Elevated Contributor", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
$aclparam = @("AZF FSLogix Reader", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
# Profiles フォルダ
$folder_path = $mount_point + '\' + 'Profiles'
mkdir $folder_path
$aclparam = @("CREATOR OWNER", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.SetAccessRuleProtection($true,$false) #継承削除
$acl.SetAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
$aclparam = @("AZF FSLogix Elevated Contributor", "FullControl", "ContainerInherit,ObjectInherit", "NoPropagateInherit", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
$aclparam = @("AZF FSLogix Contributor", "AppendData,ReadAndExecute,Synchronize", "ContainerInherit,ObjectInherit", "NoPropagateInherit", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
# ODFC フォルダ
$folder_path = $mount_point + '\' + 'ODFC'
mkdir $folder_path
$aclparam = @("CREATOR OWNER", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.SetAccessRuleProtection($true,$false) #継承削除
$acl.SetAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
$aclparam = @("AZF FSLogix Elevated Contributor", "FullControl", "ContainerInherit,ObjectInherit", "NoPropagateInherit", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
$aclparam = @("AZF FSLogix Contributor", "AppendData,ReadAndExecute,Synchronize", "ContainerInherit,ObjectInherit", "NoPropagateInherit", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
# MSIX フォルダ
$folder_path = $mount_point + '\' +'MSIX'
mkdir $folder_path
$aclparam = @("AZF FSLogix Elevated Contributor", "FullControl", "ContainerInherit,ObjectInherit", "NoPropagateInherit", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.SetAccessRuleProtection($true,$false) #継承削除
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
$aclparam = @("AZF FSLogix Contributor", "ReadAndExecute,Synchronize", "ContainerInherit,ObjectInherit", "NoPropagateInherit", "Allow")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclparam
$acl = Get-Acl $folder_path
$acl.AddAccessRule($rule)
Set-Acl $folder_path -AclObject $acl
Remove-PSDrive -Name $mount_drv
ストレージアカウント -> ネットワーク -> 許可するアクセス元で選択されたネットワークから、ハブネットワークを指定します。これにより、共有ボリュームへのSMBアクセスはファイアウォールにルートされずダイレクトにつながるため、ファイアウォールのルールを設定する必要なく、またこのハブ以外からのアクセスを拒否できます
\\<storage_account>.file.core.windows.net\avdfileshare\Profiles
のようにプロファイルの場所を指定できます。
ユーザーがプロファイルを置くためにはAZF FSLogix Contributor
グループに属している必要があります。上記で作ったセキュリティグループでは、AVD_Users
にユーザー登録するのがよいでしょう。このユーザーを、AVDのアプリケーショングループに許可することで、簡単に権限管理をすることができます。
これで、AVDをデプロイする環境が整いました。
ホストプール等関連リソースを作成し、ログ関連の設定をして、グループポリシーかイメージファイルの中でFSLogix VHDの場所をし、利用者を割り当てれば、AVDとして最低限の利用環境が整います。
さらに、日本語イメージの準備、ファイアウォール許可ルールの設定、各種利用ポリシーの設定、電源管理などを行う必要があるでしょう。