Azure VM のストレージ パフォーマンスに関する留意点と対処策

### 注釈ここから ###

本投稿は、Microsoft の TechNet Blog のリタイアに伴って、バックアップ目的で個人ブログに再投稿したものです。
リンク切れや内容にも多少の修正を加えていますが、情報が古い可能性があります。
(元記事)
https://blogs.technet.microsoft.com/jpaztech/2016/03/15/azure-vm-storage-performance/
(公式のバックアップ一覧)
Japan Azure IaaS Support Team Blog のバックナンバー #1
Japan Azure IaaS Support Team Blog のバックナンバー #2

### 注釈ここまで ###


(2016/07/28 “[補足] ストレージに発行された IO 要求数などの確認方法” 項を追記)

Azure サポートの宇田です。今回は Azure 上の仮想マシンにおけるストレージのパフォーマンスについて、よくあるお問い合わせいただく内容や、設計の際にご留意頂きたい点をご紹介したいと思います。例えば、SQL Server などのデータベースや、SharePoint の大規模環境などを構成する場合、以下のような状況に直面した or している方は少なくないのではないでしょうか。

  • Azure VM でディスクが遅い
  • Premium Storage を使っているにもかかわらずディスク性能が出ない

1. そもそもディスクの性能とは


ディスクの性能を測定するうえでは、”スループット” と “IOPS” の二つの指標を正しく把握することが重要です。スループットとは、転送速度 (30 MB/s など) のことで、ファイルのコピーをした際に目にしていると思います。一方の IOPS (I/O per sec) は、1 秒あたりの I/O 要求の数を示し、ベンチマーク ツール等ではスループットとあわせて IOPS の測定も行うものが多くあります。

実際にデータを読み書きする際には、大別すると “4 KB などの小さなファイルを多数読み書きする場合” と、”数 MB や数 GB などの大きなファイルを少数読み書きする場合” の二つに分けられます。前者の様に小さなファイルに多数のアクセスを行う場合、1 秒あたりに多くの I/O 要求を処理することができますので、一般的に IOPS の値は高くなります。ただし、多数のファイルを読み書きできたとしても、個々のファイルが小さいことから、スループットは伸び悩む形になるでしょう。逆に後者のように大きなファイルにアクセスする場合には、IOPS は伸び悩みますが、実際の転送速度 (スループット) は高くなる傾向となるかと思います。

(イメージ図: ファイル サイズとスループット、IOPS の傾向)

こうしたディスクの詳しい仕組みについては、弊社社員の以下ブログが詳しく説明しています。是非あわせてご覧いただければと思います。

IOPS の数値は高いのにスループットが低いんですけど?
http://blog.ryukiy.net/2015/06/12/premium-storage-part2/

2. Azure ストレージの概要


Azure ストレージについて具体的なイメージがついていない方もいるかもしれませんが、端的にいうとデータは仮想マシンが配置されるサーバーとは独立したストレージ サーバー上に保管されます。このため、仮想マシン (ないしホストする物理サーバー) から見るとネットワーク越しでアクセスする形となるため、オンプレミスの物理サーバーやクライアント PC と比較すると応答速度や性能面がどうしても劣りがちになります。

Azure のデータセンター内には膨大な数の物理サーバーが稼働していますので、そのうちのどのサーバーからでもストレージ上のデータにアクセスできるようにするというクラウドのアーキテクチャ上、単純に物理サーバー上にデータを置いておけばいいという訳ではないため、その点はご理解をいただきたいと思います。逆に言えば、仮想マシンをホストする物理サーバーと、ストレージが分かれていることによって、仮想マシンのサイズ変更や VHD からの再作成ができるという点がメリットとしてはあげられるかと思います。

(イメージ図: Azure ではストレージと Hyper-V ホストは独立しています)

3. Azure ストレージの制限事項


Azure ストレージには Blob (Binary large object) / Queue / Table / Files の 4 種類のストレージ機能が用意されています。このうち、仮想マシンが利用するのは Page Blob ですが、Blob とストレージ アカウントのそれぞれに IOPS 等の制限があることをご存知でしょうか。

パブリック クラウドである Microsoft Azure では、ストレージに限らず各種リソースは世界中のお客様で共有しています。このため、特定のお客様環境における過負荷が、他のお客様環境に影響しない様、ストレージ アカウントや個々の Blob (ファイル) ごとに制約が設けられています。詳細な制限事項については以下のドキュメントに記載がありますが、要約すると後述のような制限が設けられています。

Azure サブスクリプションとサービスの制限、クォータ、制約
https://azure.microsoft.com/ja-jp/documentation/articles/azure-subscription-service-limits/

Azure Storage のスケーラビリティおよびパフォーマンスのターゲット
https://azure.microsoft.com/ja-jp/documentation/articles/storage-scalability-targets/

Standard ストレージの場合

  • ストレージ アカウントあたり 20000 IOPS
  • VHD ファイルあたり 500 IOPS もしくは 60 MB/s (Basic VM の場合は 300 IOPS)

Premium ストレージの場合

  • ストレージ アカウントあたり 50 Gbps 以下
  • P10 (128 GB) のディスク: 500 IOPS もしくは 100 MB/s
  • P20 (512 GB) のディスク: 2300 IOPS もしくは 150 MB/s
  • P30 (1 TB) のディスク: 5000 IOPS もしくは 200 MB/s

2019/03/13 追記: 現在は 4 TB, 7500 IOPS, 250 MB/s の P50 や、さらに上位の SKU もプレビュー提供が行われています。

こうした制約があるため、Standard ストレージで 1 つのストレージ アカウントに VHD ファイルが 40 本以上存在する環境の場合には、十分に注意が必要です。全てのディスクが MAX の 500 IOPS を必要とする場面は多くないとは思いますが、1 ストレージあたり 40 本を超えている場合には、ある仮想マシンのディスクの高負荷が他の仮想マシンのディスク アクセスを制限する可能性がある点、お気を付けいただければと思います。

また、Premium ストレージの場合には、上記に加えて仮想マシンのサイズに応じた制約も設けられています。詳細は下記ページの DS / GS シリーズの欄をご覧頂ければと思いますが、例えば DS1 の VM では、せっかく Premium Storage を使っても 3200 IOPS もしくは 32 MB/s が上限です。これは、仮想マシンをホストする物理サーバーの帯域を複数の仮想マシンで共有している為です。例えば 16 コアの物理サーバー上では DS1 (1 コア) の仮想マシンは 16 台まで動作できてしまいますので、16 台で帯域を奪い合わないよう、コア数に応じて制限をかけているといった具合です。

仮想マシンのサイズ
https://azure.microsoft.com/ja-jp/documentation/articles/virtual-machines-size-specs/

(イメージ図: 1 台の物理サーバーを共有するため、1 台あたりの帯域は限られる)

4. ディスク性能が出ない場合に何ができるか


Azure ストレージや仮想マシンのサイズに応じた留意点をご紹介してきましたが、1つのディスク性能がアプリケーションやサイジングで期待する性能を満たせない場合には、どのようにすればよいでしょう。限られた制約の中でパフォーマンスを上げるのであれば、ディスクのスケールアウトによる解決策として、RAID-0 構成 (ストライピング) を実施し、マルチスレッドによる処理の並列化、アプリケーション側のアルゴリズムの再考等を導入すればある程度の改善は見込めます。しかし、この環境で検証をしても要件を満たせない場合には、ディスク自体をスケールアップして、Premium ストレージというより高速なストレージを使う必要があります。

また、OS に実装済みのコマンドによるファイル操作や、パッケージ製品などでアプリケーションの改修によるチューニングが行えない場合ついては、多くの場合 Azure ストレージの設定やチューニングで高速化を行う事は困難です。これは OS のコマンドであれば書き込み・読み込みなどが既定で最適化されているためで、さらなる改善のための現実的な対処策としては、Premium ストレージなどより高速なストレージをお使いいただくのが得策です。それでも性能不足となる場合には 、さらに RAID-0 構成 (ストライピング) を組み合わせるのがよいかと思います。

上記のほか、Azure ストレージにおける唯一の設定ポイントとしてホスト キャッシュがありますが、これを有効化すればキャッシュが効くため高速化する一方、予期せぬ障害の際にはデータが消失するリスクがあります。キャッシュのデータは揮発性ですので、万が一の際にキャッシュからディスクに書き戻されていないデータは消失する可能性があります。このため、頻繁に書き込み処理が発生し、整合性が取れなくなると困るファイル (例えばデータベース等) については、書き込みのホスト キャッシュを設定してはいけません。

まとめ


以上でご説明した一連の流れをまとめると、ディスク性能が出ない場合には以下のような点を事前に確認ください。

  1. スループットと IOPS のどちらの性能がどの程度必要なのかを明確化
  2. ストレージ アカウントや、仮想マシンのサイズに伴う制限を確認
  3. より高速なディスクへの変更や、RAID-0 構成にして対処
  4. 期待する性能になったかを再検証

そして、より具体的な対処策としては、以下のような順で構成変更を頂ければと思います。

  1. Standard ストレージを使用している場合には、Premium ストレージへ移行
  2. Premium ストレージの場合には、ディスク サイズを拡張して、P20 や P30 へ変更
  3. P30 の Premium ストレージでも性能不足な場合には、P30 で RAID-0 を構成

2019/03/13 追記: 現在は 4 TB, 7500 IOPS, 250 MB/s の P50 や、さらに上位の SKU もプレビュー提供が行われています。

[参考リンク]
Microsoft Azure Storage のパフォーマンスとスケーラビリティに対するチェック リスト
https://azure.microsoft.com/ja-jp/documentation/articles/storage-performance-checklist/

Azure Premium Storage: 高パフォーマンスのための設計
https://azure.microsoft.com/ja-jp/documentation/articles/storage-premium-storage-performance/

Azure Virtual Machines における SQL Server のパフォーマンスに関するベスト プラクティス
– I/O パフォーマンスに関する考慮事項
https://azure.microsoft.com/ja-jp/documentation/articles/virtual-machines-sql-server-performance-best-practices/#io

Azure Premium Storage への移行
https://azure.microsoft.com/ja-jp/documentation/articles/storage-migration-to-premium-storage/

[補足] ストレージに発行された IO 要求数などの確認方法


制限を超えた IO 要求が発生していたかどうかについては、OS のパフォーマンス ログを採取することで、推測することができます。Windows OS の場合は、以下のパフォーマンス カウンターによって IOPS を確認することができます 。

  • Disk Reads/sec
  • Disk Writes/sec
  • Disk Transfers/sec

「Disk Transfers/sec」が Reads と Writes の合計ですので、まずはこちらをご覧いただき、上記 3. 項のに記載しました、環境に応じた IOPS の制限に抵触しているかを判断いただければと思います。

ただし注意点として、ホスト キャッシュが有効な場合は、OS から見ると制限値を超えた性能が出る場合もございますので、カウンターの合計値からだけでは、本当に制限値を超えていたかを判断することはできません。その場合は、IO 要求を完了するまでの合計時間を示す、以下のカウンターを確認します。

  • Average Disk sec/Read
  • Average disk sec/Write

制限を超えた IO 要求が発生すると、スロットリングが発生して IO 要求が待ち状態になり、ストレージから応答が返るまでの時間が増幅します。上記のカウンターを確認し、IO 要求の完了までにかかる時間が大きくなっていた場合は、制限を超えた IO 要求が待ち状態になっていたのではないか、ということが推測できます。

– 参考資料
アプリケーションのパフォーマンス要件を評価するためのカウンター
https://azure.microsoft.com/ja-jp/documentation/articles/storage-premium-storage-performance/#-4

本情報の内容(添付文書、リンク先などを含む)は、作成日時点でのものであり、予告なく変更される場合があります。

Windows Server 2003 を Azure に移行する際の手順と制限事項

オンプレで いまだに Windows Server 2003 を使っているセキュリティ意識のかけらもない人たちが、そろそろ重い腰を上げてクラウドに移行しようと思っているんじゃないかと思って、気を利かせてブログを書いてみます(皮肉

仮想化 (P2V) だけでは飽き足らず、クラウドにまで負の遺産を引き継ごうという人はいないと信じていますし、このブログが役に立たないことを切に願っています。(頼むからおとなしく Windows Server 2016 / 2019 を使ってくれ…)

ご注意

  • 仮に何らかのアンチウイルス製品でセキュリティ対策を行っていたとしても、Windows Server 2003 はカーネルの設計自体が古いので、極めて脆弱なことを自覚しましょう。
  • クラウドは Internet 経由でアクセスすることを前提としていますが、言わずもがな脆弱な Windows Server 2003 を Internet に晒すことは絶対に避けるべきです。(以前の投稿でも書きましたが、Azure の IP レンジは公開されているので、ポートスキャンや大量のログイン試行が行われます。)
  • つまり、VPN や ExpressRoute などの閉域接続 Only で使いましょう。
  • 加えて、Azure から Internet 宛の通信も可能な限りブロックしましょう。(むしろ、Windows Server 2003 をネットワークに繋いでくれるな。クラウドに持ち込んでくれるな。というお気持ち。)
  • Azure に移行したからといって、レガシーなシステムを塩漬けしていいわけでは決してありません。早く根本的な対応を考えましょう。
  • Windows Server 2003 は Azure 上でも動くことは動きますが、非常に制限が多いので、悪いことは言いませんから Windows Server 2016, 2019 に移行しましょう。

前提環境

  • Hyper-V 上で稼働する第 1 世代の仮想マシン (つまり not UEFI の BIOS 環境)
  • Windows Server 2003 R2 Enterprise SP2 x86
  • VHD ファイル
  • Windows Update や各種パッチを最新版まで適用 (修正が出ているのに適用していないとか論外です)

移行手順

とりあえず、移行元ということで素の Windows Server 2003 R2 SP2 をインストールしてみます。この画面を見るのも何年ぶりか…(リリースされた当時、私は中学生ですね。

Windows Update を最新まで適用します。(これまた懐かしい…。)

必ず RDP を有効化して、Firewall にも穴をあけておきます。(忘れると接続できません)

ユーザー名とパスワードを強固なものにしておきましょう。Administrator 残ってるとか論外です。パスワードに関しては、Azure の推奨は 12 文字以上。推測しやすいユーザー、パスワードを使っていて乗っ取られても知りませんよ。

Hyper-V 統合サービスも忘れずにインストールしておきましょう。(ドライバーとか、ホストとゲストの連携用のモジュールとかです)

Azure 上での利用がサポートされない役割・機能を使っていないかを確認しましょう。(日本語版は古い可能性があるので、なるべく英語版を見ましょう。)

その他、Windows Server 2003 に限った話ではないですが、Azure に移行する際の注意事項、制限事項は以下のドキュメントに詳しく記載があります。各モジュールの推奨バージョン / 推奨 KB まで明記されているので、非常に親切ですね。必ず 3 回は熟読し、漏れがないことを確認しましょう。(PowerShell でコマンドが書かれている時点で、Windows Server 2003 はアウトオブ眼中なのが分かりますね?)

OS 内の設定が終わったら、Hyper-V 上の VM を一度シャットダウンしてから、ディスクを容量固定の VHD (VHDX は不可) に変換します。ファイル サイズが 1 MB (1,048,576 Byte) の倍数でないと Azure 上でエラーになったりするので、VMware 等の non Hyper-V 環境からディスクを変換してきた場合は気を付けましょう。

Azure Storage を作成して、アカウント名とアクセス キーをメモっておきましょう。

AzCopy 等を使って、Page BLOB として VHD をアップロードします。(BlobType の指定を忘れるとアップロードしなおしなので要注意。) 最新の AzCopy は .NET Core 2.1 でビルドされているらしいので、適当にランタイムも入れてあげましょう。(.NET Core 2.1 の Supported OS が Windows Server 2008 R2 以降なので、2008 以前だとダメな気がします。あと 0x80070057 とかエラーが出た場合は、KB2533623 を適用してあげればよいかと。)

(コマンド例)
AzCopy.exe /Source:”VHD があるフォルダ (ファイル名含まず)” /Dest:”Azure Storage のコンテナーの URL” /DestKey:”Azure Storage のアクセス キー” /Pattern:”VHD のファイル名” /BlobType:Page

アップロードが完了したら、[すべてのサービス] – [ディスク] – [追加] から Managed Disks を作ります。ソースを “ストレージ BLOB” として、先ほどアップロードした Azure Storage 内の VHD を選択し、OS ディスクなら “Windows” を、データ ディスクなら “なし” を選択し、サイズを忘れずに実サイズにしておきましょう。(大きいサイズにすると VHD が拡張されてしまって、あとで縮小できなくなります。)

Managed Disks が出来上がったら、[VM の作成] から Azure VM を作成しましょう。

受信ポートは忘れずに “なし” にしておきましょう。

パブリック IP も付与しないように。NSG は “Basic” で、受信ポートは先ほどと同じく “なし” にしておきましょう。(もし血迷ったとしても、Windows Server 2003 を Internet に公開しようと思わないこと。あえてセキュリティ インシデントを起こしたいなら別ですが。)

その他は適宜ウィザードに沿って選択して、Azure VM をデプロイしましょう。

で、出来上がったものがこちら。Public IP を付与していないので、Private IP 経由でないとアクセスできません。VPN や ExpressRoute の接続はドキュメントを見ながら別途構築しましょう。

ちゃんと RDP できますね。(2003 だからネットワーク レベル認証じゃないけど…

ハードウェアが変わったので、ライセンス認証をしろと言われますね。まだ NSG で出力方向の通信を制限していないので、ネットワーク経由で認証だけ済ませてしまいましょう。(ライセンス周りは詳しくないので、ちゃんと自己責任で調べてほしいんですが、ちゃんとクラウドに持ち込んでいいランセンス形態でやってくださいね。ライセンス モビリティの権利がないものでやるとアウトだと思います。詳細はライセンス購入元の販社に問い合わせましょう。)

ということで、Azure VM として Windows Server 2003 を構築することができました。(まだ終わりじゃないよ)

移行後に忘れずにやるべきこと

まず、最低限やるべきは以下ですかね。

  • パフォーマンス テスト (移行前後の環境で CPU やディスクの負荷テストを必ず実施して、きちんと性能劣化が生じない VM サイズ・ディスクにサイジングしましょう。)
  • アプリケーションの動作確認 (言わずもがなですが、CPU の命令セットの差異とか、MAC アドレスでライセンス認証しているようなアプリで認証が飛ぶとか、ブロードキャスト パケット等に対応していない Azure VNET の仕様とバッティングしないかとか…。VM が動くのとアプリが正常稼働できるかは全く別物ですし、Microsoft はあくまでも仮想化基盤の提供だけなので、ウワモノは構築するユーザーの責任です。)
  • 可用性の確保 (Azure VM はメンテナンスや HW 障害によってダウンすることがあります。V2C しただけでは事故りますので、必ず 2 台以上で冗長化する構成にするか、1 台だとメンテや障害の影響でダウンしうることをユーザーに事前に説明しましょう。クラウドにはクラウドのお作法がありますし、それを説明するのも V2C する人の責任です。SLA の要件を満たさずにサポートにクレーム入れても当然ですが返金されませんよ。)

加えて、ネットワークの通信制御もちゃんと対応しておきましょう。[ネットワーク] の設定画面から、以下のような形で必要最低限の IP / Port との通信だけを許可します。

  • 受信 方向の通信は、RDP やサービス用の必要最低限のポートだけ許可
  • 基盤側との連携用に Azure LoadBalancer からの受信を許可 (168.63.129.16 の全ポート開けておきましょう。)
  • 送信方向の通信も、仮に乗っ取られた場合に被害が拡大しないように必要なポート以外は拒否 (NSG は IP 制限しかできないので、URL フィルターが必要な場合は自前の Proxy でやるか、Azure Firewall を別途デプロイしましょう。)
  • その他すべての通信を拒否 (既定の 65000 番台のルールは打ち消しておきましょう。)

その他、運用上の制限事項・注意事項

  • VM Agent がインストールできません (Azure VM は VM Agent をインストールすることで基盤側との連携を実現していますが、x64 しか用意されておらず、仮に 64 bit OS だったとしても Windows Server 2003 では動かないはずです。)
  • 拡張機能が使えません (Azure Backup をはじめとする拡張機能も VM Agent が必要なため動きません。)
  • 動作やパフォーマンスに問題が出たとしても、サポートされません。(延長サポート フェーズすら終了した OS なので当たり前ですね。)
  • 繰り返しですが、Windows Server 2003 は極めて脆弱です。セキュリティには最大限の注意を払いましょう。IaaS として Azure VM を使う場合、OS やアプリケーションの運用・管理はユーザー責任です。(Internet からアクセスできる状況下で Administrator とか、SQL Server の sa みたいな脆弱なユーザー名、パスワードを使っていれば数日で乗っ取られますし、オンプレミスと VPN 等で接続していれば、逆流されて社内まで浸食される恐れもあります。)

公式の KB もあったので、追記しておきます。(こちらも英語版を推奨)

ということで、「Azure 上でも Windows Server 2003 は動く」ものの、「動かしていいわけではない」ですし、「推奨されているわけではない」ということを肝に銘じておきましょう。「Windows Server 2003 を Azure へ移行して、このまま塩漬けしよう」なんてユーザーさんから言われた際に、「そろそろ塩漬けはやめませんか?」と勇気を持って一声かけて欲しいなーと思ったりするサポートの中の人でした。

Azure との VPN 接続がうまくいかない場合のデバッグ方法

いつの間にか Azure VPN Gateway の診断ログが取れるようになってました。
これがあればユーザー側でのデバッグが大分やりやすくなるので、周知の意味も込めてメモ程度に残しておきます。

診断ログの設定方法

まず、診断ログは [診断設定] のブレードから、個別に有効化します。

適当な名前とストレージ等の出力先を指定し、有効化したいログの種類にチェックします。VPN 接続時のネゴシエーション周りは IKEDiagnosticLogs だけで十分なはず。(他のログについても順次確認中)

しばらく待つと指定したストレージに insights-logs-ikediagnosticlog という名前でコンテナが作成され、その中を掘っていくと毎時 PT1H.json というファイルが吐き出されていることが確認できます。

ログ解析のポイント

PT1H.json を開いてみると、ログは JSON Lines (各行が JSON 形式) のフォーマットで出力されていることがわかります。適当に JSON が見やすいエディタを使いましょう。

ここからは Azure 固有の話ではなく IPsec VPN のネゴシエーション周りの一般的なお話ですが、接続を確立しようとする際は、SA INIT の通信が行われます。
(SA: Security Association, INIT : Initialize のことです)

Azure とオンプレ側の VPN デバイスのどちらから接続を始めても問題ありませんが、先に接続要求を送ったほうを Initiator、接続要求を受け取ったほうを Responder と呼びます。で、SA INIT のフェーズでは Initiator 側が initiator cookie (iCookie) だけセットした状態で、responder cookie (rCookie) が空 (0x0) のパケットを送付してネゴシエーションを始めます。(受け取った Responder 側が rCookie をセットして返します)

なので、ログの中で “iCookie : 0x0” とか “rCookie : 0x0” の行を探しましょう。(闇雲にログを見るのではなく、SA INIT を始めた行から見ていくことをオススメします。)

以下の例では、Azure 側としては [RECV Network Packet] ということで、パケットを受け取ったと書かれているので、オンプレミス側 (FortiGate) が Initiator で、Azure VPN Gateway は Responder 担っていることがわかります。(図では、549-552 行目が受け取った SA INIT のデバッグ ログで、それに対しての応答が 553-555 行目になっています。)

あ、毎度のことながら IP アドレスは FortiGate 側を ff.ff.ff.ff、Azure 側を aa.aa.aa.aa でマスクしてますのでご容赦を。

この例では、iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd となっていますが、同じタイミングの VPN デバイスのログをみても同一の Cookie でログが見つかるはずです。(以下はあくまでも FortiGate のデバッグ ログの例なので、機種によって出力されるログは異なります。FortiGate の場合は 16 進数を意味する 0x なしでログが出るみたいなので、 1df26d566a7f45fa とかで検索しています。)

ということで、あとは何の処理で失敗しているのかをゴリゴリ見ていきましょう。(確認ポイントは状況によって違うのと、そもそも VPN の接続時のフローとかを把握していないとダメなので、 細かい話は Cisco のドキュメントとか見て頑張ってください。 )

正常時のログサンプル (抜粋)

{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"[RECV Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x0 ; Exchange type : IKEv2 SA Init Mode ; Length : 396 ; NextPayload : SA ; Flags : 0x8(INITIATOR,REQUEST) ; Messid : 0x00000000","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received SA INIT","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received Ike payload: Policy1:AES-CBC-256 SHA1 SHA1 DhGroup2 Policy2:3DES SHA1 SHA1 DhGroup2 Policy3:AES-CBC-256 SHA256 SHA256 DhGroup2 ","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Receiving MM Packet for tunnel Id 0x0 iCookie 0x1DF26D566A7F45FA and rCookie 0x29D6549E71D8FADD: Receiving MM Nonce","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending IKE SA_INIT response packet with tunnelId 0x0, iCookie 0x1DF26D566A7F45FA and rCookie 0x29D6549E71D8FADD","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending Ike payload for tunnel Id 0x0: Auth:PreShared Key- Responder Policy:AES-CBC-256 SHA1 DhGroup2 ","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"[SEND Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 SA Init Mode ; Length : 364 ; NextPayload : SA ; Flags : 0x20(RESPONDER,RESPONSE) ; Messid : 0x00000000","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"[RECV Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Auth Mode ; Length : 284 ; NextPayload : ENCR ; Flags : 0x8(INITIATOR,REQUEST) ; Messid : 0x00000001","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received IKE AUTH message","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received Traffic Selector payload - Number of TSIs 1: StartAddress 0.0.0.0 EndAddress 255.255.255.255 PortStart 0 PortEnd 65535 Protocol 0 Number of TSRs 1:StartAddress 0.0.0.0 EndAddress 255.255.255.255 PortStart 0 PortEnd 65535 Protocol 0","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Proposed Traffic Selector payload will be - Number of TSIs 1: StartAddress 0.0.0.0 EndAddress 255.255.255.255 PortStart 0 PortEnd 65535 Protocol 0 Number of TSRs 1:StartAddress 0.0.0.0 EndAddress 255.255.255.255 PortStart 0 PortEnd 65535 Protocol 0","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received IPSec payload: Policy1:AES-CBC-256 SHA1 Policy2:3DES SHA1 Policy3:AES-CBC-256 SHA256 ","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending SA AUTH response message for tunnelId 0x5 and tsId 0x13","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending IPSec policy Payload for tunnel Id 0x5, tsId 0x13: Policy1:AES-CBC-256 SHA1 ","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: IKE Tunnel created for tunnelId 0x5","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"[SEND Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Auth Mode ; Length : 204 ; NextPayload : ENCR ; Flags : 0x20(RESPONDER,RESPONSE) ; Messid : 0x00000001","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: IKE Tunnel closed for tunnelId 0x3 with status Deleted via RPC call","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending IPSEC SA delete for tunnelId 0x3 and tsId 0x12","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:08.4569360Z", "level": "Informational", "properties": {"message":"[SEND Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Informational Mode ; Length : 76 ; NextPayload : ENCR ; Flags : 0x0(RESPONDER,REQUEST) ; Messid : 0x00000000","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:08.4575869Z", "level": "Informational", "properties": {"message":"[RECV Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Informational Mode ; Length : 76 ; NextPayload : ENCR ; Flags : 0x28(INITIATOR,RESPONSE) ; Messid : 0x00000000","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:10.4754992Z", "level": "Informational", "properties": {"message":"[SEND Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Informational Mode ; Length : 76 ; NextPayload : ENCR ; Flags : 0x0(RESPONDER,REQUEST) ; Messid : 0x00000001","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:10.4754992Z", "level": "Informational", "properties": {"message":"[RECV Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Informational Mode ; Length : 76 ; NextPayload : ENCR ; Flags : 0x28(INITIATOR,RESPONSE) ; Messid : 0x00000001","instance":"GatewayTenantWorker_IN_0"}}

気が向いたら何パターンかありがちな設定ミス時のログの例でも追記します。

VPN 切断時のチェックポイント

VPN の切断・再接続時のログは、insights-logs-tunneldiagnosticlog コンテナー内に同じく PT1H.json ファイルとして出力されています。中を見ると、status が Disconnected (切断された) もしくは Connected (接続された) ということと、 stateChangeReason として理由が明記されているので、ざっくりとした切断理由が分かります。

以下の例だと DPD timed out で Disconnected になっているので、Azure VPN Gateway からの DPD (Dead Peer Detection) の通信にオンプレミス側の FortiGate が応答を返さなかったので切断されたことが分かります。(これは、当然 FortiGate 自身が無応答だった可能性もありますが、Internet の経路上で問題があった可能性もゼロではありません) オンプレミス側のデバッグログ等とも見比べて、どこで何が起きていたかを調査しましょう。

また、Connected に変わった際は RemotelyTriggered で発生したと書かれています。したがって、FortiGate 側が Initiator となって接続要求を送ってきたので、Azure VPN Gateway としてはそれを受け入れて接続が完了したという事になります。(メンテナンス等で Azure 側から切断、再接続をした際は LocalTriggered とかになるはずです)

ルーティング観点のチェックポイント

VPN で BGP を使っている場合など、トンネルは張れているのにルーティングの問題で通信出来ない場合もあります。そうした際は insights-logs-routediagnosticlog 内の PT1H.json ファイルでルーティング情報を確認しましょう。以下の例では、 VPN の切断・再接続に伴って発生した、経路の消失、BGP の Peer Down、BGP の Peer Up、経路の学習が確認できます。また、一部マスクをしていますが、学習した経路も確認できるので、オンプレミス側から BGP で正しく経路を出せていない場合なども一目で分かるはずです。

その他

Azure との VPN できない場合の VPN デバイス側のトラシューは以下なども併せてどうぞ。

あと、Jazug Night で登壇した際に更に詳しい話をしたので、以下のスライド P.64 – 73 や YouTube の録画 (1:03:36 – 1:18:50) もご確認ください。

[Day5] Azure のネットワークがさっぱり分からん

# Microsoft Azure Tech Advent Calendar 2018 の 5 日目です。

今回は、インフラ野郎が大好きな Azure のネットワークについて整理してみたいと思います。

4 種類の Azure ネットワーク

Azure  のネットワークは、大きく 4 種類に分かれます。

  • Private IP (Azure VNET) のネットワーク: VNET 内に展開される VM 等
  • Public IP (VNET 外) のネットワーク: VNET 外に配置される各種 PaaS や、VM の Public IP 等
  • Azure 基板側のネットワーク: バックボーン ネットワークや、物理サーバー用 (ユーザーからは見えない部分)
  • Azure 外に存在するネットワーク: Azure DNS や Traffic Manager、CDN、FrontDoor 等

ざっくり図にすると、こんな感じになります。

# よくある誤解

たまに Azure Storage や SQL Database 等の PaaS に対して VPN 接続したいという話を聞きますが、VPN 接続出来るのは VNET のみですので、Public IP の世界に接続したい場合には ExpressRoute の Microsoft Peering が必要です。(もしくは、App Service Environment や SQL Database Managed Instance のように VNET 内に専用のインスタンスを建てられる上位プランを使用する必要があります。)

また、Azure のサービスであっても、Azure データセンター外の Public IP からサービスを提供する Azure DNS, Traffic Manager, CDN, FrontDoor 等のサービスについては、VPN でも ExpressRoute 経由でもアクセスすることが出来ません。(これらは Internet 経由のアクセスを前提としたサービスなので、閉域環境で使う事を想定されていません) くわえて、内部的にこれらを使っているもの (例えば Azure Portal とか) に対しても、ExpressRoute 経由で閉域だけで接続するといったことは出来ませんので気をつけましょう。

物理的なネットワーク構成

Microsoft が世界中に保有するバックボーン ネットワークや、Azure データセンター内のネットワーク アーキテクチャについては、多少情報が古いものも混じってますが以下が参考になります。使用しているスイッチやルーターの名称まで記載されているものもあるので、インフラ野郎は隅から隅まで目を通すと興味深いかと思います。

# 以下、上記から拝借。

Microsoft 所有の Global Network の全体像。水色が自社所有、濃い青が借用、点線が計画中のもの。

Azure の各リージョンは Microsoft の Global Network (WAN) に接続され、世界中の Edge から Internet や ExpressRoute で接続されます。

各リージョンには複数のデータセンターがあり、RNG (Regional Network Gateway) で束ねられています。

データセンター内は、Quantum 10 (Q10) のアーキテクチャが採用され、以下の様な機器が使用されているらしいです。

VNET の仕組み

IaaS ユーザーの方からすると、先のような概念的な話よりも、Azure VNET の方が身近かと思います。

が、VNET の仕組みをきちんと理解した上で使っている人は少ないのではないかと思うので改めて。

Azure では、数百万台規模の物理サーバーが世界中に存在しています。VM はリージョン内のどこかの物理サーバー上でホストされますが、同一 VNET 内の VM 間の通信はどのように行われているかを考えるには、Azure 基板側のアンダーレイ ネットワークと、VNET 側のオーバーレイ ネットワークを意識する必要があります。

ここでは、以下の図のように 2 台の物理サーバー上に 2 つの VNET (A, B) が存在している場合を考えます。VNET A の 10.0.0.4 -> 10.0.0.5 宛に通信する場合は、物理サーバー上で一度カプセル化されてアンダーレイ ネットワーク上でルーティングされます。

# VNET A と B は論理的に分離されているので、別 VNET に同一の Private IP を持つ VM が乗っていても問題は起きません。

VFP の仕組み

こうした Azure の SDN を支えているのが、Hyper-V の Virtual Switch で動作する VFP (Virtual Filtering Platform) です。

詳しいことは Windows Server 2016 等の HNV 系のドキュメントや、Microsoft Research の論文を読むと理解が深まります。

論文内の画像を抜粋しつつ、かいつまんで説明すると、Hyper-V の仮想スイッチ上でフィルター ドライバーの用に振る舞い、Ingress / Egress のトラフィックに対しての処理を行うのが VFP です。

VFP ではどのような処理が行われるかというと、以下の図のように大きく 4 種類の処理があります。

  • VNET: 前述のアンダーレイ・オーバーレイ ネットワーク間のカプセル化 (encap / decap) を担います。
  • NAT: Public IP で受信したパケットを VNET 内の Private IP に変換したり、LB 経由の通信の NAT を担います。
  • ACLs: Network Security Group (NSG) の機能に該当するものです。
  • Metering: 各種メトリックのデータ取得を担います。課金メーターもこのレイヤーで行っています。

# ちなみに、上図の略称はそれぞれ以下の通り

  • PA: Physical Address (基盤側の IP アドレス)
  • CA: Customer Address (VNET 内の Private IP アドレス)
  • VIP: Virtual IP (Public IP のこと)
  • DIP: Dynamic IP (Private IP のこと)

VNET 内の通信を行う場合

では、もう少し噛み砕いて見てみましょう。(Metering は通信に直接関係しないので省略)

10.0.0.4 の VM からパケットが出て行く際は、10.0.0.4 -> 10.0.0.5 の通信として NIC および Subnet のNSG 送信規則で評価が行われます。その後カプセル化が行われ、送信元の物理サーバーの PA -> 宛先 IP の VM をホストする物理サーバーの PA (192.0.2.1 -> 192.0.2.2) のように Azure 基盤のネットワーク上をルーティングされます。

受信側ではカプセル化を解除するとともに、そのパケットが自身のホストするどの VM / VNET 宛なのかを判断し、Subnet および NIC の NSG で受信規則に基づいて評価を行います。

Azure VM 間で通信をする際、通常ここまで意識はしませんが、実は裏では VFP が頑張ってくれています。

VM の Public IP 宛の通信の場合 (LB 宛もほぼ同等)

続いて、Azure VM の Public IP 宛に通信が来た場合を考えてみます。

Internet 側からパケットが届きますが、VFP は Public IP と Private IP の対応を知っているため、宛先 IP を DNAT して VM に渡します。

反対に、戻りのパケットでは SNAT をして Src IP を Public IP に書き換えてから出ていきます。

なお、NSG の評価は受信方向の通信であれば Public IP や LB の NAT 処理後、送信方向の通信であれば NAT 処理前に行われるので、VM の Private IP のまま評価されます。

# たまに、Public IP 宛に届いた通信を NSG でブロックしようとする人がいますが、そんなことはできません。

UDR を設定した場合の挙動

次に、仮想アプライアンス (NVA) を構築する場合などで、全ての宛先 (0.0.0.0/0) 宛の通信を NVA へ向けるような UDR を設定した場合を考えてみます。

前述の 10.0.0.4 -> 10.0.0.5 宛の通信と似ていますが、送信元の物理サーバー上でカプセル化が行われる際、UDR を向けた NVA がホストされている物理サーバーの PA 宛として Azure 基盤側でルーティングが行われます。

この辺りは SDN 特有で、慣れないと混乱しますが、分からなくなったら落ち着いて図にするのが吉です。

Azure ネットワーク、ムズカシイネ。

その他、Azure のネットワークを理解するうえで参考になる資料

削除できなくなった Azure リソースを頑張って消す方法

Azure を使っていると、たまに設定ミス等でリソースが削除できない状態に陥ることがあります。

そんな時は、ひとまず以下を試してみると消せる場合があるのでご参考までにどうぞ。(必ず消せるとは限りません)

1. Azure PowerShell で正しい値に設定しなおす

誤った設定を流し込んで、リソースの状態が「失敗」や「Provisioning State: Failed」 になっている場合、Azure PowerShell 等で正しい構成情報で上書きすることで解消できることが多々あります。

一度 Azure PowerShell で既存の設定を Get して、誤ったパラメーターを修正したのち、再度 Set してみましょう。

# 誤った設定をして、「失敗」状態になった例

# Azure PowerShell で設定を修正する例 (ExpressRoute の接続リソースの例)

# 既存の設定を取得
$Connection = Get-AzureRmVirtualNetworkGatewayConnection -Name shuda1120 -ResourceGroupName shudaExR

# 誤った設定箇所を修正
$Connection.Peer.Id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/ExR/providers/Microsoft.Network/expressRouteCircuits/MyCircuit"

# 修正後の設定で上書き
Set-AzureRmVirtualNetworkGatewayConnection -VirtualNetworkGatewayConnection $Connection

2. Resource Explorer で正しい値に設定しなおす

Azure PowerShell と同じような話ですが、Resource Explorer (https://resources.azure.com) でも JSON の書き換えが出来たりします。

左のメニューから対象のサブスクリプション内のリソースを辿っていって、対象のリソースの [Edit] から書き換えて [PUT] しましょう。

# Resource Explorer から修正する例

3. JSON テンプレートの完全デプロイを試す

Azure は、JSON テンプレートからリソースをデプロイできますが、増分 (差分) モードと完全モードがあるのをご存知でしょうか。

完全デプロイをすると、対象のリソース グループ内を JSON テンプレートの内容で完全に上書きすることができます。

つまり、既存のリソースは削除されるので、それを利用して無理やり消すという小技が使える場合があります。

(不用意に使うと、他のリソースが消えるので十分注意しましょう)

なお、完全デプロイで消せるリソースについては、以下でまとまっているようです。

4. サポートに依頼する

パッと思いつくのは以上 3 点なので、ダメそうであればサポートに依頼しましょう。

ただし、サポートの中の人もお客様環境を直接操作したりできる権限は基本的に持っていないので (というか、持っていたら色々マズい)

修正が完了するにはエスカレーション等で少なくとも数日はかかります。気長に待ちましょう。