CCA — Cilium Certified Associate
BGP Control Plane and Egress Gateway — The Road Beyond the Cluster
한국어 원문으로 표시합니다.
한 줄 요약
BGP Control Plane 은 노드의 파드 CIDR 과 서비스 VIP 를 BGP 로 이웃 라우터에 광고해 바깥에서 클러스터 안으로 들어오는 길을 만들고, Egress Gateway 는 특정 파드가 바깥으로 나갈 때 정해진 노드와 IP 를 거치게 합니다. 데이터패스를 프로그래밍하지 않는 것은 BGP Control Plane입니다. Egress Gateway는 선택된 외부행 패킷을 게이트웨이 노드로 전달하고 출발지 주소를 SNAT하므로 실제 데이터패스 동작을 바꿉니다. 경로를 알리는 일과 패킷을 처리하는 일을 구분해야 합니다.
왜 이게 필요했나
바깥 라우터가 파드 CIDR로 가는 경로를 모르면 파드 IP만 알아서는 도달할 수 없습니다. 그렇다고 파드 IP가 본질적으로 클러스터 내부 전용이거나, 외부 접근에 반드시 NAT가 필요한 것은 아닙니다. 적절한 왕복 경로와 데이터패스·정책이 있으면 직접 라우팅할 수 있습니다. BGP를 사용하는 환경에서는 Cilium이 경로를 광고해 외부 라우터가 다음 홉을 배울 수 있게 합니다. 서비스 VIP도 주소를 할당받는 일과 외부에서 그 주소로 도달하는 일이 별개입니다.
반대 방향의 문제도 있습니다. 파드 IP 는 계속 바뀌고 노드 IP 도 바뀌는데, 옛 방화벽은 "이 IP 에서 오는 것만 허용" 으로 동작합니다. 문서는 Egress Gateway 의 용도를 정확히 이 사례로 설명합니다. 특정 네임스페이스의 파드가 옛 인프라로 나갈 때 예측 가능한 IP 로 나가게 하는 것입니다. CCA 의 BGP & External Networking 도메인(6%)은 이 두 기능의 역할과 제약을 묻습니다.
어떻게 동작하나
BGP Control Plane 이 하는 일과 하지 않는 일
문서의 첫 문장이 범위를 정합니다. BGP Control Plane 은 BGP 로 연결된 라우터에 경로를 광고해 파드 네트워크와 서비스를 클러스터 바깥에서 닿게 합니다. 그리고 "데이터패스를 프로그래밍하지 않으므로 클러스터 안의 도달성을 위해 쓰지 말라" 고 명시합니다. 켜는 방법은 bgpControlPlane.enabled=true 이고, agent 가 설정된 주소 계열만 광고합니다. IPv4 만 쓰도록 설정된 agent 는 IPv6 경로를 광고할 수 없습니다.
네 가지 리소스
| 리소스 | 역할 |
|---|---|
| CiliumBGPClusterConfig | nodeSelector 로 고른 노드들에 적용할 BGP 인스턴스(localASN)와 피어(peerASN, peerAddress, peerConfigRef) |
| CiliumBGPPeerConfig | 여러 피어가 공유하는 세션 설정 — 타이머, MD5 인증, eBGP multihop, graceful restart, transport, 주소 계열과 광고 선택자 |
| CiliumBGPAdvertisement | 라우팅 테이블에 넣을 프리픽스 종류와 속성(community, localPreference) |
| CiliumBGPNodeConfigOverride | 노드별로 다르게 줄 값 |
apiVersion: cilium.io/v2
kind: CiliumBGPClusterConfig
metadata: {name: cilium-bgp}
spec:
nodeSelector: {matchLabels: {rack: rack0}}
bgpInstances:
- name: instance-65000
localASN: 65000
peers:
- name: peer-65000-tor1
peerASN: 65000
peerAddress: fd00:10:0:0::1
peerConfigRef: {name: cilium-peer}
---
apiVersion: cilium.io/v2
kind: CiliumBGPAdvertisement
metadata: {name: bgp-advertisements, labels: {advertise: bgp}}
spec:
advertisements:
- advertisementType: PodCIDR
- advertisementType: Service
service: {addresses: [LoadBalancerIP]}
selector: {matchExpressions: [{key: bgp, operator: In, values: [blue]}]}
PeerConfig 의 families[].advertisements 는 라벨 선택자입니다. 위 예시의 advertise: bgp 라벨이 그 선택자에 맞아야 광고가 실제로 나갑니다. 리소스를 다 만들었는데 아무것도 광고되지 않는다면 이 라벨을 먼저 봅니다.
기본 동작에서 자주 틀리는 것
세 가지를 문서에서 그대로 옮깁니다. 첫째, BGP 인스턴스는 기본으로 수신 포트 없이 뜹니다. 같은 노드에서 Bird 같은 다른 BGP 라우터가 돌 수 있도록 한 설계라서, Cilium 은 연결을 시작만 하고 받지는 않습니다. 받아야 하면 localPort 를 주는데, 179 번은 CAP_NET_BIND_SERVICE 가 필요합니다. 둘째, 타이머 기본값은 connectRetry 120초, hold 90초, keepalive 30초이고, 데이터센터에서는 hold 9초·keepalive 3초처럼 낮추라고 권합니다. 셋째, graceful restart 를 켜면 agent 가 재시작해도 피어가 경로를 바로 거두지 않아 데이터패스가 계속 전달합니다. 기본 RestartTime 은 120초입니다.
무엇을 광고하는가
PodCIDR 광고는 그 노드에 할당된 파드 CIDR 을 광고하지 전체 범위를 광고하지 않습니다. 이것은 Kubernetes 또는 ClusterPool IPAM 에서만 동작하고, MultiPool IPAM 에서는 CiliumPodIPPool 타입으로 풀을 선택자로 골라 광고합니다. 다른 IPAM 에서는 PodCIDR 타입이 아무 효과가 없습니다. 서비스 광고는 service.addresses 에 LoadBalancerIP·ClusterIP·ExternalIP 를 골라 넣으며, VIP 는 정확한 /32 또는 /128 경로로 나갑니다. 같은 VIP 를 여러 노드가 광고하면 상류 라우터가 ECMP 로 부하를 나누는데, 라우터의 ECMP 경로 수 상한을 넘을 수 있으니 네트워크 담당자와 먼저 확인하라는 경고가 붙어 있습니다. 세션 상태는 cilium bgp peers 로 봅니다.
Egress Gateway — 나가는 길을 고정한다
Egress Gateway 는 파드에서 특정 클러스터 외부 CIDR 로 가는 IPv4·IPv6 연결을 지정한 게이트웨이 노드로 보내고, 그 노드의 예측 가능한 IP 로 마스커레이드합니다. 켜려면 egressGateway.enabled=true 와 함께 BPF 마스커레이드와 kube-proxy 대체가 모두 켜져 있어야 합니다. 정책 리소스는 클러스터 범위인 CiliumEgressGatewayPolicy 이고, selectors[].podSelector 로 원본 파드를(네임스페이스는 io.kubernetes.pod.namespace 라벨로), destinationCIDRs 로 목적지를, excludedCIDRs 로 예외를 적습니다. 내부 클러스터 IP(파드·노드·API 서버)는 목적지 범위에 들어 있어도 SNAT 대상에서 제외됩니다.
제약도 명확합니다. 새 파드에는 정책이 적용되기까지 지연이 있어 그동안은 파드 IP 나 노드 IP 로 나갈 수 있고, Cluster Mesh 와 함께 쓸 수 없으며, 아이덴티티 저장을 kvstore 로 둔 모드와 CiliumEndpointSlice 와도 호환되지 않습니다.
현장에서 만나는 모습
BGP 세션이 Established라고 서비스 도달까지 증명된 것은 아닙니다. 먼저 피어의 주소·AS·연결 상태를 확인하고, 그다음 수신 라우팅 테이블(RIB)에 목적지 프리픽스가 있는지 봅니다. 경로가 있다면 선택된 다음 홉과 커널 전달 경로(FIB)를 확인하고 실제 요청으로 이어 갑니다. 경로가 없으면 광고 선택자와 주소 할당부터, 경로가 있는데 요청이 실패하면 서비스 백엔드·데이터패스·정책·반환 경로를 조사합니다. 하나의 timeout만 보고 인증 실패나 정책 차단으로 단정하지 않습니다.
Egress Gateway 는 켠 직후 "일부 요청이 여전히 노드 IP 로 나간다" 는 보고가 오는데, 새로 뜬 파드에 정책이 붙기까지의 지연이 원인인 경우가 많습니다. 방화벽 쪽에서 게이트웨이 IP 만 허용했다면 그 짧은 구간의 요청이 거부됩니다.
실측으로 분리한 다섯 상태
LabHub의 2026-09-12 개인 VM 탐침은 Cilium 1.20.1과 FRR 8.4.4를 연결해 다음 상태를 비교했습니다. FRR은 외부 라우터 역할의 네트워크 네임스페이스에 두었으며 기본 경로는 넣지 않았습니다. 여기서 경로가 없다는 것은 실험 목적지에 대한 경로가 없다는 뜻이지, 라우터의 연결망 경로까지 전부 없다는 뜻은 아닙니다.
| 상태 | 피어 | 목적지 RIB | 목적지 FIB | 실제 Pod HTTP |
|---|---|---|---|---|
| 피어 설정 전 | Idle | 없음 | 없음 | 연결 실패 |
| 피어만 연결 | Established | 없음 | 없음 | 연결 실패 |
| PodCIDR 광고, FRR의 bgp no-rib 유지 | Established | 있음 | 없음 | 연결 실패 |
| FRR의 no bgp no-rib 적용 | Established | 있음 | 있음 | 200 |
| PodCIDR 광고 철회 후 | Established | 없음 | 없음 | 연결 실패 |
bgp no-rib은 이 탐침에서 BGP 학습과 커널 경로 설치를 의도적으로 분리한 FRR 설정입니다. Cilium의 광고를 켜면 FRR의 전달 설정까지 자동으로 해결된다는 뜻이 아닙니다. 할당된 노드 PodCIDR은 10.42.0.0/24였으며 전체 설정 풀인 10.42.0.0/16이 아니었습니다. 실패 시 curl 종료 코드는 7, 출력은 000이었습니다. 000은 서버가 준 HTTP 상태 코드가 아니고, 이 결과를 NetworkPolicy의 timeout 차단으로 바꿔 설명해서도 안 됩니다. 관측 지점과 명령의 종료 코드까지 남겨야 다른 실패와 구분할 수 있습니다.
이후 별도 비교에서는 선택한 서비스 VIP의 /32만 광고하고, 광고하지 않은 다른 VIP와 Pod 직접 접근은 실패하는지 확인했습니다. 같은 VM에서 만든 라우터 네임스페이스는 독립된 외부 머신과 달리 socket-LB의 영향을 받을 수 있었습니다. Pod 경로를 임시로 넣으면 광고하지 않은 VIP까지 성공해 비교가 흐려졌습니다. 최종적으로 socketLB.hostNamespaceOnly=true가 실행 중 에이전트에 적용됐는지 확인한 뒤, Pod 경로와 기본 경로 없이 선택 VIP만 200인 것을 확인했습니다. 이 설정을 모든 운영 장애의 만능 해결책으로 쓰는 것이 아니라, 실험 환경이 측정 대상을 바꾸지 않는지 점검하는 사례로 읽어야 합니다.
이 표는 개발용 탐침의 결과이며, 학습자가 플랫폼에서 새 BGP 실습을 완주했다는 증거는 아닙니다. 후속 실습은 비교 상태를 분리해 마지막 단계 이후에도 전체 재채점이 가능하도록 구성합니다. 공식 동작은 FRR 8.4 BGP와 Cilium socket-LB 우회에서 확인할 수 있습니다.
다음 퀴즈에서 확인할 것
Gateway API 리소스의 역할과 트래픽 분할 필드, Cilium 이 다른 컨트롤러와 다른 지점(eBPF 가로채기, ingress 아이덴티티), 노드당 Envoy 구조, WireGuard 의 키 배포와 포트, BGP 네 리소스의 역할, PodCIDR 광고 범위와 VIP 경로 길이, 수신 포트 기본값, Egress Gateway 의 전제 조건을 묻습니다. 참고: Cilium BGP Control Plane, BGP Control Plane Resources, Egress Gateway.