LinuxユーザーがイジるはじめてのAzure

LinuxユーザーがAzureを使いこなせるように応援するブログです

Bicep で IaC を実現する(2)

前回のブログの続きです。

 

Bicep を利用する上での勘所を書きましょ。だけど今回の記事は文字だらけですw見栄えは最悪ですが、bicep をガチで触った人にだけは伝わる内容かと思います。

 

■依存性と更新の問題を回避する

依存性というのは Bicep でいうところの parentプロパティやscope、dependsOn、あと暗黙の依存、なんかがあります。いわゆるリソース同士が親子の関係になっている部分や依存性のあるデプロイ処理を指定することで、その処理が終わった後に実行しなさい、といった順序を意識して実装する部分ですね。

 

1番簡単な例でいうとHub&Spoke vNETを作成した後、Azure Firewallをデプロイしたいとします。この場合はAzure Firewallをデプロイするためには、仮想ネットワークおよびAzureFirewallSubnetが存在していないといけませんよね。ですので Azure FirewallをデプロイするBicepファイルの処理には dependsOn を付けてHub&Spoke vNETを作成する処理の vnet.bicep ファイルが終わってから実施するように考慮する必要があります。

 

ところが、ここには後々問題になるケースがあります。Spoke-vNET/SubnetにUDR(Route Table)を付与してAzure Firewall のPrivate IP addressへデフォルトルートを入れたい処理をどうするんだ?という問題が発生します。Azure Firewall 経由でSpoke-vNET/Subnetからの外部アウトバウンド通信は全て一任させたいわけです。このまま進めようとすると、Azure Firewallがデプロイ完了して初めてprivate ip addressが確定するため、その情報を既にデプロイが終わった spoke-vnetのsubnetへ関連付けさせたい、だけど更新ってどうするんだ?existing リソースに対する更新はできないよね?再度spoke-vnet/subnetの作り直し処理を行うのか?それって既存リソースで利用されているTCP通信が断絶されることにならない?ってなっちゃいますよね。Azure Portalから操作すれば特にこういった問題は起きないのですが、Bicep ではできれば冪等性を重視して Bicepファイルで一括で実施できるようにしたいですよね。

 

ここでの考え方は大きく2つあります。1つは Bicep ファイルを1つにしてしまい、そこでvNET/Subnet、Azure Firewall、Routetableを全て作成し、関連付けから何から全てをそのbicepファイル1つで集約させてしまい、暗黙の依存に委任させる、というやり方です。暗黙の依存、と聞くとちょっと細部がわからず困るケースも出てきますが、VS CodeのBicep拡張機能を入れておけば、黄色波線でdependsOnが必要な箇所なのか不要な箇所なのかをちゃんと教えてくれます。例えば module キーワードで別bicepに特定のパラメータを受け渡したい時に、そのパラメーター変数の値を入れているのはそのbicepファイル内に記載している resourceキーワードの処理で生成される場合、わざわざmodule キーワードの処理の最後にdependsOn を指定しなくてもよい、というのが暗黙の依存です。ただし、この1ファイルでまとめて記載する、というやり方は小規模開発においては問題ありませんが、中・大規模開発となり、一人ではなく複数人で開発を行うチーム開発には向きません。ソースレビューの範囲も広く、メンテナンスがしんどいからですね。

 

ではどうするかというと、Hub&Spoke vNETを1つの bicep ファイルで作成するのではなく、2つの bicep ファイルでhub-vNETを作成する部分とspoke-vNETを作成させる部分と分けるんです。こうすることで、hub-vnetを作成した後にAzure Firewallをデプロイし、private ip addressをspoke-vnet作成する処理のパラメーターとして渡してあげる、という構図が出来上がります。

 

気付いたと思いますが、そうなんです、Bicep を扱うためにはシーケンシャルマップを最初に設計することが重要なんです。どのリソースがどのリソースとの連携にどんな要素が必要かを最初に洗い出さないと、上記のような実装を進めていく上でデッドロックすることになります。こういったことがないよう、オフィシャルサイトではBicep ファイルを分ける場合には、なるべく疎結合可能な処理を実装することを心がけましょう、っとあります。つまりリソース単位でなるべく小分けにして疎結合可能な処理のみをbicepファイルに記載する、ということです。そうすれば修正する箇所と依存性を考慮する部分を最小単位で対応することができる、というわけです。

 

■システム運用時にカスタム更新が発生するものと機密性情報を扱うもの

単に動けばよい、というソフトウェア開発のマインドでいけば、ここはたいして考慮する必要はないのですが、IaC となると話は別です。なぜなら冪等性重視の観点からすれば何度デプロイしても同じ結果になることを重視しているため、システム運用も考慮した実装をしなければ単なる初期導入だけに利用される便利なツール、で終わります。

 

ではどんなシステム運用を想定した実装をすればよいのか、ここでは1番簡単な例を出すと、NSG(Network Security Group)の運用を出しましょう。Azure の初期構築を実施する時には、大抵のケースでログインポート(RDP/SSH)のみ許可し、それ以外はブロックする、といったホワイトリスト運用で開始されるケースが大半だと思います。ですが、特定のプロジェクトではDNSサーバーを立てるので53ポートを開けてほしい、とか、nginxを入れるから8080ポートを開けてほしい、といった個別依頼の要求がシステム運用時に起きます。その依頼を受けた情報システム部門は、NSGのルール設定を確認しては追加作業を行い、Subnetに関連付けさせている他のNSGの設定なども確認しながら作業を行うでしょう。こういった個別更新が起きるたびに、bicep ファイル本体であるソースを修正する、というのはヒューマンエラーも起きやすく、なるべくソースにハードコートされた修正は避けたいものです。

 

ではどうするかというと、loadJsonContentといった関数を使い、ソースとは別にjsonファイルから必要なkey:valueを外部ファイルから取得する、といった実装をします。こうすることで単なる定義ファイルの1つとして扱う運用ができます。ソース本体に手を下すことなく定義ファイルのみ更新する、なるべくこういった資材の管理をしたいですよね。

 

ただし、機密情報を扱うケースは別です。機密情報というのは企業によって定義が変わりますが、例えばVMにログインする際に使うパスワードはどうしましょうか。当然VM作成時にハードコートしてべた書きする、var変数に固定値を入れておく、なんてのは論外です。jsonの外部ファイルに保管する、としても、それが漏洩すれば誰だってログインできちゃうことになりますし、誤ってgithubへpush してしまった日にはもう、、となりますよね。

 

そこで登場するのがAzure keyvaultですね。keyvaultリソースを作成する際にはどうしてもパスワードそのものを記載してデプロイする必要がありますが、それ以降は全てgetSecret関数とSecureデコレータを使って安全に取り出す実装をしたいものです。それであればHSMの強固に守られたkeyvaultに安全管理を委任させ、ソースコードや変数やパラメーターファイルなどで管理する必要もありません。もしくはkeyvaultだけは別のリソースグループでAzure Portalから作成しておき、必要なシークレットのみワークアラウンド作業として手作業で管理形態を別にしておき、bicep ではkeyvaultにアクセス可能なユーザープリンシパルIDだけ使い、scopeでkeyvaultが配置されているリソースグループを既存参照で指定し、getSecret()とsecureデコレータのみの実装をする、というのもアリでしょう。

 

という具合に頻繁に更新がされるものは外部定義にする、更新はさほどではないかもしれないが機密性の高い情報を扱う必要がある場合はkeyvaultを利用する、といった実装を最初から心がけておきましょう。(keyvaultのgetSecret関数は、moduleキーワードでパラメーターを渡す時のみ利用できる関数、という仕様制限もあるので、bicep全体の処理順序にも影響するのでここは注意です)

 

■ scopeで追加する拡張機能は1番最後に実装し、個別管理できる状態にする

これはbicepファイルを複数に疎結合した配置で意識した中・大規模開発におけるお作法に近いですが、scopeで追加する処理の中では特に診断設定やRBAC、ロック、この3つは比較的よく利用される機能になります。便利なことにこれらの拡張機能と呼ばれるものは、リソースがデプロイされた後に追加することができます。つまり構築したいコントロールプレーンのリソースを全て整合性を維持した実装ができれば、1番最後にscope処理でRBACの権限設定や診断設定をすればよい、という発想になります。そして2つ目に記載した頻度の高い更新もRBACでは発生します。scopeによる拡張機能の追加はbicepファイル処理では1番最後の後付け処理として位置付け、RBACの処理のみjsonによる個別外部定義で反映できる状態にしておく、というのが管理方法として適切かと思います。

これをやっておかないとハマるケースとしては、例えば以下のようなケースです。最初にLog Analytics Workspaceを作成し、vnet作成の前処理として依存性を持たせます。なぜならvnetの診断設定を入れる際にLAWへデータを飛ばす設定をvnetの処理に追加したいからですね。だけどこれを先に実装してしまうと、後からAMPLS(Azure Monitor Private Link Scopeを追加し、Private Endpointを作り、Private DNS Zoneを作成する処理を行うと、最後にLAWのPublic Access Data Ingestを拒否させたい処理ができなくなってしまいます。LAWは既に存在するし、Public Access Data Ingestの設定はLAWのproperties処理内で記載する仕様になっているため、どうしたらよいかがわからなくなります。こうならないように、順序としてはvnetを先に作り、AMPLS/PE/DNS Zoneの作成とLAWの作成を行う順序に変更し、最後にvnetの既存リソースを参照して、それをscopeさせて診断設定を入れる、という順序にします。

 

長くなったのでこのあたりにしますが、他にも配列で実装した場合の参照時の罠などもありますが、1番重要なのはシーケンシャルマッピングを最初の設計時に意識し、どういったbicepファイルの管理が1番自分たちの運用において楽になるか、を意識して取り扱いましょう。

Bicep で IaC を実現する

久しぶりの更新です。

 

みなさん、IaC ( Infrastracture as Code ) 好きですか?

TerraformやARM templates、Cloud Formation、Chef、Ansible などなど様々なクラウド環境のインフラ構築を自動化するOSS技術や、クラウドベンダーから提供されているサービスもいくつかありますよね。

 

今回の記事は Azure が提供する IaC を実現するための Bicep (ばいせっぷ) について記載しましょう。既に Azure Resource Manager Templates を利用されている方や過去に触ってみたことがある方、はとっつきやすいと思います。

 

でははじめましょ。

 

■ Bicep って何?

 ばいせっぷ、と呼びますが、英語で上腕二頭筋、つまり「力こぶ」を表す英単語になります。Azure Resource Manager Templates は ARM Templatesと訳されることが多く、ARM、つまり腕、、その腕をさらにパワーアップさせる力こぶ!というニュアンスから来たネーミングのようです。※こういうセンス嫌いじゃないw

 

ではそもそもBicepとは何か、という話ですが、単純に言えばJSONを生成するためのラッパー言語です。ARM templatesはJSON形式でゴリゴリ記載することになるため、かなりしんどいです。構造定義を読み解く、書き込むにはかなり職人芸的な位置づけでした。そんな職人しか扱えないようなARM templatesを、Bicep という言語をかぶせることで楽に書けるようにした、という位置づけとなっています。ですのでBicepファイルをコマンドラインVisual Studio Codeなどから実行すると、内部的には一旦ARM templatesにジェネレートされてAzure APIへ通信にいく、という構図になっています。また、ファイル変換もできるようになっており、JSON to Bicep、Bicep to JSONといったファイルフォーマットを変換させることもできます。

 

当然、ARM templateではできないことはBicepでもできません。新しすぎるサービスのAPIがtemplate referenceにもまだ対応できていなければ当然bicepでもできません。(ほぼそういうことは起きないような設計になっていますが念のため)

 

■ どうやって使うの?

ARM templatesと同じように、Azure CLI、Azure PowerShellからBicepファイルを指定してデプロイさせる、ということもできますが、1番のお薦めはVisual Studio Code(無償エディタ) です。Visual Studio って聞くと、なんだか難しそうでC#使いが利用する開発ツールじゃね?ってイメージはあるかもしれませんが、なんてことはない、VS Codeは単なるエディタとして使うだけです。

 

ダウンロードは以下。

Visual Studio Code – コード エディター | Microsoft Azure

 

なぜ Visual Studio Code がよいのか、というと拡張機能が豊富になっているからですね。例えばARM templatesであれば Azure Resource Manager Toolsという拡張機能VS Codeからインストールすると、jsonの各項目が色分けされて表示し見やすくなりますが、同じようにBicep拡張機能(Bicepという名前であります)をインストールすると、色分けはもちろん、VS CodeからBicepファイルを実行したり、アカウント設定がされていればサブスクリプションの選択やResource GroupをBicepファイル実行と共に作成してくれたりします。また、IntelliSenseと呼ばれる次に記載する内容をプルダウン形式で選択できるようになる機能もついているため、毎回オフィシャルサイトを見ながらコピペして、、みたいなこともせずにゴリゴリ書けます。

 

■ どんなことができるの?

Azureリソースを全てBicep で記載し自動構築することができます。ARM templatesもそうですが、Bicepも直接APIをコールする形になるため、Azure API Referenceで記載されているものはなんだって実装できちゃいます。例えば、こんなポンチ絵を見た時に、みなさんはどうやって構築していくことをイメージするでしょうか?

 

 

Azure 構築に慣れている人であれば、あーよくあるvNET hub&Spoke構成だね、ネットワークルーティング経路はなんとなくイメージできるけど、細部まではちょっとわからないなぁ、っと感じることもあるでしょうし、えっと、これをSIとして受けて構築するとしたら0.7人月x2ぐらいは必要かなーっとイメージされる人もいるでしょうね。

 

こんな環境が、Bicepだと、bicepファイルを1つ実行するだけで「わずか7分」で全部できちゃうんです!

 

って、いやね、別に速度をアピールしたいわけではないんです。この環境の各リソースにはRBAC権限設定も入れ、診断設定もLog Analytics Workspaceに飛ばしてますし、ネットワークウォッチャーのNSG Flow Logsも連携してて、keyvaultにはVMへログインするAdminパスワード(linuxはrootパスワード)もちゃんと保管して、セキュアに取り出すようにし、Azure Firewallのアプリケーションルールやネットワークルール、NSGの受信規則なども最低限必要なルールセットを全て入れており、AppGWはWAFでOWASP3.1のWAF Policyとも関連付けさせてIDSとして機能させ、特定のIP address レンジからのアクセスのみをブロックさせるような個別ルールも入れてるんですね。そしてCloud Adption Frameworkに記載されているような命名規則もちゃんと守ってリソース名を付けてタグもちゃんと全てのリソースに付与してます。

 

これらをARM templatesでやろうとしたら依存性の問題やら書き方やらでクッソしんどいことになるんですが、なんとこの環境を作るbicep開発にかかった時間はたったの2週間です。0.5人月x1で7分で構築できちゃうIaCが実現できちゃうわけです。

 

もちろん同じリソースグループに何度もデプロイし変更要素だけを反映させることもできますし、別のリソースグループや別のサブスクリプション、別のテナントだってtargetScopeを変更すれば同じものを7分で構築できちゃうわけです。

 

ドキュメント見ながらAzure Portalでポチポチやったり、個別個別でpowershellやAzure CLIスクリプト作って個別最適された自動化ツールを作るのもよいですが、今の時代はこういう環境を丸ごと構築できちゃうような開発がインフラエンジニアでもできちゃうんだよ、ということを知ってほしいなと。

 

■ サンプルちょーだい

localtemplate/bicep/BICEP at master · akkoike/localtemplate (github.com)

 

getStart.bicepをVS Codeから実行すればできちゃうサンプルコードです。VS CodeでAzureへログインできるアカウント設定をしておき、githubアカウントと連携させてgit cloneでもやってローカル環境のVS Codeに落とし込んでやってみてください。最初に自分の設定を入れる必要があるので、そこだけgetStart.bicepの最初のコメント行を読んでおいてください。

 

ちなみにここで作られる環境は1日放置しても1500円ぐらいです。(Azure FirewallとApplication Gatewayだけ、立てるだけでそこそこ金かかるけど、もっと安くするなら最近出たAzure Firewall BasicにSkuを変更してもよいでしょう)

 

■ ハマりどころと勘所

いくつかあるので、ここでは長くなったのでこの辺にし、次回の記事にでも記載しますね。まずはbicep触ってからじゃないと伝わらないことが多すぎるのでw

 

今回はここまで。

 

 

 

 

リソースIDの一括取得とタグ情報の一括出力

ども、みなさんタグ使ってますか?

 

AzureでのタグはKey:Value形式で設定していきますが、基本的にはリソース名の命名規則に入れたかったけど長すぎて見づらくなるため断念した管理情報なんかをタグ情報に入れることがよくあるケースかと思います。

 

例えばこんな感じで設定しますよね。

 

Azure Portalからも設定できますし、1つ1つのリソースに対して確認することも視覚的にもやりやすく実装されています。また、AWSのように特定のバッチ処理を走らせるかどうかの判定フラグようにタグ情報にバッチの最終終了時間などを更新して入れておき、バッチ起動時にそのタグ情報の日時を見てバッチサーバーからバッチ処理を走らせるかどうかを決める、といった運用をされている方もいます。

 

そんな便利なタグ情報ですが、、、

 

が、

 

が、

 

が、例えば上記のようなタグを付与したリソースが300個以上ある、タグも1つや2つじゃなく5個10個ある、といった場合においては、各リソースにタグがちゃんと付与されているかどうかってどうやって確認しましょうかね?

 

もちろんサブスクリプションやリソースグループの分け方によって、1か所のリソースグループにそんな大量なリソースがデプロイされているケースも少ないかもしれませんが、Cloud Adption FrameworkやWell-Archited Frameworkなんかでは、開発・検証・本番用でワークロード毎に分けてリソースグループを作成しましょう、というお作法があるので、エンタープライズなお客様において長くAzureをご利用されているケースは、本番用リソースグループ内では普通に大量にリソースがあるのではないかと思います。

 

また、リソースを作成する際に必ずタグ情報を入れないといけない縛りや、もしタグ情報が付与されていない場合は自動的にタグ情報を付与する、といったAzure Policyの定義(厳密には複数のタグ情報を付与する場合はカスタム定義)があるため、DeployIfNotExistsなどを利用すればモレはなくなるであろう設定はできます。

 

ご参考:

チュートリアル:タグ ガバナンスを管理する - Azure Policy | Microsoft Learn

 

ただ、Azure Policyの初期設定(割り当て)の際に、どれぐらいの頻度で既存リソースにタグが継承されていくのだろうか、ちゃんと想定している通りタグ情報が特定のリソースグループ配下のリソースに継承されているだろうか、というテスト目的も含めた確認を行いたい場合、200も300もリソースがあるとAzure Portalで目検チェックするにはさすがにシンドイのが実情でしょう。

 

ということで、リソースグループからリソースを特定し、そのリソースについているタグ情報だけを出力させたい、といったことやってみました。(やっと本題のはじまりw)

 

まず、Azure Portalにログインし、利用しているサブスクリプションを確認してリソースグループの一覧を取得するためCloudShellを起動しましょう。(bash

 

●リソースグループ名一覧の取得

 az group list | jq -r ..name

※jqコマンドはCloudShellのbashだとビルトインされているはず。

 

サンプル出力結果

akira [ ~ ]$ az group list | jq -r ..name
Rg-Dev-Hub-Poc-001
Rg-Prod-Hub-Poc-001
Rg-Stag-Hub-Poc-001
Rg-Dev-Spoke-Poc-001
Rg-Prod-Spoke-Poc-001
Rg-Stag-Spoke-Poc-001
Rg-Dev-Workspace-Poc-001
Rg-Prod-Workspace-Poc-001
Rg-Stag-Workspace-Poc-001
NetworkWatcherRG
cloud-shell-storage-southeastasia
Default-ActivityLogAlerts
akira [ ~ ]$ 

 

とりあえずこれで自分が利用しているサブスクリプションで利用されているリソースグループ名の一覧は取得できました。

 

次に、そのリソースグループ内で利用されているリソース名の一覧を取りに行きます。

 

●特定のリソースグループ名に対して、その中に存在しているリソースのリソースIDのみ一覧で取得

az resource list --resource-group Rg-Dev-Spoke-Poc-001 | jq -r ..id

 

サンプル出力結果(サブスクリプションIDだけマスクしてます)

akira [ ~ ]$ az resource list --resource-group Rg-Dev-Spoke-Poc-001 | jq -r ..id

/subscriptions/サブスクリプションID/resourceGroups/RG-DEV-SPOKE-POC-001/providers/Microsoft.Compute/disks/Vm-Dev-Spoke-Poc-001_OsDisk_1_ef5e0627bee342eb8febcd9b79ace92c
/subscriptions/サブスクリプションID/resourceGroups/RG-DEV-SPOKE-POC-001/providers/Microsoft.Compute/disks/Vm-Dev-Spoke-Poc-002_OsDisk_1_08915eedb40f4aaf98ecc70db011df1a
/subscriptions/サブスクリプションID/resourceGroups/Rg-Dev-Spoke-Poc-001/providers/Microsoft.Compute/virtualMachines/Vm-Dev-Spoke-Poc-001

以下省略
akira [ ~ ]$ 

ここまで来てようやくリソースIDに対してタグ情報を出力することができます。

 

●リソースIDからタグ情報のみ出力

az tag list --resource-id ${リソースID} | jq .properties.tags

 

サンプル出力結果

akira [ ~ ]$ az tag list --resource-id /subscriptions/サブスクリプションID/resourceGroups/RG-DEV-SPOKE-POC-001/providers/Microsoft.Compute/disks/Vm-Dev-Spoke-Poc-001_OsDisk_1_ef5e0627bee342eb8febcd9b79ace92c | jq .properties.tags
{
  "CostCenterNumber": "10181378",
  "date": "2022/12/09",
  "division": "Cloud Solution Architect Division1",
  "location": "japaneast",
  "owner": "akkoike"
}
akira [ ~ ]$ 

 

というわけで、これをシェルスクリプト再帰的に処理するように落とし込むと、こんな感じでしょうかね。

 

#!/bin/sh

for RG in `az group list | jq -r ..name`
do
        echo ${RG}
        for RESOURCE_ID in `az resource list --resource-group ${RG} | jq -r .
.id`
        do
                echo ${RESOURCE_ID}
                if [ "${RESOURCE_ID}" != "" ]
                then
                        az tag list --resource-id ${RESOURCE_ID} | jq .properties.tags
                fi
        done
done

 

実行結果の出力サンプル

 

Rg-Stag-Hub-Poc-001
Rg-Dev-Spoke-Poc-001
/subscriptions/サブスクリプションID/resourceGroups/RG-DEV-SPOKE-POC-001/providers/Microsoft.Compute/disks/Vm-Dev-Spoke-Poc-001_OsDisk_1_ef5e0627bee342eb8febcd9b79ace92c
{
  "CostCenterNumber": "10181378",
  "date": "2022/12/09",
  "division": "Cloud Solution Architect Division1",
  "location": "japaneast",
  "owner": "akkoike"
}
/subscriptions/サブスクリプションID/resourceGroups/RG-DEV-SPOKE-POC-001/providers/Microsoft.Compute/disks/Vm-Dev-Spoke-Poc-002_OsDisk_1_08915eedb40f4aaf98ecc70db011df1a
{
  "CostCenterNumber": "10181378",
  "date": "2022/12/09",
  "division": "Cloud Solution Architect Division1",
  "location": "japaneast",
  "owner": "akkoike"
}
/subscriptions/サブスクリプションID/resourceGroups/Rg-Dev-Spoke-Poc-001/providers/Microsoft.Compute/virtualMachines/Vm-Dev-Spoke-Poc-001
{
  "CostCenterNumber": "10181378",
  "date": "2022/12/09",
  "division": "Cloud Solution Architect Division1",
  "location": "japaneast",
  "owner": "akkoike"
}

以下省略

 

まとめ。

 

ということで特定のリソースグループ内にあるリソース全てのリソースIDを取ることもでき、リソースIDが取れたのでタグ情報を出す、ということができることがわかったかと思います。

 

ちなみに、

 

いやいやそんな面倒なことしなくてもARM templateのExport機能使い、"id":の箇所にあるリソースIDだけを引っ張ってこればよくね?と思う方もいると思いますが、こっちのほうがすげーめんどいです。なぜならconcat関数による文字列結合を使った記載になっているため、例えexport時に「--skip-resource-name-params」を引数に入れてparametersの値を文字列出力したとしても、リソースIDの途中で文字列がぶった切れており、concat関数の文法で使うカッコやカンマなどをくりぬいてスラッシュに置き換える、とかとかクソめんどくさいことをしないといけないからですw

 

今回はいじょーですが、参考となるサイトを張り付けておきますね。

 

az tag | Microsoft Learn

az resource | Microsoft Learn

Azure CLI でテンプレートをエクスポートする - Azure Resource Manager | Microsoft Learn

 

※他にもっと楽ちんで良いやり方があれば教えてくださいww

Azure Load Balancer Basic vs Standard について

Azure Load Balancer、一般的にはALBと略されているものですが、Skuの1つであるBasic Load Balancerが今から約3年後に廃止される計画にある、っといった通知を受け取っている方もいるでしょう。

 

既にStandard Load BalancerがGA(General Available)されていますので、そちらを今後はメインで使うよう切り替えてくださいね、という意図でしょうかね。

 

また、そもそもBasicもStandardもInternal LBとして内部ロードバランサ(Public IP addressを持たない)とした用途で使うパターンと、External LBとして外部ロードバランサ(Public IPを持つ)用途の2パターンありますが、今回のアナウンスではBasic LBの廃止アナウンスとなるので、ILBだろうがELBだろうがBasic Load BalancerのSkuを利用している場合は影響を受ける、となります。

 

とはいえ3年後までに対応すればよいので、そこまで焦る必要はありませんが、BasicとStandardとではいくつか違いもありますし、ただコストが上がるだけのデメリットなのか、というとそうではない、という点を、おさらいも兼ねて解説しましょう。

 

まずみなさん1番気にされる点は費用ですよね、きっと。

●費用

【Basic LB】

Basic LBは基本料金無料でInboundのデータ転送料も無料、Outboundのデータ転送料がかかる、というものです。

 料金 - 帯域幅 | Microsoft Azure

※LBに限らずAzureはAzureから外に出ていくOutbound転送料は一律でかかります。

 (最初の100GBは無料ですが、それを超えると日本リージョンの場合は約15円-16円/GBがかかります。転送料が100GB-10TBの間の場合)

 

【Standard LB】

Standard LBは基本料金(最初の5ルールまで)がかかりますので、約2,500円-2700円が月額でかかります。

 価格—Load Balancer | Microsoft Azure

 

ほぼ無料で利用できていたものが有償Skuに変えないといけない、という意味ではちょっと懐が痛いところではありますね。

 

では、有償に見合うメリットはそもそも何か、という点に着目してみましょう。

 

●機能/スペック

以下にBasicとStandardとの機能比較表がありますので、そちらを参考にしてください。

Azure Load Balancer の SKU | Microsoft Learn

 

割とインパクトあるかな、という点をピックアップすると、正常性プローブにHTTPSが利用できるというのがStandard LBの良い点でもありますね。SSLオフロードが必要なケースはHTTP/HTTPSに特化したApplication Gatewayの利用を推奨しますが、SSL証明書を使った構成は今や一般的ですので、バックエンド側のVM群に対してHTTPSの通信が正常に200OKのレスポンスを返すかどうかでVMの生死を判定できる、というのは、よりサービスの稼働監視として正確に実装できるかと思います。

 

あとはSLA99.99としてついている点や、Azure Monitorの多次元メトリックに対応している点(LB内部の効果測定が可能)なども運用管理の面ではStandardの方が優れているのがわかります。他にも可用性ゾーン(Availability Zone)に対応している点もよいですね。(後述で詳しく記載します)

 

ただし外部通信においてはSNATするためNAT GatewayVMに付けたPublic IPなどの構成と併用した際にOutboundのルーティングにおいてどちらが優先されるかなど、ちょっと考慮すべき点はあります。

 

全体的にBasicよりもStandardの方が機能面でもスケール面でも優れているのがわかるかと思います。

 

では次は、扱いやすさ、設計のしやすさという点ではどうでしょうか。

 

●扱いやすさ、設計しやすさ

以下は、東日本リージョンと西日本リージョンで行った複数の冗長・可用性構成に対してStandard LBを適用したパターンのメッシュテスト結果です。

 

 

noavailvmというのが可用性セットも可用性ゾーンも適用していないシングルVMです。

availvmは可用性セットを付与したVMです。

azdc1/azdc2は可用性ゾーンを適用しゾーンナンバーを1と2にしているVMです。

 

つまり全ての線が青色線ですので、VM側は可用性セットがあろうがなかろうが、可用性ゾーンを適用してようがしてまいが、どのような可用性構成であってもちゃんとStanadard LBからの通信および振り分け対象にすることができる、ということがわかります。

 

LBを使う上で裏側の可用性構成を意識しなくても利用できるのは非常に扱いやすく、設計においても変な罠にはまらない点はとてもよいですね。

 

一方でBasic LBはどうでしょうか。

 

パッと見た感じ赤色線(設定不可 or 通信負荷)が目立つことがわかります。

可用性セットが付与されたVMであればシングルでも複数VMでも適用できますが、そうではない可用性構成の場合は設定できるケースとできないケースが複雑になっており、とても扱いづらそうです。当然アーキテクチャを考慮する上でも、バックエンド側の可用性構成に応じてBasicでも稼働可能か否か、といった注意ポイントが発生します。いかにStandard LBが扱いやすく設計しやすいロードバランサーになっているかが一目瞭然でしょう。

 

最後に。

 

Standard LBのほうが、より標準的に利用でき、今後の開発にも注力されていくことが機能面、スペック面、扱いやすさなどがわかったかと思います。2500円/月支払う価値があるかどうかはお客様の価値観の差になりますね。

また、本記事では詳しく記載しませんが、Basicを使っている環境からStandardへ切り替える際はいくつか考慮すべき点があります。以下にPowerShellから変更するやり方が記載されていますので、こちらをまずご参考ください。

Basic Public から Standard Public へのロードバランサーのアップグレード - Azure Load Balancer | Microsoft Learn

 

また、手動で行う場合およびPublic IP addressを変更したくない場合は、まず仮のパブリックIP(Basic)を新規で作成しておき、既存のBasic LBのFront IP構成に設定されている既存のPublic IPを新規で作成したPublic IP basicに変更しておきます。(この時点で既存Public IPはBasic LBとの関連付けから削除されます)次に取り外したPublic IPリソースをBasicのSkuからStandardのSkuへアップグレードします。最後に、手動でStandard LBを作成する際にFront IP構成を設定する箇所があるため、そこで取り外したPublic IPを指定してあげれば、既存のBasic LBで使っていたPubilc IP addressをそのままStandard LBでも使うことができます。ただしこちらはサービスからのアクセスを一時的に停止して行う手順となるため、リアルタイムで切り替えたい場合は新規で作成したPublic IPからの受付を一時的に許可するよう振り分けしているDNS側の振り分け先として登録する必要があるでしょうね。(ちなみにbasic Public IPも廃止予定ですので今後はStandard Public IPを使うようにしましょう)

 

まぁ廃止が3年後なのでこれからゆっくりと検討・検証して頂ければと思います。

 

【これ何?】Azure Confidential Computing

ども。

 

今回のブログ記事はちょっと今までと趣向が変わり、「これ何?」シリーズの記事にしました。Linuxユーザーかどうかはあまり関係なく、Azureのサービスでこれ何?どんな感じ?というものが出てきた時にさらっと読んで理解しましょう、という趣向で記載しています。

 

まず、タイトルにあるAzure Confidential Computingですが、名前からして何だか機密性の高いコンピューティングの技術なんだろうな、というのは想像できるけど、正直オフィシャルサイトを読んでもさっぱり理解できねぇんだが!という状況かと思います。(読んで理解できた人はこのブログ読まなくてもよいですw)

 

「オフィシャルサイト:念のため」

Azure Confidential Computing の概要 | Microsoft Docs

 

ちなみにですが、Confidential ComputingってのはIntel SGXというプロセッサがTEEを使って隔離空間を作りだして、、、とか、AMD SEV/SEV-SNPのプロセッサの場合は仮想マシンをハイパーバイザ配下から機密性を保持して、、、みたいな説明を記載したところでチンプンカンプンになること間違いないので、そういう難しい技術を難しい説明で伝えるつもりはありません!

 

というかブログを読みに来た人の多くは、なんかセキュリティを高める技術なんだろうけど、使えるの?どう使うの?何がうれしいの?安いの?ぐらいしか興味がないと思いますので、その観点で記載します。

 

では始めます。

 

【そもそも何なん?】

Azure Confidential Computingというのは抽象化されたサービス名となってまして、実態としては4つある技術を総称しています。

 

1,Enclaves(えんくれーぶ、と呼ばれるOS内の隔離空間をそう呼んでいる)

2,Confidential VMs(VM丸ごと隔離空間にするぜ、というもの)

3,Confidential Container(aksのコンテナノード丸ごと、コンテナ内の一部の処理をEnclavesする、の2種類)

4、Confidential Services(上記機密性を維持した環境と連携可能なサービス)

 

【それって使えるの?】

まず1のエンクレーブですが、Intel SGXというIntel社が出している特別なプロセッサを使わないと使えない技術です。なので、どのAzure VMのSkuであっても利用できるものではありません。利用するにはDCsv2 or DCsv3 or DCdsv3 のいずれかのVMサイズを選択した場合のみ利用できます。この技術そのものはむかーしからOSSでもありますが、専用のSDKで実装したアプリケーションを、OS内のメモリ空間に機密性の高いエンクレーブという空間を用意して処理を行う、というものです。このエンクレーブの環境をTEE(Trusted Execution Environment)という技術を使って機密性を高く実現させている、というものです。ちなみに日本では現時点で東日本リージョンしか対応していません。

 

2は、VMそのものを丸ごと機密性の高いプロセッサを使った環境で保護されているよ、というものです。こちらもどのAzure VMのSkuでも使えるものではなく、DCasv5,DCadsv5,ECasv5,ECadsv5のいずれかのVMサイズを選択した場合にのみ利用できます。1のエンクレーブとは異なり、仮想マシンそのものを保護するAMDの技術ですが、Confidential VMを立てたからといって、何か特別なVM操作は必要なく、普通のVMと同じように扱えます。sshやRDPでのログインなども普通にできますし、OS DiskそのものもConfidential VMの仲間としてディスクも機密性高く保護されています。こちらも日本では現時点で東日本リージョンしか対応していません。

 

3は、1のエンクレーブで丸ごと保護されたコンテナノードを作れますよ(Confidential Container)、コンテナ内でエンクレーブを利用することもできますよ(Enclaves-aware Container)、というものです。主にAKSを利用されている場合に、コンテナとしてConfidential Computingに対応したものがほしい時に使います。こちらもどのAzure VMのSkuでも使えるものではなく、エンクレーブと同じくDCsv2 or DCsv3 or DCdsv3のSkuを選んだVMの中でコンテナを丸ごと保護するか、コンテナ内でエンクレーブ環境を用意するか、という使い方になります。1と同じく東日本リージョンのみ現時点では対応しています。

 

4は、平たく言うと周辺サービスですが、現時点ではSQL Database(SQL DB Alaways Encrypted with enclaves)とConfidential Ledger(blockchainのやつ) の2つのみ、データストアとして連携できるよ、というものになっています。いかにConfidential VMやエンクレーブで機密化した環境で実装しようとも、結局データそのものを配置するストレージ空間もIntel SGXやAMDといった特別なプロセッサで対応された環境でないといけないため、これら2つ用意しておいたよ、というものです。なのでConfidential Computingの中で連携できるサービスや機能だよ、という代物ですね。

 

【どう使うの?】※3と4は長くなりそうなので割愛

1のエンクレーブについてはIntel SGXに対応したAzure VMのSkuを選択し、その中でSDKを展開した実装して使います。対応しているSDKは以下です。

ダウンロードやインストールなどはオフィシャルサイトからリンクされているので、そちらを参考にしましょう。

Azure のコンフィデンシャル コンピューティング開発ツール | Microsoft Docs

 

2のConfidential VMについては何も考える必要はないです。前述した通り、DCasv5,DCadsv5,ECasv5,ECadsv5のいずれかのVMサイズを選択して、普段通りAzure Portalからデプロイすれば作成できます。(Portalではこのサイズを選択すると、Confidentail VMとして利用するかどうかのチェックボックスや選択フィールドが出てくるので、そこを選んで作成しましょう)

 

【何がうれしいの?】

1ですが、このエンクレーブの空間は機密性が高いため、アプリケーションが実行されているメモリ空間に対して、例えば管理者がgdbgcoreなどを使ってメモリダンプをしようとしても、出力が全て「?????」で埋め尽くされる、というガードが強くかかっているものです。なのでアプリケーションだけが内部的な処理をエンクレーブ内では平文でやっているけど、アプリケーション以外からは一切中身が見えない、わからない、というものです。VM管理者やOS管理者は内部の人間だけど、性悪説にのっとり内部犯そのものも物理的に防御する対策を講じたい、といった場合にうれしいものです。

 

2は、そもそもユーザー側でその恩恵を感じ取ることはまずないでしょう。なぜならこの技術はAMDを利用したHW上で展開した仮想マシンが物理的に機密化されている、というもののため、その仮想マシンを利用しているユーザー側の恩恵はありません。唯一あるのが、提供元である事業者や提供されているプラットフォームの管理者すら「信用しない!」と定めた場合です。つまりAzureっつっても、結局仮想基盤やハードウェアを管理しているマイクロソフトのエンジニアからしたら、うちらの仮想マシンも中身を覗くこともできちゃうよね?といった契約や紳士協定だけでは納得できない危篤高尚な方にとっては安心できる環境かもしれません。

 

【で、安いの?】

値段がネックで利用を見合わせる場合は買うべし、値段以外がネックで利用を見合わせる場合は買うな、っとどっかの偉い人が名言を出していたような記憶がありますが、ぶっちゃけ高いです。vCPUの数にもよりますが、同等のスペックで一般のVMサイズと比較すると約5倍程します。暗号化という技術そのものは本来高いものですが、今回のように専用のプロセッサを利用しないと実現できないような特殊な技術であればあるほど安くはない、っとお考えいただいた方がよいかと思います。

 

最後に。

実用性についてですが、正直Azure環境で本番展開するにはまだまだ発展途上な感じが否めない状況です。例えばAzure BackupやAzure Site Recovery、VMSSなどにもまだ対応できておらず、スポットVMエフェメラルディスク、高速ネットワーク、ライブマイグレーション、共有ディスク、ウルトラディスクなどにも対応はできていません。また、当たり前ですが、Confidential Computingのサービスを利用したからといって100%安全です!っていうわけではありません。そもそも通信経路が暗号化されているか、通信先のデータのセキュリティは担保できているか、しかるべき権限のみアクセス可能な状態か、MFAといった本人確認の対策を多層で管理されているか、ネットワーク層でのアクセス制御、ミドルウェア層でのOS内脆弱性防御、データ層での監査フローなどなど、セキュリティ対策とは各レイヤにおいて、対象とするリスクと効果を把握した上で自社にとって最低限必要な仕掛けを予算と鑑みながら展開していくものです。最新のプロセッサ技術を使って高い金払っているからもう安心だぜ!なんてことは絶対ありませんのでご注意ください。

 

この記事を最後まで読んでいただいた方はもうお分かりですね、OS内管理者やVM管理者ですらアクセスできない隔離空間を使った実装をしたい、(カード情報や個人情報、最重要機密情報などを扱う処理部分のみ適用する、など)または、提供されるプラットフォームや事業者に問わず、どこであったとしても我々利用者しか中身が管理できる自社のスタンス/ポリシーを維持する必要がある、こういったケースにのみ、Confidential Computingを利用してみようか、っと検討の素性にあがるものです。

 

Azure でプロセス監視

システム監視やサービス監視をAzureプラットフォーム上で構築する、といった話はどの案件であっても必ず存在しますよね。ただ、監視といっても様々な機能要件があり、単純な稼働監視だけでなく、CPU使用率やメモリ消費率、ディスクの空き容量やプロセス監視、ポート監視など、細かい要件が存在します。

 

もちろんAzure VMにZabbixをインストールして監視システムを組み立てることもできますが、可能な限りサーバー管理を必要としないAzureの機能だけを使って組み立てたい、といったニーズも少なくありません。

 

ここでは、Azureでは対応しているの?していないの?っと特に疑問に思われてきたプロセス監視について触れたいと思います。

 

まず、結論から言うとAzure VMのOS内で起動しているプロセスが起動しているかどうかのプロセス監視は、Azure Monitorを使って実現することができます。

 

先にそのやり方を記載すると、Log Analyticsで以下のクエリ検索を実施することで、特定のプロセス名が対象VMにて起動しているかどうかを定点観測することができます。

 

let ApacheProcessId = toscalar (
    VMProcess
    | where Computer startswith "u003"
    | where ExecutablePath contains "apache2"
    | top 1 by TimeGenerated
    | project Process
);
InsightsMetrics
| where Name == "Heartbeat" and Origin == "vm.azm.ms/map"
| where Computer startswith "u003"
| where isnotempty(ApacheProcessId) and Tags contains ApacheProcessId
| where TimeGenerated > ago(5m)

 

上記クエリのサンプル結果が以下です。

※事前にVM Insightsを適用しておく必要があります。

 Azure portal で 1 つの仮想マシンまたは仮想マシン スケール セットで Azure Monitor を有効にする - Azure Monitor | Microsoft Docs

 

f:id:akazure:20220303124326p:plain

クエリ内容の"u003"と記載したVM名と、"apache2"と記載したプロセス名を任意な値に変更することで汎用的に利用できるようにしてあります。また、出力結果がわかりやすいようにクエリを実行した時間から5分前までのプロセス起動状態を出力してありますので、このクエリの結果をそのままアラートルールへ関連付けさせ、条件やアクションからアラートグループの中でメール通知を行う、といったことができます。

 

クエリについて少し補足するとこんな感じです。

1番ややこしい部分は、InsightsMetricsというテーブルでは、確かに起動しているプロセス状態を定期的(1分ここでいう間隔)にデータ投入されているのですが、肝心のプロセス名(ここでいうapache2)が、どのレコードにも記載されていません。そのためInsightsMetricsテーブルだけで操作しようとしても無理だという点です。InsightsMetricsテーブルでは、p-xxxxxといった一意な識別子が入っており、この識別子がいわゆる各プロセスを表すコードになっているため、apache2のプロセスがp-xxxというどの識別子に置き換えられたかの情報が必要になってきます。

 

そこで、プロセス情報のマスターテーブルのような位置づけとなっているVMProcessというテーブルから、apache2という名前のプロセスが、p-xxxxxというどんな識別子に解釈されているのかを引っ張ってこないといけないわけです。

 

クエリ上位にある「let」から「);」までは変数の格納を表す関数のため、VMProcessテーブルで該当の識別子のみを「ApacheProcessId」という独自でつけた変数名に代入している処理を行っています。そしてInsightsMetricsにて、「where Tags contains ApacheProcessId」とすることで、Tagsレコード内にapache2として識別されたp-xxxが部分一致するかどうかを判定しています。

 

ここまで来てお気づきの方もいますが、「いや、プロセスが起動していることはわかるんだけど、ポートがListenしているかも合わせてみたいんだよね」という話もあります。

 

ポートはVMBoundPortというテーブルに定期的にデータが入ってきます。

VMBoundPort
| where Computer == "u003" and Port == "80"
| where TimeGenerated > ago(5m)

出力結果サンプルは以下です。

f:id:akazure:20220303124845p:plain

 

なるほど、っと思われる方も多いと思いますが、もう少しいろいろとこだわってみましょう。

 

確かにプロセスの起動ステータスやポートの受付状態などは監視することができますが、プロセスの起動本数を監視したい、ポートに対して正常に通信が確立するかを監視したい、といった要件もあります。

 

残念ながらプロセス起動本数の監視は現時点でのAzure Monitorの機能だけでは厳しい状況かと思います。ただ、できないわけではありません。以下のようなスクリプトを用意し、判定された際にloggerコマンドでログ出力させれば、そのログが定期的にLog Analytics WSへ反映されます。

 

#!/bin/sh

HTTPCOUNT=`ps -ef | grep -i apache2 | grep -vc grep`

if [ ${HTTPCOUNT} -lt 3 ]

then

  logger -p local0.crit "apache2 process down! please check"

fi

 

つまりLog Analytics側では「"apache2 process down! please check"」というメッセージがsyslogへ出力されたレコードを定期的にチェックしておき、HITしたらアラートルールや通知を呼び出す、といった連携方法になります。

 

次にポートがListenしているだけではなく、定期的にポート通信が確立しているかの監視については、Network Watcherの接続モニターで可能です。

接続モニターを作成する - Azure portal - Azure Network Watcher | Microsoft Docs

 

要点だけ記載すると、ソースとなるVM(特定のポートを発信する側)を選択し、そのVMにNetwork Watcher Agentをインストールします。そして対象とするVMを選択します。(Private IP address指定可)最後にシナリオを組み立てます。シナリオでは、何番のポートでエラー率や頻度などを組み立てます。ですので、どのVMであってもZabbixサーバーのように監視システムとして機能させることができるよ、というものです。

 

今日はこのへんで。

Azure 仮想ネットワークのハブアンドスポークについて

Azure の案件対応をしていると、時々vNETの構成について相談を受けることがあります。相談内容としては、ネットワーク設計といったハイレベルでの検討状態の時に生まれるネットワークセグメントの分け方やオンプレとの繋ぎ込み、ルーティング優先度、各PaaSサービスとの接続方式などなど多岐に及びますが、仮想ネットワークのハブアンドスポーク構成に疑問を持たれる方も少なくありません。

 

そもそもvNETをHub&Spokeで分けることにどんな意味があるのか、ご利用されていないお客様ほどピンとこないケースも多いようです。

 

この記事ではそんなvNETのHub&Spokeについて記載します。よくある構成はこんな感じでしょう。

 

f:id:akazure:20211206130946p:plain

 

まず大前提の話からすると、1vNETで詰め込んだ構成をするのも、2vNETでHub&Spoke構成にするのも、どちらでも技術的には可能です。つまり192.168.0.0/16と大きな1vNETを取ってリソースをデプロイしていくのも、192.168.0.0/20と192.168.16.0/20と2つのvNETに分けるのもどちらも構成可能です。

 

次にAzureではどちらが推奨かと問われるとHub&Spokeで分けた構成を推奨しています。1vNETで詰め込んだ構成は非推奨というわけではないですが、どちらが推奨構成かと問われれば2つに分けて管理される方を推奨としています。

 

では大きく3つの観点から見ていきましょう。

 

コンプライアンスから見た観点

ISO27001、つまりISMSの観点ではネットワーク分離という章があります。経産省が出している情報セキュリティ管理基準にも同様の内容が記載されています。そこでは、サービスを利用する側とサービスを提供する側のネットワークを分けることが望ましい、とか、役割や権限を整理しアクセス可能な利用者を限定することが望ましいといった事項が記載されています。つまりvNETだろうがSubnetだろうが、ちゃんと利用する人と管理する人を分けてリソースをデプロイし、それぞれRBACや場合によってはPolicyなどで権限分掌および制限を付けて管理しましょう、となります。この記事を読んでいる方はオンプレのシステムを利用している方も多いと思うので、イメージでいうとこうです。オンプレで自分が利用しているサーバーが外部インターネットへアクセス可能だとしたら、そのインターネット向けまでに経由するプロキシサーバーや、その上位コアルータやスイッチなどの設置や管理もご自分でされていますか?おそらく、あーそこはネットワーク管理者がやってるよ、自分は操作どころかログインすらできないよ、といった当たり前じゃん!的な返答があると思います。その通りです、その通りの構成をAzureというプラットフォームでもお作法守って構成しましょう、というのがネットワークをちゃんと分けましょう、という分離の話です。ですがコンプライアンスから見てもvNETで分けなさい、Subnetでは分けないでください、といったセグメントレベルで明文化されたものはありません。つまりコンプライアンスの観点では1vNETであっても複数Subnetで権限分掌を行いアクセス経路や利用者が限定された管理ができていれば問題はない、とも見えます。コンプライアンスの観点ではどちらであるべきといったことは記載されていないことがわかります。

 

●Azureにおける制約や制限の観点

じゃあ1vNETでSubnetレベルで分けるやり方でもいいじゃん、という話になりそうですがAzureには各リソースにおいて制限がたくさんあります。例えば以下を例にしましょう。

 

ExpressRoute 用の仮想ネットワーク ゲートウェイについて - Azure | Microsoft Docs

各仮想ネットワークに配置できる仮想ネットワーク ゲートウェイは、ゲートウェイの種類ごとに 1 つに限られています。

 

つまり1vNETで管理していると、ExpressRoute GatewayVPN Gatewayも、それぞれ1つずつ作ってしまうと、2個目は同じvNETには立てられないという制限になります。なのでこの場合はゲートウェイが設置された別vNETをもう1つ用意し、既存のvNETとピアリングするか、新設したvNETにワークロードのシステムをデプロイし、さらに1vNET詰め込み用途を用意するか、といった話になります。既に感じられつつあるように情報システム部門が統制しようとする管理対象とは別に再度野良システムを管理するための管理ネットワークが無数に広がっていく図式に陥ります。一方でHub&Spokeの場合はというと、新たにvNETを用意しないといけない要件は変わりませんが、Hub-vNETだけが基本的に増えるだけになります。

 

既設のSpoke-vNETへのアクセスは新規で建てたHub-vNETへピアリングを張るだけでよいです。また、新規でSpoke-vNETを立てて親設のHub-vNETとピアリングを張り、Hub&Spokeをもう1セット増やすスケールもアリでしょう。そしてなによりも、既設のSpoke-vNETと新説のSpoke-vNETとの接続部分はデフォルトルートとなるHub-vNETを経由する図式を取るため、情シスのネットワーク管理者が管理するHub-vNET間経由(主にAzure Firewallで制御)でルーティングの統制ができます。(やればできちゃいますが、Spoke-vNET同士でvNET Peeringを行うとすべての通信が情シスで管理対象にならなくなるため、ここはガイドラインや標準化などで制限をかけましょう)

 

ここではゲートウェイの一例ですが、他にも1つのvNET内にデプロイできる個数が決まっているサービスや機能もあるかもしれません。「今」よりも「今後」の起きうる予測を考えるとvNET単位でスケールできるように当初から設計しておいたほうが無難であることは間違いないでしょう。

 

●有事の際のオペレーション

例えばSpoke-vNETにある特定のSubnet内のVMがウィルス感染やスパイウェアが埋め込まれてしまった、ということが判明した場合を想像しましょう。まず最初にやるべきことはなんでしょうか?

 

犯人捜し?ウィルススキャンのソフトを導入する?

違いますよね。いま以上に被害が拡大しないように問題のあるネットワーク経路を特定し、入り口を塞ぎ、かつ問題のネットワークを孤立させることが何より優先されるべきでしょう。Subnetレベルでネットワーク分離を行っていた場合を想像すると、おそらくNSGによるFW制御で許可していたルールを拒否にする、とか、NSG Flow Logsのパケットログを解析する、などがあげられると思います。既に大量に定義されているNSGルールから特定のルールのみを拒否させるといったオペレーションは間違いも起きやすく判断も見誤る可能性もあります。仮にNSGの設定を入れていたとしても同一vNET内にNAT Gatewayが入っていたりPublic IPを持つVMなどが混在していると手を下す範囲も広がり、しっかりと管理されていた場合であっても作業範囲は広がります。

 

一方Hub&Spoke構成はどうでしょうか。問題となるネットワーク経路を特定する作業は同じかもしれませんが、分離においてはシンプルです。Hub-vNETとピアリングを行っている問題となるSpoke-vNETとのピアリング設定を外せば終わります。つまりSpoke-vNETがデフォルトルートとしているHub-vNET側へのルーティングが断絶されるため、Spoke-vNET内からのすべての通信において行き場がない状態にできます。NSGや他リソースの経路調査など面倒な作業は初動で必要とせず、まずはネットワークを分離させることが最優先でできます。また、復活させるときもAzure FirewallのコレクションルールやNVAのルールセットをしっかり見直して必要最低限のログイン経路だけを開ける、など、分離されている状態だからこそしっかりと調査・検討した上でFW制御を改修させてトラブルシュートに挑める、といったメリットもここにはあります。

Spoke-vNETとのすべての通信はAzure FirewallやNVAなどHub-vNETに配置されているリソースでFW制御やルーティングが一元的に管理できている状態のため、統制されたシステムの中で限定的な作業を行うだけでやりたいことができるメリットがここにはあります。

 

今回の記事は以上となりますが、他にもvNET Hub&Spokeだからこそメリットがあることはいくつかあると思います。「いままで1vNETで詰め込んできたやり方に慣れているから」、「これまでの実績から対応範囲も想起しやすいから」、という考え方もわかりますが、分離することでこれまで見えなかったメリットや管理工数の削減、統制のシンプルさを恩恵として受けるやり方の1つとして参考になればと思います。