ルーターは接続済みなのに、なぜサービスへ届かないのか
한국어 원문으로 표시합니다.
목표
실제 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 풀·서비스를 수정·삭제하지 마세요. 기본 경로·정적 우회·다른 정책은 추가하지 않습니다. 단계 준비는 기존 파일을 덮어쓰지 않습니다. 잘못 저장한 파일은 직접 수정해야 하며, 객체를 바꿨다면 관측 기록도 갱신하세요. 세션 종료 시 파일은 사라지므로 필요한 자료는 먼저 내보내세요.
단계
- 관측 도구의 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 한 항목입니다. rib 라우터에는 실제 노드 PodCIDR의 유효한 최선 BGP 경로가 있어야 하지만 FIB에는 없어야 합니다. FRR의 초기 bgp no-rib를 유지하고 Pod HTTP 연결 실패와 비교하세요.
- /root/cca-bgp/pod.yaml에 CiliumBGPAdvertisement cca-pod를 작성·적용합니다. 라벨 lab=cca-bgp와 advertise=pod, 광고 항목은 PodCIDR 하나입니다. 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로 학생용 풀과 서비스 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입니다. 두 서비스에 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 한 항목의 advertisementType=Service, service.addresses=[LoadBalancerIP], selector.matchLabels.publish=selected입니다. vip 라우터는 selected의 정확한 /32만 RIB/FIB에 갖고 200을 반환해야 합니다. excluded와 Pod 직접 접근은 연결 실패여야 합니다.
- 초기 자료 /opt/fixtures/cca-bgp/baseline.json의 광고·서비스 UID와 실제 초기 200을 읽으세요. /root/cca-bgp/withdrawal.json에 advertisement=cca-withdraw, advertisement_uid=초기 광고 UID, service=cca-retire, service_uid=초기 서비스 UID, action=delete-advertisement를 기록합니다. CiliumBGPAdvertisement cca-withdraw만 삭제하세요. cca-retire 서비스·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 상태 코드가 아닙니다.
실제 서버와 다섯 연결망의 신원 기록
관측 도구의 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 하나만 고쳐 광고 없는 연결 만들기
초기 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 한 항목입니다. 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 하나입니다. 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로 학생용 풀과 서비스 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입니다. 두 서비스에 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 한 항목의 advertisementType=Service, service.addresses=[LoadBalancerIP], selector.matchLabels.publish=selected입니다. vip 라우터는 selected의 정확한 /32만 RIB/FIB에 갖고 200을 반환해야 합니다. excluded와 Pod 직접 접근은 연결 실패여야 합니다.
PeerConfig가 고르는 광고 라벨과 광고가 고르는 서비스 라벨은 서로 다른 선택자입니다. 실패할 비교 대상도 함께 확인하세요.
서비스를 남기고 경로만 철회
초기 자료 /opt/fixtures/cca-bgp/baseline.json의 광고·서비스 UID와 실제 초기 200을 읽으세요. /root/cca-bgp/withdrawal.json에 advertisement=cca-withdraw, advertisement_uid=초기 광고 UID, service=cca-retire, service_uid=초기 서비스 UID, action=delete-advertisement를 기록합니다. CiliumBGPAdvertisement cca-withdraw만 삭제하세요. cca-retire 서비스·HTTP Pod·withdraw 피어는 남아야 하고, withdraw 라우터의 203.0.113.20/32 RIB/FIB만 사라져 연결이 실패해야 합니다.
서버나 BGP 피어를 지워 만든 실패는 광고 철회의 증거가 아닙니다. 초기 UID를 유지하는지 확인하세요.
다섯 현재 상태로 종합 사고 보고
관측 도구의 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만 보지 말고 어느 주소·어느 요청·어느 리소스 생애의 관측인지 함께 읽으세요.