CCA — 실리움 인증 어소시에이트 · BGP 사고 조사: 경로를 배웠는데 왜 못 갈까 · 실습
연결된 라우터인데 서비스는 왜 안 열릴까
목표
실제 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 풀·서비스를 수정·삭제하지 마세요. 기본 경로·정적 우회·다른 정책은 추가하지 않습니다. 단계 준비는 기존 파일을 덮어쓰지 않습니다. 잘못 저장한 파일은 직접 수정해야 하며, 객체를 바꿨다면 관측 기록도 갱신하세요. 세션 종료 시 파일은 사라지므로 필요한 자료는 먼저 내보내세요.
단계
1. 관측 도구의 inventory 출력을 /root/cca-bgp/inventory.json에 저장하세요. Pod·CiliumNode의 이름과 UID, 실제 Pod IP·할당된 PodCIDR, 라우터 5개의 netns·양쪽 IP·AS를 읽습니다. 전체 10.42.0.0/16을 노드 할당 범위로 대신 적지 마세요.
2. 초기 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 연결은 실패해야 합니다.
3. /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 연결 실패와 비교하세요.
4. /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 라우터의 비교 상태는 보존하세요.
5. /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는 보존합니다.
6. /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 직접 접근은 연결 실패여야 합니다.
7. 초기 자료 /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만 사라져 연결이 실패해야 합니다.
8. 관측 도구의 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 상태 코드가 아닙니다.
단계 8개
- 실제 서버와 다섯 연결망의 신원 기록
- AS 하나만 고쳐 광고 없는 연결 만들기
- 경로를 배웠지만 전달하지 않는 라우터
- 같은 PodCIDR로 실제 HTTP 전달 확인
- 서비스 주소 할당과 광고 분리
- 같은 서버 중 선택한 VIP만 광고
- 서비스를 남기고 경로만 철회
- 다섯 현재 상태로 종합 사고 보고