Azureの既存リソースをARMテンプレートに変換する際、AzureポータルだとGUI操作に手間がかかり、あまり効率的ではない。そこで主にAzure PowerShellを使ってARMテンプレートをエクスポートする方法とその注意点を説明する。
対象:Azure PowerShell、ARMテンプレート、Bicep
Tech TIPS「【Azure】既存リソースをARMテンプレートに変換してインフラをコード化する(Azureポータル編)」では、Azureポータルを使って、既存リソースの「ARM(Azure Resource Manager)テンプレート」をエクスポートする方法を紹介した。
ただ、対象のリソースがたくさんある場合や、デプロイ時に新旧リソースのARMテンプレート比較を自動化したい場合は、GUI(グラフィカルユーザーインタフェース)だと操作が面倒で効率的ではない。このような場合はコマンドで操作するCUI(キャラクタユーザーインタフェース)の方が便利だ。
そこで本Tech TIPSでは、主に「Azure PowerShell」を使ってARMテンプレートをエクスポートする方法と注意点を説明しよう。PowerShellなら自動化もしやすいはずだ。
エクスポート対象は既存リソースとし、デプロイの履歴からのエクスポートは取り扱わない。また、各種作業はWindows 10/11搭載PC上で実行し、そのPCにはAzure PowerShellをインストール済みである、ということを前提としている。Azure PowerShellのインストールについては、Tech TIPS「Azure PowerShellをインストールする【Windows 10/11】」を参照していただきたい。
PowerShellを使ってAzureのリソースからARMテンプレートをエクスポートするには、「Export-AzResourceGroup」コマンドレットを用いる。
Export-AzResourceGroup -ResourceGroupName <リソースグループ名>
上記のコマンドラインを実行すると、<リソースグループ名>で指定したリソースグループに含まれる全リソースのARMテンプレートが、カレントディレクトリの「<リソースグループ名>.json」というJSON形式のファイルに保存される。
Export-AzResourceGroupコマンドレットの戻り値には、ARMテンプレートの保存先パスのオブジェクトが格納される。保存先パスを取得するには、そのオブジェクトの「Path」プロパティを参照すればよい。
ARMテンプレートファイルが既に存在している場合、上記のコマンドラインを実行すると、上書きしてもよいかどうかと聞かれる。この問い合わせを省略して強制的に上書きするには、「-Force」オプションを指定すればよい。
Export-AzResourceGroupコマンドレットには「-Path」オプションがあり、ARMテンプレートの保存先パスを指定できる。つまり、保存先のディレクトリやファイル名を変更できる。
ただ、執筆時点では、このコマンドレットは相対パスを正しく扱えないようだ。例えば「-Path <ファイル名>」と指定すると「The value cannot be an empty string. (Parameter 'path')」というエラーが発生して、ARMテンプレートの保存に失敗した。また「-Path .\<ファイル名>」と指定すると、サインイン中のユーザーのユーザープロファイルディレクトリに保存されてしまった(カレントではなくユーザープロファイルディレクトリからの相対パスと認識されているようだ)。
一方、絶対パスで指定すると、ARMテンプレートは正しく保存された。相対パスで指定したい場合は、以下のように「Join-Path」「Resolve-Path」コマンドレットを併用して、絶対パスに変換してから「-Path」オプションに指定するとよいだろう。
$RGName = "<リソースグループ名>"
$OutputDir = "<保存先ディレクトリの相対パス>"
$OutputFileName = "<保存先ファイル名>"
$OutputPath = Join-Path (Resolve-Path $OutputDir) $OutputFileName
Export-AzResourceGroup -ResourceGroupName $RGName -Path $OutputPath
ただし、<保存先ディレクトリの相対パス>には存在するディレクトリのパスを指定する必要がある(未作成だとエラーになる)。
リソースグループ内の特定リソースのみARMテンプレートをエクスポートしたい場合は、そのリソースID単体か、または複数のリソースIDを格納した配列を「-Resource」オプションで指定する。
Export-AzResourceGroup -ResourceGroupName <リソースグループ名> -Resource <リソースIDまたはその配列>
例えば、メトリックアラートのリソースのみエクスポートしたい場合は、次のように実行すればよい。
$RGName = "<リソースグループ名>"
$ResourceType = "Microsoft.Insights/metricAlerts" # 対象のリソースタイプ
$Resources = Get-AzResource -ResourceGroupName $RGName -ResourceType $ResourceType
$ResourceIds = $Resources | Select-Object -ExpandProperty ResourceId
Export-AzResourceGroup -ResourceGroupName $RGName -Resource $ResourceIds
上記リストでは、「Get-AzResource」コマンドレットでリソースを絞り込んでから、そのリソースIDの配列を「Select-Object」コマンドレットで生成し、それをExport-AzResourceGroupコマンドレットに指定している。
変数「$resourceType」に別のリソースタイプ名を代入すれば、他のリソースを抽出できる。例えば、App Serviceなら「Microsoft.Web/sites」を代入すればよい。
さらに、Get-AzResourceコマンドレットで「-Name」「-TagName」「-TagValue」などのオプションを駆使すると、リソース名やタグなどで絞り込んだリソースからARMテンプレートをエクスポートできる。
ARMテンプレートをJSON形式ではなくBicep形式で作成している人も多いだろう。ただ、Azure PowerShellの標準機能では、ARMテンプレートをBicepで直接エクスポートする方法はないようだ(執筆時点でExport-AzResourceGroupコマンドレットにそのようなオプションはなかった)。
そこで、Bicep形式のARMテンプレートからデプロイするのに用いる「Bicep CLI」を使って、JSONからBicepに変換(デコンパイル)しよう。
まずBicep CLIをインストールする(これは1回実行すればよい)。
winget install -e --id Microsoft.Bicep # wingetでBicep CLIをインストール
bicep --version # 正しくインストールされていればバージョン番号が表示される
Bicep CLIが使えるようになったら、Export-AzResourceGroupコマンドレットで保存したJSON形式のARMテンプレートを、Bicep CLIでBicepに変換する。
$RGName = "<リソースグループ名>"
$Result = Export-AzResourceGroup -ResourceGroupName $RGName
bicep decompile $Result.Path
これでカレントディレクトリに「<リソースグループ名>.bicep」というファイル名のBicepのARMテンプレートが保存されるはずだ。別のファイル名でBicepファイルを保存したい場合は、「bicep decompile」のオプションとして「-outfile <Bicepファイルパス>」を指定すればよい。
Export-AzResourceGroupコマンドレットもBicep CLIも、完全なARMテンプレートを出力することはない。実際にデプロイに利用するには、必ず何らかの修正が必要になる。
特に注意が必要なのは、リソースの一部がエクスポートされないことだ。例えばApp Serviceの環境変数は、アプリ設定も接続文字列も全くエクスポートされない。これらは「Get-AzWebApp」コマンドレットなど別の方法で取得し、ARMテンプレートのパラメータなどで反映する必要がある。
$RGName = "<リソースグループ名>"
$Name = "<リソース名>"
$WebApp = Get-AzWebApp -ResourceGroupName $RGName -Name $Name
$AppSettings = $Webapp.SiteConfig.AppSettings # アプリ設定が格納されたオブジェクト
$ConnectionStrings = $Webapp.SiteConfig.ConnectionStrings # 接続文字列
また、App ServiceとLog Analytics、ストレージをひも付ける「診断設定」も、筆者はエクスポートできたことがない。
複数のプロパティ間で依存関係がある場合でも、エクスポートあるいは変換時に特別扱いされることはなく、似たような値が静的に記されたコードが出力される。変数や関数などを駆使して依存関係を表すようにARMテンプレートを書き換えて、矛盾した設定ができないようにするべきだろう。
■関連リンク
Copyright© Digital Advantage Corp. All Rights Reserved.