アップグレードが適用され、トンネルの向こう側のシステムが、前週まで動いていた Pod のトラフィックを拒否し始める。トンネルは上がっており、ファイアウォールのルールも変わらず、ピアのポリシーを編集した人はいない。変わったのはクラスタのログには現れない部分だ:それらのシステムが今見ている送信元アドレス。このずれが、ネットワーク障害のように見えて権限の問題のように振る舞う不具合を説明する。

有効な答えは二つあり、それぞれ別の場所へ導く。ConfigMap を編集する前に、ソースの契約を選んでほしい。

導入されなくなった既定のルール

以前の GKE リリースは、宛先が 10.0.0.0/8 の外にあるときは常に Pod の送信元をノードのアドレスに置き換える masquerade ルールを導入していた。その範囲の内側にある VPN ゲートウェイは Pod のアドレスを見ていたが、もっと遠くのものはノードから来たように見えていた。ピアは自分たちが観測したとおり、ノードのアドレスを前提に許可リストと戻り経路を組み立てた。

後のリリースはその既定ルールを導入しなくなった。Pod のトラフィックは宛先が何であっても、Pod のアドレスでゲートウェイに届く。ノードのアドレスだけを経路として持つピアは応答を捨て、どちらの側も役に立つログを残さない。要求は遠端で成功してさえいることがあり、それがこの不具合を追いにくくしている。

死んだ部品という意味では何も壊れていない。単に、どちらの送信元が正当かについて両側の認識が食い違っているだけだ。

ピアに見せるべき送信元を選ぶ

Pod のアドレスを保つほうが正確な契約だ。遠端はトラフィックを生んだワークロードを見られ、ログは正直なままで、Pod ごとのポリシーも可能になる。代償は、ピアが Pod のプレフィックスを持たなければならないことだ。

ノードのアドレスを保つほうが安い契約だ。その宛先に対して masquerade を再び有効にすれば、ピアはすでに信頼しているアドレスを見続けられる。

どちらを選ぶかは一つの問いで決まる:ピアは送信元をどう扱うのか。ログを取り、送信元ごとのポリシーを適用し、狭い戻り経路を強制するなら、Pod のアドレスは追加設定に見合う。応答を返すだけでよいなら、masquerade のほうが安く、相手側に何も求めない。両チームが書き留めておく限り、どちらの選択も擁護できる。

第三の選択肢はたいてい誤りだ:すべてを masquerade すると、トラフィックを紐づける能力を失う。ピアが本当にノードのアドレス以外を経路に持てない場合を除いて、避けるべきだ。

nonMasqueradeCIDRs を実際の範囲に向ける

GKE は kube-system で ip-masq-agent を動かしており、その ConfigMap が masquerade を飛ばす宛先を列挙している。トンネルに向けて Pod の送信元を保つには、Pod の範囲、ノードのサブネット、オンプレミスのプレフィックスがすべてその一覧に入る。

サンプルの値は自分のクラスタの範囲に置き換え、必要以上に一覧を広げない。余分な項目は、別の宛先から見えるものを変えてしまう。下の三つの項目は、Pod のネットワーク、ノードのサブネット、トンネルの向こう側のプレフィックスを表している:

nonMasqueradeCIDRs:
  - 10.12.0.0/14
  - 10.100.0.0/16
  - 172.16.0.0/12
masqLinkLocal: false
resyncInterval: 60s

0.0.0.0/0 の項目はすべての宛先で masquerade を無効にし、無関係なワークロードが外部サービスにどう見えるかを変えるため、意図されることはほとんどない。エージェントは resyncInterval で設定を読み直すので、通常は再起動が要らない。エージェントの Pod が動いていることを確認し、その中にマウントされたファイルを開く。そのファイルを読むことが、変更が届いた証拠になる。

戻りの経路がもう半分だ

masquerade が変えるのは要求の送信元だけで、それ以外ではない。ピアはどの送信元を受け取っても、そこへ戻る経路を依然として必要とし、クラスタもまたピアへ向かう経路を必要とする。

VPN ゲートウェイでのキャプチャは二つの障害を素早く切り分ける。Pod のアドレスで届き、応答が一度も返らないパケットは、ピアに Pod のプレフィックスへの経路がないことを意味する。ゲートウェイに現れてもクラスタに届かない応答は、ローカルの経路が欠けていることを意味する。どちらにせよ契約をチケットに書く:ピアが見る送信元と、応答を戻す先のプレフィックスだ。

アップグレードのたびに再確認する

masquerade の既定の振る舞いはすでに一度変わっており、ノードプールの入れ替えでクラスタのネットワークが初期化されることもある。ソースの契約は前提にするものではなく、確認するものとして扱う。

アップグレードの後、Pod からオンプレミスのサービスへ要求を一つ送り、ピアが記録する送信元を読む。その一度の観察が、トンネルの状態画面が平然と正常と報告する回帰を捕まえる。繰り返すのに一分かかり、次の人の夜が一つ救われる。

関連記事