備忘録、のようなもの

頭を使うために書き始めることにしました。わりと何でも書くつもりです。

AzureのARMテンプレートと少々闘った

早くも半年以上放置されていたブログです。
継続的にブログとか記事書いてる人はすごいですねほんと。

私事ですが転職して7月から新たな環境で働いてるので、そのうちAWS関連のメモが登場するかもしれません。
ちょうど来週Cloud Practitioner受けますが今回はAzureの話です。

ARMテンプレートって何かというと、Azureリソースの構成をJSON形式で記述しているものです。
IaC的なノリです、たぶん。
JSON形式でAzureリソースを定義しておいて、PowershellとかAzure CLIでえいっ!ってやると、
定義どおりにAzureリソースが作成されます。

で、何を書くかというと
本番環境のデータをコピーして検証環境作るんだ!!多分それなりの頻度で作っては壊すんだ!
って感じのお話があったので、それをARMテンプレートにしてみました。
ARMテンプレートならAzureポータルから作成できるので、お客さん自信でも必要なときにデプロイできますしね。
まぁもう3年位プレビューだけど…ポータルから消えないことを祈ります。
f:id:idx_ccd3:20190908180616p:plain
今回はそのARMテンプレートを作る過程でハマったこととか関数とかをメモがてら置いていきます。

ハマったもの

増分デプロイモードの挙動

リソースをデプロイするときに、「完全デプロイモード」と「増分デプロイモード」が選べます。
完全デプロイモードではARMテンプレート内に記述のないリソースは削除されますが、
増分デプロイモードでは記述のないリソースはそのままです。

増分デプロイモードでリソース内の設定を少し変更しようと思って手抜きしようとしたら少しハマりました。
Azure Resource Manager のデプロイ モード | Microsoft Docs

ただし、既存のリソースを増分モードで再デプロイした場合の結果は異なります。 更新対象だけでなく、リソースのすべてのプロパティを指定します。 一般的な誤解は、指定されていないプロパティは変更されないままであると考えることです。 特定のプロパティを指定しなかった場合、Resource Manager は更新によってそれらの値を上書きするものと解釈します。

一般人なので一般的な誤解をしました。 具体的には作成済みのNICをLoad Balancerのバックエンドプールに追加しようとしたところ、既存のNSG設定を削除しました。

増分デプロイモードはリソースの有無に対しては増分のみデプロイされるけど、リソース内のプロパティは上書きされるのでしっかり定義しましょう。(戒め

それと検証環境だし完全デプロイモードにしようとしたら、リンクされたテンプレートとか入れ子のテンプレートがあると使えないよ~!という感じだったので増分デプロイモードになりました。

copyのcount

copyは反復処理させるときに使用する関数です。
VMが合計24台とかあったので有効活用しました。が、一部ハマりました。
いろんな用途のVMがあったのでデータディスクの本数も様々なので、
count: "[length(parameters('dataDisks'))]" みたいなことしたかったんですが、コピー制限がありました。

Azure リソースの複数インスタンスのデプロイ | Microsoft Docs

REST API バージョン 2019-05-10 以降のテンプレートをデプロイする場合、count を 0 に設定できます。 それ以前の REST API のバージョンでは、count をゼロに設定することはサポートされていません。

Microsoft.Compute/virtualMachines 2019-03-01 - Azure template | Microsoft Docs
Microsoft.Compute/virtualMachinesの最新APIバージョンは2019-03-01ってなってました。詰んだ。
おとなしくデータディスクが存在しないVMは別のテンプレートにしました

他にもちょいちょいハマりましたが、だいたい書く階層を間違えてるような凡ミスが多かったです。jsonで書くのつらたんです。

便利だったもの

リソース関数 reference

NSGのセキュリティルールを1から書くのしぬほど大変じゃないですか。
検証環境なので本番環境の値そのまま持ってくればいいので探してみたら便利な関数見つけました。

Azure Resource Manager テンプレートの関数 - リソース | Microsoft Docs

使い方はこんな感じでした。

    "resources": [
        {
            "name": "nsg2",
            "type": "Microsoft.Network/networkSecurityGroups",
            "apiVersion": "2017-10-01",
            "location": "Japan East",
            "properties": {
                "securityRules": "[reference(resourceId(parameters('prdRg'), 'Microsoft.Network/networkSecurityGroups', 'nsg1'),'2019-04-01').securityRules]"
            }
        }
    ]

第1引数にリソースID、第2引数にAPIバージョンを指定してあげて、参照したいプロパティ名を最後につけるだけ。
第3引数に’Full’を与えるとproperties以外の値も取ってきてくれるようですが、
NSGのセキュリティルールはpropertiesに書いてあるので引数2つで問題なしです。
使用可能な箇所については制限があるのでちゃんと読みましょう。読まなかった人からのアドバイスです。

reference 関数は、リソース定義のプロパティと、テンプレートまたはデプロイの出力セクションでのみ使用できます。

nullの判定

特定のプロパティが存在しないときにequals(parameters('aa'),null) みたいなこと書いてみたら怒られました。
空とかnullの判定はemptyという関数があるようです。
Azure Resource Manager テンプレートの関数 - 配列とオブジェクト | Microsoft Docs

empty(parameters('aa'))

とってもシンプルでした。

大層なテンプレートは書いてないので今日はざっくりここまでということで。
(というかちょいちょい忘れてる部分があるので、次回からはもう少しメモ残しながら作ります