【失敗と対策】Azure SQL Managed Instance を ExpressRoute 経由で使用する際の注意点
こんにちは、アバナード関西)篠田です。
今回の記事は、私が以前に遭遇した Azure SQL Managed Instance (以下、SQLMI)の事象についてですが、内容としてはDB寄りではなくかなりインフラ寄りな内容です。
「PaaSでしょ?インフラでそんな悩むことある?」とお思いの方もいるかもしれませんが、そんな方にこそ読んで欲しい内容になっています。
最後までお付き合いいただけますと幸いです。
はじめに:そもそもSQLMIって何だっけ?
SQLMIは、一言で言うと、VMで構築する Microsoft SQL Server と、PaaS の Azure SQL Database の中間に位置するリレーショナルデータベースのサービスです。
PaaSではあるものの、Microsoft SQL Server との互換性が高く、クラウドシフトする際に Azure SQL Database だと機能不足だったりする時は、採用候補に入るサービスになります。
インフラ的にも少し特徴があって、ネイティブにVNetで動作します。
具体的に言うと、プライベートIPアドレスがデフォルトでVNetから払い出されていて、インターネットからアクセスを受けるための「パブリックエンドポイント」がオプション(使用しない構成にもできる)という扱いなんです。
他のPaaSではむしろパブリックエンドポイントがデフォルトで、プライベートエンドポイントがオプション扱いな事が多いですよね。
Webサービスでも、App Service Environment とかがSQLMIと同じ、VNetネイティブ系統としてあったりします。
VNetネイティブの良い点は、VMを使用しているかのように、ルートテーブルとNSGで、外部通信と内部通信の両方のルーティングとアクセス制限を、マニュアルで臨機応変に組めることですかね。
私が担当したSQLMIでは、用途がPowerBIでのデータ分析だったので、オンプレミスの PowerBI Desktop からの通信と、インターネットの PowerBI サービス からの通信の両方を受ける必要があり、上記の柔軟性が役立っていました。
また、SQLMIをデプロイするサブネットは、SQLMIのサービスへサブネットを委任する形になり、ネットワークインテントポリシー(NIP)というルーティングやアクセス許可ルールが、デプロイと合わせて自動設定されます。
それらのルーティングやアクセス許可による通信経路さえ捻じ曲げなければ、VNet内で稼働していても、ノードの維持管理に必要な通信はPaaSとして担保される仕様となっているのも、SQLMIの特徴の1つです。
そう、捻じ曲げなければね…
遭遇した事象:DB使ってないのに ExpressRoute をパケットが流れた
ここでは代表して ExpressRoute と記載していますが、オンプレミスとVNetをプライベートネットワークで定常的に繋ぐ手段としては他にもIP-VPN等があります。
以後、読み替えていただいても構いません。
ともかく、見出しのように、誰もオンプレミスからSQLMIに接続していないし、SQLクエリも実行していないにもかかわらず、ExpressRoute をパケットが流れてたんですよ。
そのデータ転送量が割と大きかったので「いったいどんなクエリ実行したらそうなるんだ?」とまずはSQLMIの監査ログ見ましたが、クエリを実行した形跡はありませんでした。
で、私が首をかしげていると、「どうやらSQLMIからオンプレミスのWeb-PROXYサーバへパケットが流れている」という追加情報が入ってきました。
Web-PROXYと聞いたところで、流れている通信がバックアップや監視等に必要な管理系のWeb通信だろうという事はすぐ当たりがついたのですが、Web-PROXYの設定について、SQLMIの設定メニューやリファレンスを見ても、どこにも情報はありませんでした。
自力調査は早めに諦め、Microsoftサポートに原因を問い合わせたのですが、
MSサポート「SQLMIではインスタンスに対してWeb-PROXYを設定する機能は提供されていません…」
篠田「え???」
というように、サポートに聞いても何でSQLMIがオンプレミスのWeb-PROXYへ通信しているのかの原因は分からずで、当初はどうしようかと非常に悩みました…
起こった事象を簡単に図にすると、以下のような感じです。
先述のように、ネットワークインテントポリシーによって管理系の通信はルーティングされるはずだったのですが、Web-PROXYのIPアドレスはそれらのルーティングではなく、デフォルトルートでオンプレミスにルーティングされる設定になっていたので、通信経路が想定外に捻じ曲がってしまっていました。
原因その1
原因は2つあり、1つは、SQLMIのOSでWPADが既定で有効となっていた事でした。
WPADは、Web Proxy Auto-Discovery の略で、Web-PROXYの設定をクライアントが自動的に探索する仕組みを示します。
Windows11だと、「設定」→「ネットワークとインターネット」→「プロキシ」→「自動プロキシセットアップ」の設定項目にある、「設定を自動的に検出する」をオンにしていると、WPADプロトコルでOSはPROXY設定を自動取得しようとします。
自動プロキシセットアップには他にもセットアップスクリプト (Proxy Auto-Configuration ファイル、通称PAC)のパスをクライアントOSに直接指定する方法があります、こちらも良く法人のPROXY構成で用いられますね。
WindowsのOS設定としての自動プロキシセットアップの良いところは、
PROXYの細かい設定を各クライアントで実施しなくて済む
Webサーバに配置した自動設定ファイルを書き換えるだけで、クライアントのPROXY設定の変更が可能
自動設定ファイルを読み込めない場合はPROXYサーバへ通信しようとせず直接インターネットアクセスをする動作となるため、リモートワーク等でオンプレミスから離れる際に都合が良い場合がある
※PROXY手動構成の場合、個別にURL除外設定をしない限り、例え繋がらない状況でもPROXYサーバへ通信しようとするため、Web閲覧は失敗する
という感じですが、さらに言うと、WindowsOSではデフォルトで「設定を自動的に検出する」がオンに設定されているので、WPADを利用する場合はクライアントPCのPROXY初期セットアップが不要だったりします。
そして、SQLMIを初めとしたAzure SQL のPaaSでは、ユーザには操作・管理が出来ないレイヤーでWindowsOSが使用されていることが知られています。
実際、SSMSでOS確認したら、WindowsServerってちゃんと表示されます。
その関係でSQLMIは、ユーザには触れない部分である、内部ノードのPROXY設定で「設定を自動的に検出する」が既定でオンになっていた、という訳です…
ちなみにこの設定は私が直面した時点で非公開仕様であり、公式ドキュメントには記述がありませんでした、今も探した限りでは無いです。
原因その2
WPADの詳細については上記のMicrosoftのブログを見て頂きたいのですが、WPADでは設定ファイルであるwpad.datが置いてあるWebサーバの自動探索を、
DHCP サーバへ問い合わせ
DNSサーバへ問い合わせ
NetBIOS 名を用いた問い合わせ
の優先度順で実施します。
この中のどれであったかが2つ目の原因に繋がるのですが、まず1. ではない事はすぐに分かりました。
VNetにデプロイされるSQLMIでは、利用する内部ノードへVNetからDHCPでIPアドレスが自動的に払い出されるのですが、そのVNetが内包するDHCPサーバはあまり設定可能項目が無く、WPADに関する設定を入れる余地が無いからです。
続いて、OSのホスト名が「wpad」になっているようなノードは環境内に無かったので、3. も候補から外れました。
という事で消去法から2. のDNSサーバを調査したのですが、本環境では、オンプレミスの内部ドメインとAzure上のプライベートDNSゾーンの名前解決用に、オンプレミスと共用のカスタムDNSサーバがAzure上に構成されており、クライアントPCにWPADでPROXY設定を配布するのに必要な、内部ドメインの「wpad」のAレコードを持っていました。
そして、SQLMIのVNetではその Azure 上のカスタムDNSサーバがDNS設定してありました。
なお、カスタムDNSサーバにオンプレミスの内部ドメインの情報を持たせる構成は、Azureとオンプレミスを ExpressRoute で繋いでいる環境では決して珍しいものではなく、DNSサーバを何台も稼働させなくて済む、自然な構成です。
サービスはSQLMIではないのですが、最近、Azure Machine Learning で Private Endpoint の構成を検討した際、プライベートDNSゾーンの名前解決にVNet上のカスタムDNSサーバが必須である事がわかる、良い図がmsdocsにあるのを見つけたので、ついでに紹介しておきます。
少し話がそれましたが、これで原因が出そろいました。
簡単に図にすると以下のようになります。
対処
この事象、放っておくと本来そこを通る必要の無い通信で、ExpressRoute の帯域が無意味に消費されてしまう事になるので、何かしらの対処をして、ネットワークインテントポリシーのルートテーブルに従い、バックアップや監視等に必要な管理系のWeb通信を、VNetからインターネット(Azureバックボーンネットワーク)へ直接逃がす必要がありました。
MSサポートに依頼して、SQLMIの内部ノードのOSに対し、
WPAD設定の無効化
PROXY構成のキャッシュのクリア
は実施してもらい、通信経路は正常になったのですが、SQLMIの仮想クラスター内のノードは、メンテナンスやスケールアップ/ダウンによって再起動やリイメージが行われると、実施したOSのカスタマイズは元の状態(WPADオン)に戻ってしまいます。
要するに、一時対処は出来ていますが、恒久対処は出来ていない状態です。
恒久対処としては2通りの方法があり、1つはVNetでカスタムDNSを使用する事をやめて、Azureで提供される標準のDNSサーバの利用に切り替えることです。
ただ、SQLMI自体にはカスタムDNSを参照しないといけない理由は無かったのですが、そのVNetにはSQLMIのデプロイされたサブネット以外にも他システムのサブネットがあり、DNS設定を変えることの影響が大きかったので、これは実施出来ませんでした。
VMの仮想NICのように対象リソースだけDNS設定が個別に変更出来れば一番良かったのですが、残念ながらSQLMIのDNS設定はVNetの全体設定からしか変更出来ないんですよね…
実際に実施したもう1つの恒久対処方法は、WPADによって発生するDNSサーバを用いた探索の通信を、SQLMIのいるサブネットのNSGで遮断する方法です。
具体的に言うと、DNS名前解決(53/TCP,UDP)を止めるとSQLMIが正しく動作しなくなることは明白だったので、名前解決後にOSがwpad.datが置いてあるWebサーバ(nslookup wpad で返されるIPアドレス)を、http(80/TCP)で参照しに行く通信をピンポイントで叩くよう、NSGの送信セキュリティ規則に拒否ルールを追加しました。
これならWPADがノードで再度有効化されても、新たにPROXYが自動構成されることは防げます、実際に再発も無かったです。
なお、安易にWeb-PROXYへの通信を直接NSG等で拒否する対処は厳禁です。
本来必要な管理系の通信が遮断され、PROXYに一旦向かおうとした通信はPROXY無しでリトライされたりしないので、SQLMIのバックアップやメトリックの収集が出来なくなります。
まとめ
Microsoft がSQLMIのサブネットに対し設定するネットワークインテントポリシーによって、SQLMIのバックアップや監視等に必要な各種管理用の通信は、送信についてはルートテーブルでネクストホップがインターネットに設定されます。
そのようなルールを既定で強いるのだから、
「SQLMIにはWeb-PROXYなんて設定する余地は無いし、PROXY構成が入り込まないよう、OSのWPADは無効化されているはず」
というように、思い込みが発生しやすい状況にありました。
(もしくはそこまで考えず、盲目的にPaaSに対するクラウドベンダー側の管理を信用してしまう)
この事象は、まさにそんな「PaaSの見えないインフラに潜む落とし穴」だったように思えてなりません。
実際、その落とし穴に全て事前に気付いて対処出来るか、というと、正直難しい部分もあります。
でもそれでも「見えない部分について守備範囲じゃないとバッサリ切り捨てるのではなく、まずは少しでも知ろうとすること」が大事なんじゃないかなと私は感じました。
そこまで突き進まないと解決できない事象だと、クラウドの責任分界点として、ベンダー責か利用者責かがすごく微妙だったりしますが、インフラ担当者が目指すべきは自責にしない事ではなく、システムが正常に安定して稼働することだよなと。
また、VNetに限って言うと、やはりNSGのフローログは収集して、システム導入前や設計変更をした後は、部分的にでも良いのでログを確認すべきだなと思いました。
でないと気付けない通信はあるな、というのもこの事象の教訓だったかと。
この記事が皆さんのお役に立てましたらいいねやフォローをお願いします。
内容に関するご指摘や、その他何かございましたら下記に連絡ください。
アバナード関西オフィス 篠田 諭
satoshi.shinoda(@)avanade.com