二つのトラフィック方向、ひとつのボックス
こんにちは
多くのアーキテクチャー図では、トラフィックが一方の方向に流れていると思われます。クライアントが上に、サーバーが下に、矢印が下に向かっています。現実には、トラフィックが二方向に流れています。
イングレス: 外部クライアントがサービスに到達するパスです。ネットワークの端に位置するリバースプロキシがTLSの終了、リクエストのルーティング、およびアクセスポリシーの強制を担当します。
エグレス: サービスが外部サービスに到達するパスです。支払いプロセッサーのAPIに電話する、ウェブフックのターゲットを取得する、リクエストをパートナーに送信するなど。通常、許可リストを持つフォワードプロキシまたはNATゲートウェイを通じて行われます。
多くのアーキテクチャーは、一つのボックスが両方を処理するものから始まります。それは機能するが、内部サービスが十分に存在するまでに、失敗モードが曖昧であり、分離の懸念事項の重要な教訓を学びます。
このレッスンを終了すると、次のことを理解できます:
- どのようにイングレス&エグレスが、異なるスケーリング軸、および異なる失敗モードを持つ、根本的に異なるトラフィックパターンを表しているか
- Hairpin NAT、およびプロキシが自分自身に接続しようとする理由
- アーキテクチャーフォーク: 一つのボックスが二つに変わり、それぞれが独自に所有するもの
- セキュリティの分離の利点: 各側が実際に許可されたペアにロックダウンできる
- 一つのボックスの設計がスプリットが必要であると判断するための方法
なぜ方向が異なるツールが必要なのか
二つの異なるワークロード、一つのネットワーク境界
イングレストラフィック特性:
- 外部パーティーによって開始されます(インターネット全体)
- ボリュームはユーザーベースに比例します
- TLS終了、リクエストルーティング、ソースごとの制限
- 深い防御の懸念事項:DDoS、アブズ、スクラピング
- パブリックIPは、どの接続も受け入れなければなりません
エグレストラフィック特性:
- 自分のサービスによって開始されます(知られた、少ないクライアントセット)
- ボリュームはサービス間のコールパターンおよび外部API呼び出しパターンに比例します
- ソース-IPの許可リスト設定 (パートナーが一つの固定的なアウトバウンド IP を信頼しています)
- ディフェンス・イン・ディープثの懸念事項: データ漏洩、内部サービスが外部に接続されている場合
- 他のサービスからの接続を拒否するべきです
鍵の不均衡性: 侵入は世界からのトラフィックを受け入れますが、出gress はあらゆるサービスからのトラフィックのみを受け入れます。両者を同じマシンに配置することは、機器が世界から侵入トラフィックを受け入れられる必要がある一方、サービスからのトラフィックだけを受け入れられる必要があるという矛盾を引き起こします。どちらのルールも満たす firewall ルールは、もう一方に反対します。
成長パス: 小さなプロジェクトは、IP が短く、パートナー-IP-allowlist が短いため、1 つの IP と 1 つのツールで両方を隠すことができます。プロジェクトが成長すると、2 つの役割間の摩擦が増加し、ある日、特定の失敗モード (hairpin NAT) がスプリットを強制するまでに至ります。
バグが引き起こすスプリット
サニタイズされたアウトエージェストーリー
実際のプロダクション・フリートで起こるアーキテクチャのフォークを想像してください。以下の名前は変更されていますが、現実の世界でチームが直面する形状は同じです。
組織は、203.0.113.5 に単一のプロキシサーバーを実行しています。このサーバーは、侵入 (ユーザー向けのポート 443) とエグレス (内部サービスがアウトバウンドに接続するためのポート 1080 SOCKS5) を処理します。内部サービスはすべてのアウトバウンドトラフィックを、203.0.113.5:1080 の SOCKS5 プロキシにルーティングします。
同じ 203.0.113.5 にあるサービスの一つは api.example.com です。パブリック DNS は api.example.com を 203.0.113.5 に解決します。
異なる内部サービスが api.example.com を呼び出す必要がある場合、そのアウトバウンドパスは次のとおりです。
1. 内部サービスが api.example.com を解決します → 203.0.113.5
2. 内部サービスが、SOCKS5 エグレスプロキシ 203.0.113.5:1080 にリクエストを送信します。
3. プロキシが自身から 203.0.113.5:443 に接続しようとします。
4. 接続が拒否されました。 パケットは、ほとんどのネットワークスタックが拒否するように、同じ NAT を出入りする必要があります。プロキシは、自身のパブリック IP を介して自身に接続できません。
このはいるピンNAT:パケットがNATを出て、目的地に同じNATに再入する必要があります。ルーティングレイヤに特別なhairpinサポートがないと、パケットは失われる。
なぜ遅くに表面に現れるか
プロジェクトの初期段階では、内部サービスは内部サービス同士がprivateホスト名(internal-api.local)で通信していたり、組織のパブリックサービスに戻ることは一切なかった。hairpinパスは存在しなかった。
新しい機能が必要になったとき、サービスAがapi.example.com(パブリックホスト名)を呼び出す必要がありました。hairpinパスがアクティブになり、接続が拒否され、サーバーダウンになりました。
症状の治療は、リゾルバーがapi.example.comのプライベートIPをパブリックのものに代わりに強制することで行われました。根本的な原因は、単一のボックスが多すぎることでした。
アーキテクチャのフォーク
一つのボックスが二つになる
クリーンな修正方法:プロキシを2つのマシンに分ける。
イングレスサーバー(パブリックIP 203.0.113.5):
- Caddy / リバースプロキシ、ポート80, 443
- 公開DNSレコードがここに指示されている
- api.example.com、app.example.comなどをホスト
エグレスサーバー(異なるパブリックIP 203.0.113.99):
- SOCKS5 / フォワードプロキシ、ポート1080
- ファイアウォールは内部サブネットIPのみに限定される
- 内部サービスはすべてのアウトバウンドがこのアドレスを経由する
これが買うもの:
1. Hairpinが解決された。内部サービスがapi.example.comを呼び出すと、203.0.113.99(エグレス)経由でアウトバウンドにルーティングされ、通常203.0.113.5(イングレス、異なるIP)に接続されます。NATループは消滅する理由は、2つのIPが異なるマシンに存在するからです。
2. セキュリティの分離。エグレスサーバーのファイアウォールは内部IPの小さなセットに制限できます。イングレスサーバーのファイアウォールは世界に開放されます。2つの独立したルールセットがあり、それぞれがクリーンに1つの役割を表しています。
3. 独立したスケーラビリティ。イングレスの帯域幅はユーザーに関連し、エグレスの帯域幅は内部サービス活動に関連します。1つをアップグレードすることで、もう一方を触れることなくもう一方をアップグレードできます。
4. 障害の分離。エグレスが誤って設定されていないと、パブリックサイトが破壊されません。パブリックサイトに対するDDoS攻撃は、エグレス帯域幅を枯渇させることがなくなります。
5. より明確なメンタルモデル。 各機械には1つの役割があります。エンジニアは、イングレスの懸念事項について考慮することなくエグレスを考慮し、逆にその逆も同じです。
2つの軸、2つのサイズ決定
独立したスケーリング
スプリット前は、どの方向の成長も同じマシンにストレスを与えていました。スプリット後は、各方向が独自のプロビジョニングを持っています。
イングレスのサイズ決定: ユーザー数に比例してスケールします。容量決定は、パブリック向けレイヤー(逆プロキシレプリカの増加、より大きなVM、CDNの前方)にあります。バンド幅予算は、ピーク時のユーザーTRAFFICに基づいて計算されます。
エグレスのサイズ決定: 内部サービスから外部APIコールのボリュームに比例してスケールします。ウェブフックの配信、支払いプロセッサークール、またはサードパーティデータフェッチによって通常は支配されます。バンド幅予算は、内部コールパターンに基づいて計算されます。
障害の分離: パブリックイングレスに対するDDoS攻撃は、エグレスバンド幅(支払いプロセッサークールは通常通り通じます)。エグレスプロキシクラッシュは、パブリックサイトがダウンしない(ユーザーはサイトに到達し続け、ただし内部からのアウトバンドコールのみが失敗します)。
異なるSLO: イングレスの可用性はユーザーにとって重要です(視覚的なサイトダウン時)。エグレスの可用性はオペレーターにとって重要です(背景の失敗が長時間検出される可能性がある)。各側が独自のSLOを持つことができます。
複数のエグレスサーバー
エグレス役割が独自のマシンであるとすると、次の明確な動きは、HAのために複数のエグレスマシンがロードバランサー後で実行されることです。新しい内部サービスはエグレスホスト名(ロードバランスのプールに解決される)にポイントするのではなく、単一のIPにポイントしていました。
分散システムの残りの部分の同じレッスンです:ステートレスな階層が独自の役割を持つと、安価に簡単に複数化できます。
新しいパートナーの統合
あなたの組織は、エグレスサーバーに固定パブリックIP(203.0.113.99)があり、3つの既存のパートナーAPI(支払いプロセッサー、SMSゲートウェイ、メールプロバイダー)にそれをアロリストしたままにしています。
製品チームが追加の4番目の統合を追加したいと考えています:世界中のクライアントエンドポイントに返信するウェブフック配信システム。予測されるボリューム:分単位で30,000回の呼び出しに至るまで、10,000回の呼び出し。
成長するサービスにネットワーク境界を設計する
シンセシス
あなたはイングレスとエグレスが異なるツールが必要である理由、リアルな艦隊でハープインNAT障害が分割のために強制される理由、そして分離が行われた後に得られる独立的なスケーリング、セキュリティ分離、および障害分離を理解しました。
すべての4つを適用してください。
中規模のSaaS会社は、ユーザー向けに3つの製品サブドメイン(app、api、admin)を運営しています。また、4つのアウトバウンド統合(Stripe、Twilio、SendGrid、お客様ウェブフックシステム)があります。今日、すべてが1つのプロキシマシンにあり、1つのパブリックIPが存在します。内部サービスがapi.example.comに呼び出しを試みると、hairpin障害が間欠的に報告されています。彼らは恒久的な解決策を設計することを望んでいます。
これからのコースの方向性
これからのコースの方向性
あなたは、分散システムの最もきれいな責任の分離リファクタリングの1つを確認しました:1つのボックスが2つに変わり、それぞれに明確な役割があり、システムはスケーラビリティ、セキュリティ、および障害分離の利益を獲得しています。
次のレッスン(cs_distsys_failure_modes_and_blast_radius)は、障害分離の推論を拡張します。あなたは、シード名義DNS-SERVFAILポストモーテムを読み、キャスケーディング障害パターンを特定し、システムではなく人々に向けた非難のない行動項目を記述します。
補習: geometry_of_ingress_egress_separation は、分割を二部グラフとして再構成し、カット頂点、ネットワーク分割、およびグラフ理論がネットワーク境界について教えるものです。
よくできました。次に進みましょう。