SNATポート枯渇エラーとは
MicrosoftAzureの有償サポートに、「この時間に503エラーが発生してたのですが、Azure側で何か起きてませんでしたか。」などと問合せをすると、「本事象はSNATポート枯渇が原因で発生したと推測されます。」と返事がくることがあります。
今回は、「SNATポート枯渇とは」「対策」について書きます。
SNATポートを意識するのはどういう場面か
"SNATポート枯渇" は、アプリケーション開発をされてる皆さまには、馴染みのないワードだと思います。ですので、まずはAzureプラットフォーム側の目線で、どういうものとして扱われているのかを説明します。
◎ SNATポートが使用されるタイミングと場所 ▽
クライアントからリクエストを受信した際、アプリケーションが処理を行いますよね。このAzureで動作しているアプリケーション処理にて、Azure内のリソース(StorageAccount/SQL Databaseや他の AppService/Functions など)やAzure以外の外部サービスへリクエストを送る場合がございます。その際に、SNATポートが使用されます。
イメージ
ClientPC <-> (Azure)FrontEnd <-> AppService <-【SNATポート使用】-> Azureリソースや外部サービス
アプリケーションにアクセスするユーザが、1人か複数人かどうかは関係ありません。
アクセスされているユーザが少なくても、クライアントからのリクエストが1件だけでも、アプリケーション処理で何かしらの要因で多くのループ処理が行われて、同じ宛先に対して多くの外部アクセス通信が発生した場合は、異なるSNATポートが使用されてSNATポート枯渇の可能性が発生する可能性があります。
そのため、お客様のアプリケーションにアクセスされているユーザ様の人数は、SNATポートの使用状況に直接関係ありません。
◎ Azure 内部の仕組みを説明 ▽
AppServiceは、1 台のインスタンスに対して、SNAT変換を行うために最低で128のSNATポートが保証されており、そこまでのSNATポートは問題なく確保されます。そして、それを超えるSNATポートが必要になった場合には、インスタンスが所属するスケール ユニット (スタンプ) から、余剰なSNATポートが動的に割り当てられます。
この際、1 つのスタンプでは、総計で64,000のSNATポートを確保できますが、スタンプ全体でそれを超えたSNATポートが要求された場合には、SNATポートの枯渇が発生することになるのです。
SNATポートの枯渇について、同一スタンプ内の他ユーザー様でポートの使用量が増加した、といったようなことがあった場合に、スタンプ全体でのポート使用量が増加し、最低保証数以上のポート確保ができなくなる可能性があります。
他ユーザのポート使用状況については、把握することが困難なものとなります。
以下の公式ドキュメントに、トラブルシューティング ガイドが書いてあります。
送信プロキシの Azure Load Balancer > ポートの枯渇
===== 抜粋 ここから =====
ポートの枯渇が発生すると、宛先IPへの新しい送信接続は失敗します。 ポートが使用可能になると、接続は成功します。 この枯渇は、IPアドレスからの64,000個のポートが多数のバックエンド インスタンスにわたってまばらに分散されている場合に発生します。 SNATポートの枯渇を軽減するためのガイダンスについては、トラブルシューティング ガイドのページを参照してください。
===== 抜粋 ここまで =====
SNATポート枯渇の対策
SNATポート枯渇が発生しないように、アプリケーションプログラムを改良、またはAzure上の設定を変更などしていく必要があります。具体的な方法を紹介していきます。
~ SNATポート枯渇の対策 ~ |
---|
アプリケーションのプログラムコードを改良 |
スケールアウトでインスタンス数を増やす |
仮想ネットワーク・Vnet統合を構築する |
ASE(AppServiceEnvironment)を構築 |
アプリケーションのプログラムコードを改良
以下の公式ドキュメントに、App Serviceにおける送受信接続エラーの対策について書かれています。
◎ 参考サイト ▽
Azure App Service での断続的な送信接続エラーのトラブルシューティング > 問題の回避
===== 抜粋 ここから =====
可能な場合は、接続プールを使用するようにコードを改良し、すべての状況を改善します。必ずしも、この状況を軽減するのに十分な時間をかけてコードを変更できるとは限りません。時間内にコードを変更できない場合は、他の対策を利用してください。問題を解決する最善策として、すべての対策を可能な限り組み合わせることをお勧めします。Azureサービスにはサービス エンドポイントとプライベート エンドポイントを、それ以外にはNATGatewayを使用してみてください。
===== 抜粋 ここまで =====
その他にもプログラムコードについて書かれている参考サイトを貼っておきます。
===== 抜粋 ここから =====
こうすることでHttpClientを自分のアプリケーションとSDKで共有できるので、より効率的にSNATを利用できることができます。
まとめ
.NETCore2.1以降であればHttpClientを直接使うより、HttpClientFactoryを利用したほうがよりメリットを享受できると感じました。
===== 抜粋 ここまで =====
スケールアウトでインスタンス数を増やす
◎ なぜスケールアウトで対策するのか説明 ▽
AppService では、1 台のインスタンスに対して、SNAT変換を行うために最低で128のSNATポートが保証されており、そこまでのSNATポートは問題なく確保されます。
そして、それを超えるSNATポートが必要になった場合には、インスタンスが所属するスケール ユニット (スタンプ) から、余剰なSNATポートが動的に割り当てられます。
この際、1 つのスタンプでは、総計で64,000のSNATポートを確保できるが、スタンプ全体でそれを超えたSNATポートが要求された場合には、SNATポートの枯渇が発生することになります。
SNATポートの枯渇について、同一スタンプ内の他ユーザーでポートの使用量が増加した、といったようなことがあった場合に、スタンプ全体でのポート使用量が増加し、最低保証数以上のポート確保ができなくなる可能性もあります。(※他ユーザのポート使用状況については確認することはできない)
◎ 保証されるSNATポート数 ▽
インスタンス数を増加すると、保証される SNATポート数が増えます。
インスタンス台数ごとの保証されるSNATポート数
インスタンス台数 | 保証 SNATポート数 |
---|---|
1台 | 128ポート |
2台 | 256ポート |
3台 | 384ポート |
◎ 注意点 ▽
インスタンス数を増やして、保証されるSNATポート数を増やしたとしても、一時的にそれ以上のSNATポート数が必要になってしまった場合は、またSNATポート枯渇エラーが発生してしまう可能性があります。なので、スケールアウトは手軽にできる一時的な対策ですが、手軽な分SNATポート枯渇が発生してしまう可能性は残りますので、ご理解ください。
仮想ネットワーク (Vnet統合) を構築する
仮想ネットワーク内のリソース同士が通信する場合は、SNATポートは使用されない(パブリックIPで通信されない)ので、SNATポート枯渇が発生する可能性はなくせます。また、外部インターネットに通信する場合も考えると、NATゲートウェイもあわせて構築する必要があります。
◎ 注意点 ▽
SNATポート枯渇が発生する可能性がなくなるのは良いのですが、そもそも仮想ネットワーク・Vnet統合は、本来より高いセキュリティを確保したい場合に構築するものなので、SNATポート枯渇の発生をさせなくするために使用するのは少し違うのではないかと思うので、SNAT の対策のための仮想ネットワーク構築は推奨しません。
ASE(AppServiceEnvironment)を構築する
ASEを使用すると、1台のサーバで使える数万のSNATポートをすべて使えるので、SNATポート枯渇は発生しなくなります。
ただ・・・ASEも本来セキュリティの確保やカスタマイズが柔軟にできるなどの目的で使用するものなので、SNATポート枯渇を発生させなくするために使用するのは推奨しません。1ヶ月の課金額が数十万円跳ね上がりますからね。
参考サイト
Microsoft 公式ドキュメント
SNATポートの枯渇に関する公式ドキュメントを貼っておきます。
送信プロキシの Azure Load Balancer > ポートの枯渇
===== 抜粋 ここから =====
ポートの枯渇が発生すると、宛先IPへの新しい送信接続は失敗します。 ポートが使用可能になると、接続は成功します。 この枯渇は、IPアドレスからの64,000個のポートが多数のバックエンド インスタンスにわたってまばらに分散されている場合に発生します。 SNATポートの枯渇を軽減するためのガイダンスについては、トラブルシューティング ガイドのページを参照してください。
===== 抜粋 ここまで =====
参考になる海外サイト
Microsoft 社員の方の記事
以上です。