トンネルと backend の間のどこかで、クライアントのアドレスは生き残るか置き換えられるかします。どちらの結果も正当化できます。選択は受け側サービスの所有者のものであり、CNI をインストールした人のものではありません。クライアント単位の認可、クォータ、監査記録が重要なら、アドレスはすべてのホップを生き延びる必要があります。共有の帰属で足りるなら、送信元 NAT はそうでなければ永遠に維持することになるルーティング問題を消します。

クライアントのアドレスが実際に消える場所

リモートクライアントのパケットは、トンネル範囲内の内部送信元、たとえば 10.90.0.42 で VPN pod に届きます。pod がそのパケットを ClusterIP や pod IP へ転送すると、三つの異なる仕組みが送信元を書き換えられます。ノードの CNI masquerade ルールは pod がクラスタ CIDR の外へ送る通信を対象にします。宛先ノードの kube-proxy conntrack エントリは Service へのホップ自体を対象にします。接続を終端するプロキシはパケットを転送しないので、最終的に見える送信元はプロキシのものです。

それぞれが別の層に住んでいるので、一つの Service フィールドで経路全体が直ることはほとんどありません。

VPN の公開 Service の externalTrafficPolicy が決めるのは外側の接続だけです。Local は受け取ったノードにリモートアドレスを残し、Cluster は kube-proxy にパケットを別ノードへ渡してそこで masquerade させます。この設定がクライアントの接続するリスナーを支配します。VPN プロセスがその後クラスタへ流す復号済みパケットについては何も語りません。

議論を決着させる 三つの条件

この話題が出るたびに同じ 三つの質問を同じ順で投げます。最初の質問で議論が終わることが多いからです。答えるのは個別のワークロードについてで、クラスタ全体についてではありません。一社の中の 二つのクラスタが別々の答えに達し、どちらも正しいことがあります。

QuestionPreserveSNAT
Does the backend enforce policy per client?Yes, the address is the identityOnly if a trusted proxy supplies identity
Can the cluster route 10.90.0.0/24 back to a stable gateway?RequiredNot needed
Is the workload a forwarder or a proxy?ForwarderProxy is fine

backend が最初の質問に「はい」、二番目に「いいえ」と答えるなら、必要なのは manifest の編集ではなくネットワーク作業です。三行目がプロキシと言うなら、そのアドレスは最初から生き残りませんし、そうでないふりは 一週間のパケットキャプチャの費用になります。

preserve モードがネットワークに求めるもの

送信元を保持するとは、宛先ノードが有効な VPN ゲートウェイ経由で 10.90.0.42 へ通信を返さなければならないということです。VPN プールはクラスタ CIDR ではないので、どの CNI も既定ではルーティングしません。経路は自分で追加し、それが指すゲートウェイのエンドポイントが再スケジュールを生き延びることを確かめます。

ip route add 10.90.0.0/24 via 10.244.3.17 dev eth0
sysctl -w net.ipv4.conf.eth0.rp_filter=2

その次のホップは pod のアドレスで、pod のアドレスは動きます。経路を Service VIP か動かないノードアドレスに向けるか、退去のたびにゲートウェイを追いかけることを受け入れます。逆経路フィルタも罠です。strict モードは到着したインターフェースと戻り経路が一致しないパケットを落としますが、これは保持された VPN フローの形そのものです。

緩い検証は、機能するリターンパスと backend を離れた後に消える応答 の違いになることがよくあります。VPN ノードの masquerade ルールもトンネル範囲を除外する必要があります。さもないと、どの経路を組んだとしても転送パケットは pod のアドレスで出ていきます。この除外は iptables を手で編集するのではなく CNI 自身の設定で表現してください。エージェントは再起動でチェーンを書き直すので、手書きのルールは次のアップグレードまでしか持ちません。

NetworkPolicy はアクセス制御であってルーティングではありません。ポリシーを厳しくしても masquerade がすでに置き換えたアドレスは戻りません。

SNAT のコストと、それを書き留める方法

クラスタ向きの送信元 NAT は安い設計で、間違いではありません。backend は VPN pod かノードのアドレスを見て、ログは互いに一致し、戻り経路は存在しなくて構いません。失うのは 二人のクライアントをネットワーク層で区別する能力なので、クォータ、BAN、監査証跡は別の場所から供給する必要があります。

ふつうその別の場所はアプリケーションです。セッショントークン、署名付きヘッダー、あるいは自分で管理するプロキシが書く PROXY プロトコルの行です。これらが受信側に信頼できる身元を与えるのは、プロキシが経路上にいてヘッダーをクライアント側から設定できないときだけです。runbook ではどれが当てはまるかを明記してください。次のエンジニアはログのアドレスがクライアントだと思い込むからです。実際は違いますし、一度のインシデントでその思い込みは高くつきます。

書き留めてある限り、この交換は正直なままです。

機能する経路と幸運な経路を分けるチェック

キャッシュされた接続ではなく新しい接続で試し、両方向で試します。いくつもの障害が断続的に見えるのは、新しいフローが書き換えられた経路を通るからだけです。

認可された 一つのリクエストの間に tuple を 三点で捕まえます。カプセル化解除の直後、VPN pod の egress インターフェース、そして backend です。送信元が 二番目と 三番目のキャプチャの間で変わるなら原因は pod の下流です。二番目より前に変わるなら pod 自身が変換しています。

次に VPN pod を削除し、再スケジュール中に同じテストを繰り返します。退去で壊れる保持経路は未完成ですし、もう存在しないアドレスに固定された NAT ルールも同じです。最後に、拒否されるはずの送信元から 一つリクエストを送り、拒否が欠けた経路ではなくポリシーから来ることを確かめます。

関連記事