ルーターは接続済みなのに、なぜサービスへ届かないのか
目標
実際のCilium・FRR・Linuxルーターで、BGP接続、RIB、FIB、HTTPの、証拠の範囲を区別します。
なぜ重要なのか
経路のアドバタイズの成功を、サービスへの到達の成功と誤解すると、障害の原因を見当違いの場所で探すことになります。失敗した比較も残して、正常な転送と突き合わせ、サーバーやピアを止めずに、アドバタイズだけを取り下げます。すべての作業は、この個人用VMのk3sの中だけで行います。準備に数分かかることがあり、Cilium 1.20.1・FRR 8.4.4・k3s 1.35.8+k3s1を使います。もとの実験は、IPv4・単一ノードであり、複数の物理ノードのフェイルオーバーの代わりにはなりません。
すべての課題リソースには、metadata.labels.lab=cca-bgpを付けます。初期のPeerConfig 5つ、HTTP Pod、cca-retireのプールとServiceを、変更・削除しないでください。デフォルト経路・静的な迂回・ほかのポリシーは、追加しません。ステップの準備は、既存のファイルを上書きしません。間違って保存したファイルは、自分で修正する必要があり、オブジェクトを変更した場合は、観測記録も更新してください。セッションが終了するとファイルは消えるので、必要な資料は先にエクスポートしてください。
ステップ
- 観測ツールのinventoryの出力を、/root/cca-bgp/inventory.jsonに保存してください。Pod・CiliumNodeの名前とUID、実際のPodのIP・割り当てられたPodCIDR、ルーター5つのnetns・両側のIP・ASを読み取ります。全体の10.42.0.0/16を、ノードの割り当て範囲として代わりに書かないでください。
- 初期のCiliumBGPClusterConfig cca-bgpを読み、/root/cca-bgp/peers.yamlに修正版を保存して適用してください。nodeSelectorはkubernetes.io/os=linux、インスタンス名はccaとlocalASN=65001を維持します。emptyピアの誤ったpeerASN=65003だけを65002に直します。残りのrib・pod・vip・withdrawを含むピア5つと、peerAddress・peerConfigRefを維持してください。emptyはEstablishedですが、宛先のアドバタイズはなく、Pod接続は失敗する必要があります。
- /root/cca-bgp/rib.yamlに、CiliumBGPAdvertisement cca-ribを作成して適用します。ラベルはlab=cca-bgpとadvertise=rib、spec.advertisementsはadvertisementType=PodCIDRの1項目です。ribルーターには、実際のノードのPodCIDRの有効なベストパスのBGP経路がある必要がありますが、FIBにはない必要があります。FRRの初期のbgp no-ribを維持して、Pod HTTP接続の失敗と比較してください。
- /root/cca-bgp/pod.yamlに、CiliumBGPAdvertisement cca-podを作成して適用します。ラベルはlab=cca-bgpとadvertise=pod、アドバタイズ項目はPodCIDRの1つです。podルーターは、該当のPodCIDRをRIBとFIBの両方に持ち、Pod HTTP 200を受け取る必要があります。FIBのprotocolはbgp、gatewayは192.0.2.9、devはrouterです。ribルーターの比較状態は維持してください。
- /root/cca-bgp/services.yamlに、v1 Listとして、学習者用のプールとService 2つを保存して適用してください。プールのCiliumLoadBalancerIPPool cca-studentは、blocks=[{start: 203.0.113.10, stop: 203.0.113.11}]、serviceSelector.matchLabels={lab: cca-bgp, pool: student}です。Service cca-selected・cca-excludedは、type=LoadBalancer、loadBalancerClass=io.cilium/bgp-control-plane、externalTrafficPolicy=Cluster、selector.app=cca-bgp-web、port・targetPort=8080、protocol=TCPです。2つのServiceにlab=cca-bgp・pool=studentを付け、publishはそれぞれselected・excludedにします。異なるVIPが割り当てられることを確認し、初期のcca-retireは維持します。
- /root/cca-bgp/vip.yamlに、CiliumBGPAdvertisement cca-vipを保存して適用してください。ラベルはlab=cca-bgp・advertise=vip、advertisementsの1項目のadvertisementType=Service、service.addresses=[LoadBalancerIP]、selector.matchLabels.publish=selectedです。vipルーターは、selectedの正確な/32だけをRIB/FIBに持ち、200を返す必要があります。excludedとPodへの直接アクセスは、接続の失敗である必要があります。
- 初期資料/opt/fixtures/cca-bgp/baseline.jsonのアドバタイズ・ServiceのUIDと、実際の初期の200を読み取ってください。/root/cca-bgp/withdrawal.jsonに、advertisement=cca-withdraw、advertisement_uid=初期のアドバタイズのUID、service=cca-retire、service_uid=初期のServiceのUID、action=delete-advertisementを記録します。CiliumBGPAdvertisement cca-withdrawだけを削除してください。cca-retire Service・HTTP Pod・withdrawピアは残っている必要があり、withdrawルーターの203.0.113.20/32のRIB/FIBだけが消えて、接続が失敗する必要があります。
- 観測ツールのreportの結果を、/root/cca-bgp/report.jsonに保存し、diagnosesを自分で判断して埋めてください。emptyはno-advertisement、ribはnot-installed、podはpod-forwarding、vipはselected-vip、withdrawはwithdrawnです。現在のUID・specのハッシュ、RIB/FIB、各リクエストの識別子とサーバーの応答を読んで、この判断の根拠を説明してみてください。異なるリクエストをコピーして、同じ識別子で埋めないでください。全体採点では、前のステップもすべて、現在の状態で通過する必要があります。
参考
- 観測ツール: python3 /opt/fixtures/cca-bgp/runtime.pyのobserveコマンドで、ステップ名を指定します。ステップ名は、inventory、peer、rib、pod、ipam、vip、withdraw、reportです。
- FRR: ip netns exec cca-rib vtysh -N cca-rib -c 'show bgp ipv4 unicast json'
- FIB: ip -n cca-rib -j route show。ほかの比較では、名前のribを該当の名前に置き換えます。
- ピア: cilium bgp peers、アドバタイズ: kubectl get ciliumbgpadvertisement -o yaml
- ファイルは、単一のJSON/YAMLオブジェクトとして作成します。複数のリソースは、v1 List.itemsを使ってください。
- curlの7/000は接続の失敗であり、000はサーバーのHTTPステータスコードではありません。
実際のサーバーと5つの接続ネットワークのアイデンティティを記録する
観測ツールのinventoryの出力を、/root/cca-bgp/inventory.jsonに保存してください。Pod・CiliumNodeの名前とUID、実際のPodのIP・割り当てられたPodCIDR、ルーター5つのnetns・両側のIP・ASを読み取ります。全体の10.42.0.0/16を、ノードの割り当て範囲として代わりに書かないでください。
実際のPodのIPが、どのノードのPodCIDRの中にあるのかを確認してください。inventoryは設定を変更しません。
ASを1つだけ直して、アドバタイズなしの接続を作る
初期のCiliumBGPClusterConfig cca-bgpを読み、/root/cca-bgp/peers.yamlに修正版を保存して適用してください。nodeSelectorはkubernetes.io/os=linux、インスタンス名はccaとlocalASN=65001を維持します。emptyピアの誤ったpeerASN=65003だけを65002に直します。残りのrib・pod・vip・withdrawを含むピア5つと、peerAddress・peerConfigRefを維持してください。emptyはEstablishedですが、宛先のアドバタイズはなく、Pod接続は失敗する必要があります。
CiliumのpeerASNは、相手のFRRのASです。ピアの接続とアドバタイズは別のものなので、emptyにアドバタイズを追加しないでください。
経路を学習したが、転送はしないルーター
/root/cca-bgp/rib.yamlに、CiliumBGPAdvertisement cca-ribを作成して適用します。ラベルはlab=cca-bgpとadvertise=rib、spec.advertisementsはadvertisementType=PodCIDRの1項目です。ribルーターには、実際のノードのPodCIDRの有効なベストパスのBGP経路がある必要がありますが、FIBにはない必要があります。FRRの初期のbgp no-ribを維持して、Pod HTTP接続の失敗と比較してください。
FRRのRIBを確認したあと、ip -n cca-rib routeを別に読んでください。このステップの失敗する接続は、意図した比較です。
同じPodCIDRで、実際のHTTP転送を確認する
/root/cca-bgp/pod.yamlに、CiliumBGPAdvertisement cca-podを作成して適用します。ラベルはlab=cca-bgpとadvertise=pod、アドバタイズ項目はPodCIDRの1つです。podルーターは、該当のPodCIDRをRIBとFIBの両方に持ち、Pod HTTP 200を受け取る必要があります。FIBのprotocolはbgp、gatewayは192.0.2.9、devはrouterです。ribルーターの比較状態は維持してください。
静的経路やデフォルト経路で迂回しないでください。誰が経路をインストールしたのか、実際のネクストホップは誰なのかも見ます。
Serviceのアドレス割り当てとアドバタイズを分ける
/root/cca-bgp/services.yamlに、v1 Listとして、学習者用のプールとService 2つを保存して適用してください。プールのCiliumLoadBalancerIPPool cca-studentは、blocks=[{start: 203.0.113.10, stop: 203.0.113.11}]、serviceSelector.matchLabels={lab: cca-bgp, pool: student}です。Service cca-selected・cca-excludedは、type=LoadBalancer、loadBalancerClass=io.cilium/bgp-control-plane、externalTrafficPolicy=Cluster、selector.app=cca-bgp-web、port・targetPort=8080、protocol=TCPです。2つのServiceにlab=cca-bgp・pool=studentを付け、publishはそれぞれselected・excludedにします。異なるVIPが割り当てられることを確認し、初期のcca-retireは維持します。
アドレスを受け取ったことは、ルーターがそのアドレスを学習したという意味ではありません。LoadBalancer statusを先に読んでください。
同じサーバーのうち、選択したVIPだけをアドバタイズする
/root/cca-bgp/vip.yamlに、CiliumBGPAdvertisement cca-vipを保存して適用してください。ラベルはlab=cca-bgp・advertise=vip、advertisementsの1項目のadvertisementType=Service、service.addresses=[LoadBalancerIP]、selector.matchLabels.publish=selectedです。vipルーターは、selectedの正確な/32だけをRIB/FIBに持ち、200を返す必要があります。excludedとPodへの直接アクセスは、接続の失敗である必要があります。
PeerConfigが選ぶアドバタイズのラベルと、アドバタイズが選ぶServiceのラベルは、別のセレクターです。失敗すべき比較対象もあわせて確認してください。
Serviceを残したまま、経路だけを取り下げる
初期資料/opt/fixtures/cca-bgp/baseline.jsonのアドバタイズ・ServiceのUIDと、実際の初期の200を読み取ってください。/root/cca-bgp/withdrawal.jsonに、advertisement=cca-withdraw、advertisement_uid=初期のアドバタイズのUID、service=cca-retire、service_uid=初期のServiceのUID、action=delete-advertisementを記録します。CiliumBGPAdvertisement cca-withdrawだけを削除してください。cca-retire Service・HTTP Pod・withdrawピアは残っている必要があり、withdrawルーターの203.0.113.20/32のRIB/FIBだけが消えて、接続が失敗する必要があります。
サーバーやBGPピアを削除して作った失敗は、アドバタイズの取り下げの証拠ではありません。初期のUIDが維持されているかを確認してください。
5つの現在の状態で、総合的にインシデントを報告する
観測ツールのreportの結果を、/root/cca-bgp/report.jsonに保存し、diagnosesを自分で判断して埋めてください。emptyはno-advertisement、ribはnot-installed、podはpod-forwarding、vipはselected-vip、withdrawはwithdrawnです。現在のUID・specのハッシュ、RIB/FIB、各リクエストの識別子とサーバーの応答を読んで、この判断の根拠を説明してみてください。異なるリクエストをコピーして、同じ識別子で埋めないでください。全体採点では、前のステップもすべて、現在の状態で通過する必要があります。
レポートの200だけを見ず、どのアドレス・どのリクエスト・どのリソースの生存期間の観測なのかをあわせて読んでください。