この記事は [Microsoft Azure Tech Advent Calendar 2019(https://qiita.com/advent-calendar/2019/microsoft-azure-tech) の16日目の記事です。今回はよくご質問を頂いた1つであるApp Services と SNATについて記載します。
#####よくあるご質問
App ServicesからSQL Database や他のサービスへの接続がタイムアウトした、もしくはパフォーマンスが低下する問題が発生した。アプリケーション側は何も変更していないのになぜこうした事象が発生するのか。
原因
SNATポートの枯渇を引き起こし、外部への通信ができないため。
#####SNATとその動作
App Servicesのアプリケーションは1つ以上のApp Serviceワーカー インスタンスによってホストされています。このワーカーインスタンスに対して、インターネットIPアドレスは割り当てられておらず、外部IPアドレスに接続するためには、スタンプ (App Service を構成する各ロールインスタンスをホストする、ゲストOS の集合体) のロードバランサーを利用してネット ワークアドレス変換(SNAT)を実行する必要があります。
以下のようなイメージです。
App Service のWorker Instance <-> Load Balancer <-> Internet、外部サービス
Azure の Outbound connections
https://docs.microsoft.com/ja-jp/azure/load-balancer/load-balancer-outbound-connections
App Service から外部への接続に関して、同じ宛先に対して複数の通信が発生する場合、それぞれの通信にてSNATポートが使用されます。
もし、複数の通信が発生した場合でもそれぞれ異なる宛先となる場合には1つのSNATポートが共有されます。
SNATポートは各スタンプごとに65536個と制限があり、他のお客様と共有されています。
現在の仕様では、SNATポートは各インスタンスごとに128個まで確保され、その後、必要に応じてベストエフォートにてSNATを確保しようとします。
しかしながら、確保できない状況となった場合、外部への接続が失敗する状況となります。
#####対処
一時的にでも問題の解消が必要な場合には、以下の対処策が有効になることが考えられます。
・スケールアウト(インスタンスごとのSNATポートが確保できるから)
・ASEを利用する(専有環境であり、他のお客様の影響を受けることなくSNATポートを確保できるから)
もし継続して発生する場合には、コネクションプールを用いてSNATポートの利用数を再現する、HttpClientオブジェクトを再利用するようにアプリケーション側の変更が必要です。
なお、現時点にてSNAT数を確認できるメトリック情報は公開されていません。
ただし、該当App Service の「問題の診断と解決」から 「TCP Connections」を確認することで、各インスタンスごとのOutbound Connections数が確認可能です。こちらを基におおよその状況は確認できるため、もし外部サービスへの接続失敗など発生した場合には、確認してみて下さい。
参考URL
以下の記事にてより詳細な動作が記載されています。参考させていただいたので、ご紹介させて下さい。
HttpClientをusingで囲わないでください
https://qiita.com/superriver/items/91781bca04a76aec7dc0
SNAT with App Service
https://4lowtherabbit.github.io/blogs/2019/10/SNAT/