みち草

Azure中心にまとめる技術情報ブログ

Logic Apps でサブスクリプションのクォータを定期メール送信する

はじめに

結構前ですが、 Azure サービスのクォータを取得できる REST API の、新バージョンのパブリック プレビューがアナウンスされていました。 これを使って Azure Virtual Machines (コア/vCPU) のクォータを取得することができるので、定期的にクォータ状況を取得、メール送信する Logic Apps を構成してみました。

azure.microsoft.com

※前述のとおりこの API はまだプレビュー版であり、サポートされていないことに注意してください

目次

作るもの

1 週間に 1 回など、定期的にサブスクリプションのコンピューティング リソースのクォータを確認し、使用状況と上限、上限の拡張可否プロパティを取得しメール送信します。

実際に届くメールはこんな感じです。

作り方

完成後の全体像はこんな感じです。

クォータの上限と使用状況を別に取得し、最後にいい感じにマージしてメールします。

以下で作り方を紹介します。

Logic Apps デプロイ

まずは Logic Apps をこんな感じでデプロイします。

Standard にすると App Service プランを使用するため、動いていなくても時間で課金されてしまいます。 定期的にクォータを取得してメール通知するのみなので、従量課金の消費プランで十分です。

トリガー、変数の追加

デプロイが終わるとデザイナー画面が開きます。定期的に繰り返したいので、[繰り返し] を選択します。

繰り返しの設定が開くので、好きなタイミングに設定します。

Add new parameter から時刻、曜日を追加するとより細かく設定できます。タイムゾーンは忘れずに追加して、日本時刻にしておきます。

こんな感じにすると、毎週金曜日の 18 時に動作します。

続いて、[新しいステップ] から "変数" を検索して、[変数の初期化] を選択します。

サブスクリプション ID など、変わることなく繰り返し使用する値を入れておく変数と、途中経過、最終結果を入れておくための変数で、以下の 5 個を使用します。

変数名 種類 概要
subscriptionId 文字列 クォータを取得するサブスクリプションのサブスクリプション ID を示す文字列 (ここでは Logic Apps をデプロイしたのと同じサブスクリプション)
region 文字列 クォータを取得するリージョンを示す文字列 (ここでは Logic Apps のデプロイと同じ東日本リージョン)
usageArray アレイ 取得したクォータ使用状況を一時的に格納する配列
limitArray アレイ 取得したクォータ上限を一時的に格納する配列
result アレイ 最終的に通知する結果を格納する配列

こんな感じで変数に設定していきます。

配列にした 3 つは後で値を入れるので、初期値は空で大丈夫です。

これで、タイマーと変数は OK です。

マネージド ID 有効化、権限付与

一旦保存して Logic Apps の [ID] からシステム割り当てマネージド ID を有効化します。

有効にしたマネージド ID に、クォータ取得対象サブスクリプションの [閲覧者] 権限を付与しておきます。

権限の付与はこれで OK です。

クォータ上限の取得

デザイナーに戻り、クォータの上限一覧を取得します。

[新しいステップ] から "HTTP" を入力、検索して [HTTP] アクションを追加します。

このアクションで API を実行することができるので、プレビューの API を使ってクォータ上限の List を取得します。

learn.microsoft.com

変数で入力したサブスクリプション、リージョンを対象にコンピュート リソースのクォータを取得するため、以下のように指定します。

  • 方法 : GET
  • URI : https://management.azure.com/subscriptions/[動的なコンテンツから変数: subscriptionId]/providers/Microsoft.Compute/locations/[動的なコンテンツから変数: region]/providers/Microsoft.Quota/quotas?api-version=2021-03-15-preview
  • ヘッダー : Content-Type, application/json

[Add new parameter] から [認証] を追加して、マネージド ID での認証も有効にしておきます。

こんな感じで OK

これで様々なリソースのクォータ上限を取得できるので、この中から必要な部分を取り出していきます。

[新しいステップ] から [JSONの解析] を追加します。

これをとおすことで、JSON の持つ各種プロパティを動的なコンテンツとして呼び出しやすくなります。

[コンテンツ] には、直前の HTTP アクションで取得した [本文] (body) を指定します。

読み込ませる JSON のスキーマを指定する必要があるので、以下をコピペします。

失敗前提で適当に実行して、実行履歴からレスポンスの JSON をコピー、サンプル ペイロードとして貼り付け、という方法も可能です。

{
    "properties": {
        "value": {
            "items": {
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "properties": {
                        "properties": {
                            "isQuotaApplicable": {
                                "type": "boolean"
                            },
                            "limit": {
                                "properties": {
                                    "limitObjectType": {
                                        "type": "string"
                                    },
                                    "limitType": {
                                        "type": "string"
                                    },
                                    "value": {
                                        "type": "integer"
                                    }
                                },
                                "type": "object"
                            },
                            "name": {
                                "properties": {
                                    "localizedValue": {
                                        "type": "string"
                                    },
                                    "value": {
                                        "type": "string"
                                    }
                                },
                                "type": "object"
                            },
                            "properties": {
                                "properties": {},
                                "type": "object"
                            },
                            "unit": {
                                "type": "string"
                            }
                        },
                        "type": "object"
                    },
                    "type": {
                        "type": "string"
                    }
                },
                "required": [
                    "properties",
                    "id",
                    "type",
                    "name"
                ],
                "type": "object"
            },
            "type": "array"
        }
    },
    "type": "object"
}

取得結果は多数のリソースのクォータが含まれるため、For-Each で全要素から必要なものだけ抜き出します。

[新しいステップ] の [制御] から [For each] を追加します。

以前の出力として、JSON の解析の [value] を選択します。

[アクションの追加] から [配列変数に追加] を選択します。

最初に作った空の limitArray 配列に、取り出したプロパティを追加していきます。

配列には以下の値を 1 要素として、JSON 形式で格納します。

  • currentLimit (クォータ上限) : 1000 や 50 などの上限数
  • isQuotaApplicable (クォータ拡張の可否っぽい) : True か Flase
  • name (クォータの名称) : Standard D Family vCPUs や Total Regional vCPUs など

これらを取得するため、[値] を以下のように指定します。

以下コピペ用

{
  "currentLimit": "[動的なコンテンツ: JSON の解析の value (以下に注意点あり)]",
  "isQuotaApplicable": "[動的なコンテンツ: JSON の解析の isQuotaApplicable]",
  "name": "[動的なコンテンツ: JSON の解析の localizedvalue]"
}

動的なコンテンツまで指定するとこんな感じです。

注意点として、[value] が 3 つあり、どれを選んだらいいかわかりづらいです。

追加した後にマウス オーバーすると中身が見えるので、items('For_each')?['properties']?['limit']?['value'] の value を選んでください。(これもうちょい何とかしてほしい)

[value] にマウス カーソルを乗せてこれが出てくればあってます。

これで、 limit 側は一旦 OK です。

クォータ使用状況の取得

続いて、大体同じようにして、クォータの使用状況を取得します。

上限の取得と使用状況の取得を並列に行いたいので、変数と HTTP の間の [+] ボタンから [並列分岐の追加] を選択し、[HTTP] を追加します。

今度はクォータの使用状況の List を取得します。

learn.microsoft.com

変数で入力したサブスクリプション、リージョンを対象にコンピュート リソースのクォータを取得するため、以下のように指定します。

URI は usages 用に若干変わってます。

  • 方法 : GET
  • URI : https://management.azure.com/subscriptions/[動的なコンテンツから変数: subscriptionId]/providers/Microsoft.Compute/locations/[動的なコンテンツから変数: region]/providers/Microsoft.Quota/usages?api-version=2021-03-15-preview
  • ヘッダー : Content-Type, application/json

[Add new parameter] から [認証] を追加して、マネージド ID での認証も有効にしておきます。

同様に JSON の解析を追加します。

スキーマはこちら。

{
    "properties": {
        "value": {
            "items": {
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "properties": {
                        "properties": {
                            "isQuotaApplicable": {
                                "type": "boolean"
                            },
                            "name": {
                                "properties": {
                                    "localizedValue": {
                                        "type": "string"
                                    },
                                    "value": {
                                        "type": "string"
                                    }
                                },
                                "type": "object"
                            },
                            "properties": {
                                "properties": {},
                                "type": "object"
                            },
                            "unit": {
                                "type": "string"
                            },
                            "usages": {
                                "properties": {
                                    "UsagesType": {
                                        "type": "string"
                                    },
                                    "Value": {
                                        "type": "integer"
                                    }
                                },
                                "type": "object"
                            }
                        },
                        "type": "object"
                    },
                    "type": {
                        "type": "string"
                    }
                },
                "required": [
                    "properties",
                    "id",
                    "type",
                    "name"
                ],
                "type": "object"
            },
            "type": "array"
        }
    },
    "type": "object"
}

For each を追加して、JSONの解析の出力を選択します。

この Usage の API は、クォータの使用状況が 0 でも取得するので (中には -1 も…)、数がとても多くなります。

ここでは全量ではなく、条件を用いて使用状況が 1 以上のものだけ取り出します。

For each の中で [条件] を追加して、Usage が 1 以上だったら配列変数に追加するようにします。

配列に追加は、先ほどと同様です。

  • currentUsage (クォータ使用状況) : 100 や 50 など
  • isQuotaApplicable (クォータ拡張の可否っぽい) : True か Flase
  • name (クォータの名称) : Standard D Family vCPUs や Total Regional vCPUs など

これらを取得するため、[値] を以下のように指定します。

以下コピペ用

{
  "currentUsage": "[動的なコンテンツ: JSON の解析2の Value]",
  "isQuotaApplicable": "[動的なコンテンツ: JSON の解析2の isQuotaApplicable]",
  "name": "[動的なコンテンツ: JSON の解析2の localizedvalue]"
}

こちらでも [value] が 3 つ見えているので注意です。

マウス オーバーすると中身が見えるので、items('For_each')?['properties']?['limit']?['Value'] の Value を選んでください。(条件の Value と、currentUsage の Value の 2 ヶ所)

これで、使用状況の取得はできました。

テーブル作成、メール送信

最後に、取得した 2 つの配列を使ってテーブルを作成し、メールで送信します。

まずは、2 つの For each の間の [新しいステップ] から、For each を追加します。

以前の手順からの出力には、[limitArray] を指定します。

[アクションの追加] から For each を追加して二重の For each にし、内側の For each では [usageArray] を指定します。

こんな感じです。これで共通の要素を探し、それだけを通知するようにします。

内側の For each にて [アクションの追加] から [条件] を追加し、条件として、"items('for_each_3')?['name'] が items('for_each_4')?['name'] と等しい" という条件を作ります。

ここは、動的なコンテンツから選択できないので [式] から手打ちします。

配列から取り出した各要素の名前が一致したら、出力すべき共通の要素として result に格納します。

result 配列への追加ですが、ここの値も動的なコンテンツで追加できないので、それぞれ式で追加します。

以下コピペ用

{
  "currentLimit": "式で items('for_each_3')?['currentLimit'] を指定",
  "currentUsage": "式で items('for_each_4')?['currentUsage'] を指定",
  "isQuotaApplicable": "式で items('for_each_3')?['isQuotaApplicable'] を指定",
  "name": "式で items('for_each_3')?['name'] を指定"
}

こんな感じです。 (画像を取り直したので若干差がありますが値の部分は一緒です)

result 配列から、メールに載せる用のテーブルを作成します。

[新しいステップ] から、[HTML テーブルの作成] を追加します。

列名とその値を指定することで result 配列の内容をテーブルに加工しますが、動的なコンテンツを使えないのでヘッダーは手打ち、 値は先ほどの要領で [式] を用いて指定します。

こんな感じです。

  • Name : item()?['name']
  • CurrentUsage : item()?['currentUsage']
  • CurrentLimit : item()?['currentLimit']
  • isQuotaApplicable : item()?['isQuotaApplicable']

これで使用中のクォータとその上限値を表示するテーブルが作成できたので、あとはメールを送るだけです。

[新しいステップ] から [メールの送信] を追加します。ちなみに、アクションを変えれば Teams などへの通知も可能です。

サインインが必要なため、メールの送信元となるアカウントでサインインします。

宛先や件名は任意に指定してください。

本文には動的なコンテンツから、直前で作成した HTML のテーブルを追加します。

表示されないときは [もっと見る] を選択します。

仕組み部分は構成できたので、最後に保存して [トリガーの実行] からテスト実行します。

一覧を取得、二重 for each で比較するので 1 分ほどかかりますが、以下のようにメールが届くはずです。

終わりに

長くなってしまいましたが、今回は設定した日時に定期的に動作し、使用中のクォータを通知してくれる仕組みを Logic Apps で作成しました。

CPU コア数のような拡張できるクォータであればサポートへ依頼し拡張可能ですが、 上限に対する使用状況を把握していないと、使いたい!というタイミングで使えず、 2, 3 日の待ち時間が発生する可能性があります。

また、拡張できるものであればよいのですが、途中まで構築したのに拡張不可のクォータに達してしまい、別のサブスクリプションに変えざるを得ないような状況になっては大きな影響がでてしまいます。

そうならないようクォータを意識することは重要ですが、現状は Azure ポータルや Azure Monitor で通知する仕組みがないため、今回のような API を用いた仕組みが活用できるかと思います。

API の URI を変更すれば他のサブスクリプションやリージョン、コンピュート以外のクォータも取得が可能ですし、条件を変えていろいろな値を取ることができるためお試しください。