🧱 BGP Control Plane Resources
Cilium의 BGP Control Plane은 BGP Peer, Policy, advertisement 구성을 제공하는 유연한 커스텀 리소스들로부터 제공된다.
BGP Control Plane을 관리하기 위해, 다음의 자원들이 사용된다:
CiliumBGPClusterConfig: BGP 인스턴스와 피어링 구성을 정의한다. 여러 노드들에 적용된다.CiliumBGPPeerConfig: BGP Peering의 일반적인 설정 셋으로, 여러 peer들간에 사용될 수 있다.CiliumBGPAdvertisement: BGP Routing table에 주입되는 prefix들을 정의한다.CiliumBGPNodeConfigOverride: node-specific한 BGP구성을 정의하여 더 나은 제어를 제공한다.
아래의 다이어그램으로 보여질 수 있다:

📜 BGP 클러스터 구성
CiliumBGPClusterConfig는 nodeSelector필드에 있는 1개 이상의 노드에 대한 BGP설정을 하는 곳이다.
각각의 CiliumBGPClusterConfig은 1개 이상의 BGP 인스턴스를 정의하며, 그들의 name필드에 대해 식별된다.
BGP 인스턴스는 1개 이상의 Peer를 가질 수 있다.
각 Peer는 name필드에 의해 식별된다.
Peer AS는 peerASN과 peerAddress필드에 의해 정의된다.
Peer의 구성 설정은 peerConfigRef필드로 참조할 수 있다.
peerConfigRef의 Group과 kind는 옵셔널하며, 기본적으로 cilium.io와 CiliumBGPPeerConfig이다.
기본적으로, BGP 컨트롤 플레인은 리스닝 포트 없이 동작한다.
설정된 Peering만 가능하다는 의미이며, 들어오는 Peering을 받을 수 없다는 뜻이다.
이게 기본인데, 그 이유는 같은 노드에서 BGP라우터가 동작할 수 있음을 고려했기 때문이다.
들어오는 커넥션을 받으려면, localPort필드로 리스닝 포트를 정할 수 있다.
NOTE
기본 BGP Port(179)를 쓸 때에는,CAP_NET_BIND_SERVICE가 필요하다.
만약 기본 포트를 쓰고싶다면,securityContext.capabilities.ciliumAgent에서CAP_NET_BIND_SERVICE를 helm value로 넣어줘야 한다.
아래는 CiliumBGPClusterConfig의 예시이며, instance-65000이 두 개의 peer와 피어링한 것이다.
|
|
Auto-Discovery
Cilium BGP Control Plane은 BGP Peer에 대한 자동 디스커버리 역시 지원한다.
mode에서 특정 특정 IP주소를 정할 수 있다.
DefaultGateway모드도 있다.
기본 게이트웨이를 이용하면, 자동으로 기본 게이트웨이와 BGP를 맺으려 한다.
아래와 같이 할 수 있다:
|
|
ToR switch의 BGP 구성에는 다음 설정을 해줘야 한다:
|
|
설정이 적용되면, Cilium은 특정 Address Family의 기본게이트웨이를 식별하여 자동으로 BGP 세션을 맺는다.
peerConfigRef 세션 파라미터를 참조하여 피어링을 맺는다.
default gateway설정 + multi-homing(두 개 이상의 BGP와 연결)일때는 같은 address family에 대해서 동시에 여러 BGP세션을 맺을 수 없다.
대신, 우선순위가 더 높은 (metric이 더 낮은)경로를 하나 선택하여 BGP 세션을 맺는다.
Cilium은 BGP 세션을 address family당 하나만 맺을 수 있다.
대신, failover로 연결가능한데, 처음에 아래와 같은 상황이라고 가정했을 때,
|
|
ToR A가 장애가 난다면, ToR B와 새로 BGP 세션을 맺는다.
아래 예시에서는, IP를 직접 명시하지 않았지만 기본 게이트웨이에서 가장 우선순위가 높은 하나를 고른다고 보면 된다.
|
|
대신, 같은 address family에서 여러 peer와 세션을 맺고 싶다면, 직접 두 peer를 명시해야 한다.
🛠️ BGP Peer Configuration
CiliumBGPPeerConfig 자원은 BGP Peer 연결설정을 정의할 때 사용한다.
여러 Peer와의 연결에서 같은 Configuration을 공유해서 사용할 수 있다.
여러 옵션을 가질 수 있다:
- MD5 Password
- Timers
- EBGP Multihop
- Graceful Restart
- Transport
- Address Families
아래는 예시이다:
|
|
MD5 Password
AuthSecretRef는 RFC-2385의 TCP MD5 Password를 BGP Peering에 쓸 수 있다.
아래는 예시이다.
|
|
AuthSecretRef는 BGP secrets namespace에 써야 한다.
(helm-chart 기본값은 kube-system)
password라는 키를 가져야 한다.
BGP 시크릿은 각 Cilium Agent 인스턴스가 최소로 쓸 수 있는 권한으로 제한되어있다.
만약 namespace를 바꾸고싶다면, helm chart의 bgpControlPlane.secretNamespace.name의 값을 바꾸면 된다.
생성도 자동으로 하고싶으면, bgpControlPlane.secretNamespace.create를 true로 해주면 된다.
패스워드가 틀리다면, dial: i/o timeout으로만 뜬다.
만약 authSecretRef의 시크릿을 찾을 수 없으면, BGP시션은 빈 패스워드를 쓰고, 아래와 같은 오류를 낸다:
|
|
Timers
BGP Control Plane은 BGP timer 파라미터를 수정하는 것을 지원한다.
| Name | Field | Default |
|---|---|---|
| ConnectRetryTimer | connectRetryTimeSeconds |
120 |
| HoldTimer | holdTimeSeconds |
90 |
| KeepaliveTimer | keepAliveTimeSeconds |
30 |
장애 감지를 더 빠르게 하기 위해서는, HoldTimer와 KeepaliceTimer를 더 짧은 주기로 설정하는것을 권장한다.
최소수치인 holdTmeSeconds=9와 keepAliveTimeSeconds=3과 같은 식으로 할 수 있다.
Peer와 연결이 끊기고 빠르게 회복하려면, connectRetryTimeSeconds를 줄이면 된다.
내부적으로 랜덤 jitter가 적용되는데, [ConnectRetryTimeSeconds, 2 * CoonnectRetryTimeSeconds)이다.
|
|
EBGP Multihop
기본적으로 BGP 패킷의 IP TTL은 1인데, Multihop 설정을 위해서는, spec.ebgpMultihop을 1보다 크게 해주면 된다.
Graceful Restart
Graceful Restart 를 켜면, Cilium Agent가 재시작하는것과 같이 BGP 프로세스가 잠깐 내려가도, 실제 커널은 살아있어서 패킷 포워딩은 가능한 경우가 있다.
이때 route를 지우면 트래픽 중단이 불필요하게 생기니, 금방 다시 올라올 수 있다고 알려주는 capacity가 graceful restart이다.
- Cilium이 BGP OPEN 메시지에서 graceful restart capacity를 광고
- Peer는 재시작중에도 경로유지를 할 것을 약속
- Cilium Agent가 재시작되는 동안, BGP 세션이 끊기는데,
Peer는 route를RestartTime동안 유지 - Cilium은 다시 BGP를 복구하면, 트래픽 중단없이 계속 이어짐
- 시간이 초과되면, 실제로 죽었다고 판단하고 route삭제
상대 라우터는 TCP FIN플래그 메시지를 받고, RestartTime 타이머를 시작한다.
|
|
RestartTime의 기본값은 120초이다.
Transport
transport는 TCP연결의 세부사항을 만진다.
기본 설정과 다르게 TCP연결을 설정할 때 사용한다.
|
|
Address Families
families필드에는 AFI(Address Family Identifier) , SAFI(Subsequent Address Family Identifier) 의 리스트가 있다.
기본적으로, address family가 없다면, BGP Control Plane은 IPv4 Unicast와 IPv6 Unicast를 멀티프로토콜 확장 capability로 광고한다.
각 Address family에서는, advertisements label selector를 통해 라우트 광고를 제어할 수 있다.
CiliumBGPAdvertisement를 골라야 한다.
NOTE 매칭이 없으면, 아무 prefix도 광고될 수 없다.
|
|
📢 BGP Advertisements
CiliumBGPAdvertisement자원은 다양한 광고 타입을 정할 수 있다.
advertisements label의 매칭은 Peer Configuration의 familes와 연관있다.
BGP Attributes
BGP path attributes를 advertisements[*]에 정의할 수 있다.
두 가지의 속성이 있는데, Communities와 LocalPreference이다.
- Communities: BGP의 라우트 태그같은 개념이라고 보면 된다.
standard는:으로 32비트 숫자를 나누며, 16비트:16비트숫자를 쓰는 형식이다.wellknown은standard와 같은 형식을 가지지만, well-known값에 대한 alias를 가진다.- ex. internet은 0:0, no-advertise는 “65535:65282”
large는 3개의 4바이트정수가 콜론으로 나뉘어진다.- ex.
64512:100:50
- ex.
- Local Preference: iBGP에서의 내부 우선순위 값이며,
eBGPpeer에게는 무시될것이다.
|
|
Advertisement Types
Cilium은 세 가지의 광고를 제공한다:
- Pod CIDR range
- Service VIPs
- Interface IPs
Pod CIDR Ranges
노드의 Pod CIDR prefix를 광고할 수 있다.
BGP Peer가 로드밸런서 또는 NAT없이 접속할 수 있다.
IPAM모드 세팅별로 두 가지 방법이 있다.
Kubernetes나 ClusterPool IPAM인 경우, advertisement의 type을 PodCIDR로 하면 된다.
|
|
이 구성으로, BGP 인스턴스는 로컬 노드의 Pod CIDR prefix를 광고할 수 있다.
MultiPool IPAM에서는 advertisementType을 CiliumIPPool로 해야 한다.
selector필드의 .matchLabels 또는 matchExpressions로 매칭할 수 있다.
|
|
이 설정에서는 선택된 Cilium Pod IP Pool에 할당된 PodCIDR prefix가 광고된다.
이 예시에서, CiliumNode 리소스에 CIDR이 반드시 할당되어야 한다.
모든 CiliumPodIPPool CIDR를 클러스터 안에 광고하고 싶다면, NotIn으로 dummy key-value를 이용하여 쓸 수 있다.
|
|
name이나 namespace를 기반으로 고르고 싶은 때가 있는데, 특별한 키를 제공한다.
io.cilium.podippool.name->meta.nameio.cilium.podippool.namespace->meta.namespace
|
|
다른 IPAM Type은 BGP prefix 광고가 지원하지 않는다.
Service Virtual IPs
Service는 여러 virtual IP를 가질 수 있다.
Service의 virtual IP를 BGP Peer로 광고할 수 있다.
NOTE Cilium의 BGP Control Plane은 VIP를 /32또는 /128 prefix로 광고한다.
service의 virtual IP를 광고하기 위해, advertisementType의 필드를 Service로 하고,
service.addresses 필드에 LoadBalancerIP, ClusterIP, 또는 ExternalIP로 해준다.
.selector에서 .matchLabels또는 matchExpressions로 가능하다.
|
|
업스트림 라우터가 **ECMP(Equal Cost Multi Path)**를 지원한다면, 같은 VIP에 대해서 실제로 로드밸런싱이 일어날 것이다.
NOTE 많은 라우터들이 라우팅 테이블에 저장하는 ECMP 경로에 대해 한계를 가지는데, 많은 노드들로부터 Service VIP가 광고된다면, 한계를 넘을 수 있다. 이 기능을 쓰려면, 네트워크 관리자로부터 한계를 알아내는 것이 좋을 것이다.
각 주소 타입별로 특징이 있다:
- ClusterIP
- 클러스터 내부 전용.
kubeProxyReplacement와 함께 쓰려면, 여기를 참고
- ExternalIP
- 관리자가 직접 지정하는 외부 노출용 IP
kubeProxyReplacement와 함께 쓰려면, ExternalIP 지원이 켜져야 한다.
- LoadBalancerIP
- Kubernetes에서는 이 IP를 자동할당하지 않는다.
- 그래서, 별도 할당 주체가 필요하다.
- Cilium은 LoadBalancer IPAM을 이용할 수 있다. 특별한 metadata들 역시 제공된다:
io.kubernetes.service.namespace->.meta.namespaceio.kubernetes.service.name->.meta.name
service가 LoadBalancer 타입일때, loadBalancerClass=io.cilium/bgp-control-plane이거나 비어있다면, Cilium이 광고할 수 있다.
또는, 미설정인 경우 광고할 수 있다.
대신, 다른 class를 지정하면, Cilium은 광고할 수 없다.
NOTE
externalTrafficPolicy가Cluster인경우, 조건 없이 광고하지만,Local인 경우, 해당 endpoint가 없으면 광고하지 않는다.
하나의 Service가 여러 advertisement selector에 동시에 걸릴 수 있는데, 이 경우 community는 합쳐지며(union), local-pref는 가장 큰 값 하나(max)를 쓴다.
기본적으로 service는 단일 IP(/32, /128)을 광고하지만, aggregation이 지원되기도 한다.
아래와 같이 더 큰 대역단위로 광고할 수 있다.
|
|
이렇게 하면, 라우팅 테이블을 적게 차지하며, 광고 수를 줄일 수 있다.
그러나, 실제 service에 없는 트래픽도 클러스터로 들어올 수 있음을 유의해야 하며,
또한 externalTrafficPolicy=Local인 경우, aggregation될 수 없다.
Interface IP
Service가 아니라, 노드 인터페이스에 붙은 IP자체를 광고할 수도 있다.
멀티호밍에 유용하게 쓰일 수 있다.
정확한 주소(/32, /128)로 광고되며, 다음의 주소는 광고되지 않는다:
- loopback
- multicast
- IPv6 link-local
- IPv4-mapped IPv6
인터페이스는 up이나 unknown상태여야 한다.
|
|
(여기서의 lo는 논리적 인터페이스로, 127.0.0.1이 아닌 다른 주소를 붙인 것이다.)
📝 BGP Configurations Override
🏋️ Hands-On
helm values에 다음과 같이 추가한 뒤, 업데이트한다:
|
|
LoadBalancer IP 광고
다음의 네트워크 토폴로지를 가정한다:

쿠버네티스 노드들의 기본 게이트웨이가 FRRouter로 설정되어있다.
FRRouter의 설정(/etc/frr/frr.conf)은 다음과 같다:
|
|
CiliumBGPClusterConfig
우선, CiliumBGPClusterConfig를 설정한다.
이 설정은 모든 노드에 적용된다.
|
|
localPort를 BGP의 기본 포트인 179번 well-known포트로 받기 위해서는, helm values에서 다음과 같이 설정되어야 한다:
|
|
CiliumBGPPeerConfig
cilium-peer라는 CiliumBGPPeerConfig를 설정한다.
|
|
CiliumBGPAdvertisement
|
|
간단한 HTTP 앱 노출
|
|
이제, kubectl apply -f http-test.yaml로 적용하면 된다.
단, CiliumLoadBalancerIPPool이 설정되어있어야 한다.
아래와 같이 설정할 수 있다:
|
|
생성된 service를 확인해보자.
|
|
BGP Peering 상태도 확인할 수 있다:
|
|
📚 결론
- Cilium BGP Control Plane을 이용하여 BGP Peering을 맺은 라우터에 클러스터 내에서 쓰이는 IP들 및 LoadBalancer IP들을 광고할 수 있다.
- L2광고대신 실드가 LoadBalancer IP를 광고하는 “진짜 로드밸런싱"이 가능하다.
- Pod IP에 직접 접근할 수도 있으며, 서로 다른 네트워크에서 중간에 BGP라우터가 중개하는 경우, Pod간 통신에서 이 기능이 활용될 수 있다.