본문 바로가기
Work/개발 노트

[Cilium study] 5주차 - BGP Control Plane

by ★용호★ 2025. 8. 15.

실습 환경 구성

curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/cilium-study/5w/Vagrantfile

vagrant up
  • 기본 배포 가상 머신 : k8s-ctr, k8s-w1, k8s-w0, router (frr 라우팅)
  • router : 192.168.10.0/24 ↔ 192.168.20.0/24 대역 라우팅 역할, k8s 에 join 되지 않은 서버, BGP 동작을 위한 frr 툴 설치됨 - FRR
  • k8s-w0 : k8s-ctr/w1 노드와 다른 네트워크 대역에 배치
  • 실습 동작에 필요한 static routing 설정 됨 with vagrant script file

FRR은 서버에서 돌아가는 라우팅 도구(데몬)라고 볼 수 있습니다. 원래는 네트워크 장비를 사용해야하는데 리눅스 환경에서 네트워크 장비의 역할을 할 수 있도록 하는 역할 합니다.

Cilium을 helm으로 install 할 때 bgpControlPlane.enable을 true로 설정하면 이후부터는 Cilium 컨트롤 플레인이 BGP를 사용하게 됩니다. BPG 사용이 활성화 되면 아래와 같은 설정 정보를 확인할 수 있습니다.

cilium config view ❘ grep -i bgp

  • bgp-control-plane.enabled: true로 설정
  • auto-direct-node-routes: false로 설정 - BGP로 정보를 광고받아서 처리하기 때문에 같은 네트워크 대역이더라도 이 기능이 필요하지 않음

FRR에 의해 생성된 프로세스와 소켓 리스닝 정보도 아래와 같이 확인할 수 있습니다.

(참고) BGP와 FRR 개념 설명

  • BGP (Border Gateway Protocol): 인터넷에서 라우팅 정보를 교환하는 프로토콜입니다. 서로 다른 자율 시스템(AS, Autonomous System) 간에 네트워크 경로 정보를 공유하여 최적의 라우팅 경로를 결정합니다.
  • FRR (Free Range Routing): FRR은 리눅스에서 동작하는 라우팅 소프트웨어 suite입니다. 여러 라우팅 프로토콜(BGP, OSPF 등)을 지원하며, 네트워크 장비 대신 소프트웨어로 라우팅 기능을 제공합니다.
  • Cilium BGP 컨트롤 플레인 구조:
    • BGP 버전 1 (레거시)
      • BGP Peer Policy를 사용하는 구형 방식
      • 기능이 제한적이며 현재는 사용을 권장하지 않음
    • BGP 버전 2 (컨트롤 플레인)
      • BGP Control Plane 리소스를 사용하는 신형 방식
      • Cilium의 Custom Resource(CR)를 통해 대부분의 BGP 설정이 가능
      • 실제로는 Go BGP가 동작하여 BGP 데몬 역할을 수행

BGP Control Plane

https://docs.cilium.io/en/stable/network/bgp-control-plane/bgp-control-plane-v2/

Cilium BGP Control Plane은 Border Gateway Protocol(BGP)을 사용하여 Kubernetes 클러스터의 네트워크 라우팅을 외부 네트워크와 연결하는 고급 네트워킹 기능을 제공합니다. 이 시스템은 네 가지 핵심 커스텀 리소스를 통해 BGP 피어링, 정책 및 광고를 관리하며, 확장 가능하고 유연한 BGP 구성을 가능하게 합니다

  • CiliumBGPClusterConfig: 클러스터 내 여러 노드에 적용되는 BGP 인스턴스와 피어 구성을 정의하는 중심적인 리소스입니다. 이 리소스는 nodeSelector 필드를 통해 특정 노드들을 선택하여 BGP 구성을 적용하며, 각 BGP 인스턴스는 고유한 name 필드로 식별됩니다
  • CiliumBGPPeerConfig: BGP 피어의 공통 설정을 정의하는 리소스로, 여러 피어가 동일한 구성을 공유할 수 있도록 설계되었습니다. 이는 대규모 환경에서 구성 관리의 일관성과 효율성을 크게 향상시킵니다.
  • CiliumBGPAdvertisement: BGP 라우팅 테이블에 주입되는 프리픽스를 정의하는 리소스입니다. 이 리소스는 다양한 광고 유형과 관련 속성을 정의하며, CiliumBGPPeerConfig의 families 필드에 정의된 advertisements 라벨 선택기와 매칭됩니다.
  • CiliumBGPNodeConfigOverride: 자동 생성된 구성을 노드별로 오버라이드하여 더욱 세밀한 제어를 제공하는 리소스입니다. 이 리소스를 통해 개별 노드의 특수한 네트워킹 요구사항을 충족할 수 있습니다.

FRR 라우터 구성

FRR 기본 구성

FRR은 여러 라우팅 프로토콜 관련 데몬들을 관리하는 통합 라우팅 소프트웨어입니다. BGP 데몬을 포함하여 OSPF, IS-IS 등 다양한 라우팅 프로토콜을 지원합니다.

BGP AS(Autonomous System) 구성:

  • FRR 라우터: AS 65000
  • Cilium 노드들: AS 65001

AS 65000번대는 Private AS Number로 BGP의 사설 IP 대역과 같은 개념입니다. 공인 AS Number와 달리 편하게 사용할 수 있는 대역입니다.

BGP 네이버 설정

FRR에서 Kubernetes 노드들과 BGP 네이버를 맺기 위해 다음과 같이 설정합니다:

neighbor CILIUM peer-group
neighbor CILIUM remote-as external
neighbor 192.168.10.100 peer-group CILIUM
neighbor 192.168.10.101 peer-group CILIUM
neighbor 192.168.20.100 peer-group CILIUM

external 옵션을 사용하면 자기 자신과 다른 AS라면 모두 네이버로 받아주는 편리성 설정입니다.

Cilium BGP 설정 구성

노드 라벨링

BGP가 동작할 노드를 지정하기 위해 라벨을 설정합니다:

kubectl label nodes k8s-ctr k8s-w0 k8s-w1 enable-bgp=true
kubectl get node -l enable-bgp=true

BGP 클러스터 구성

apiVersion: cilium.io/v2
kind: CiliumBGPClusterConfig
metadata:
  name: cilium-bgp
spec:
  nodeSelector:
    matchLabels:
      "enable-bgp": "true"
  bgpInstances:
  - name: "instance-65001"
    localASN: 65001
    peers:
    - name: "tor-switch"
      peerASN: 65000
      peerAddress: 192.168.10.200  # router ip address
      peerConfigRef:
        name: "cilium-peer"

BGP 피어 구성

apiVersion: cilium.io/v2
kind: CiliumBGPPeerConfig
metadata:
  name: cilium-peer
spec:
  timers:
    holdTimeSeconds: 9
    keepAliveTimeSeconds: 3
  ebgpMultihop: 2
  gracefulRestart:
    enabled: true
    restartTimeSeconds: 15
  families:
    - afi: ipv4
      safi: unicast
      advertisements:
        matchLabels:
          advertise: "bgp"

BGP 광고 구성

Pod CIDR 광고:

apiVersion: cilium.io/v2
kind: CiliumBGPAdvertisement
metadata:
  name: bgp-advertisements
  labels:
    advertise: bgp
spec:
  advertisements:
    - advertisementType: "PodCIDR"

이 설정으로 각 노드는 자신의 Pod CIDR을 BGP로 광고합니다.

중요한 기술적 특징

Cilium BGP의 커널 라우팅 주입 비활성화

Cilium 노드는 BGP 업데이트를 받지만 OS 커널 라우팅에 주입하지 않습니다. 이는 Cilium의 철학적 설계 결정으로, 온프레미스 환경에서 Cilium 서버들은 네트워크 장비 아래에 있고 보통 디폴트 게이트웨이가 ToR 스위치로 설정되기 때문입니다.

예를 들어, 300대의 노드가 있는 클러스터에서 각 노드가 300개의 BGP 노드별 CIDR을 OS 커널 라우팅에 알 필요가 없습니다. 디폴트 게이트웨이인 라우터만 알면 되기 때문입니다.

GoBGP의 설정에서 disable-fib가 설정되어 있어 OS 커널 라우팅에 주입하지 않습니다.

실습 환경에서의 해결책

실습 환경에서는 네트워크 카드가 두 장(eth0, eth1)이 있어서 수동으로 스태틱 라우팅을 추가해야 했습니다:

  • eth0: 인터넷 용
  • eth1: Kubernetes 내부 통신 용

서비스 LoadBalancer External IP BGP 광고

IP Pool 생성

# LB IPAM Announcement over BGP 설정 예정으로, 노드의 네트워크 대역이 아니여도 가능!
cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2"
kind: CiliumLoadBalancerIPPool
metadata:
  name: "cilium-pool"
spec:
  allowFirstLastIPs: "No"
  blocks:
  - cidr: "172.16.1.0/24"
EOF

BGP를 통한 External IP 광고의 장점은 노드와 다른 네트워크 대역을 사용할 수 있다는 것입니다. L2 Announcement와 달리 ARP를 뿌릴 필요가 없어 라우팅으로 처리하기 때문입니다.

서비스 External IP BGP 광고

# LB EX-IP를 BGP로 광고 설정
cat << EOF | kubectl apply -f -
apiVersion: cilium.io/v2
kind: CiliumBGPAdvertisement
metadata:
  name: bgp-advertisements-lb-exip-webpod
  labels:
    advertise: bgp
spec:
  advertisements:
    - advertisementType: "Service"
      service:
        addresses:
          - LoadBalancerIP
      selector:             
        matchExpressions:
          - { key: app, operator: In, values: [ webpod ] }
EOF

ExternalTrafficPolicy 최적화

문제점

기본 externalTrafficPolicy: Cluster 설정에서는 모든 노드가 LoadBalancer IP를 광고하므로 비효율적인 라우팅이 발생할 수 있습니다. 예를 들어, 파드가 없는 노드로 트래픽이 들어와도 BGP 광고가 되어 있어서 그 노드를 거쳐 실제 파드가 있는 노드로 이동하는 비효율적인 경로가 생성됩니다.

해결책: externalTrafficPolicy: Local

spec:
  type: LoadBalancer
  externalTrafficPolicy: Local

externalTrafficPolicy: Local로 설정하면:

  • 파드가 있는 노드만 BGP로 External IP를 광고
  • 파드가 없는 노드는 광고하지 않음
  • 최적 경로로 트래픽 라우팅 보장

ECMP 해시 정책 조정

Linux의 기본 ECMP 해시 정책은 L3 기반(소스/목적지 IP)이므로 동일한 소스와 목적지 간 통신은 항상 같은 경로를 사용합니다.

부하 분산을 위해 L4 포트까지 포함하는 해시 정책으로 변경:

# 리눅스 커널은 기본적으로 L3(목적지 IP 기반) 해시를 사용합니다. 보다 정교한 부하분산을 원하면 L4 해시 (IP + 포트) 기반으로 설정
# 1 : source IP, dest IP, source port, dest port 기반 hash (more granular)로 변경
sudo sysctl -w net.ipv4.fib_multipath_hash_policy=1
echo "net.ipv4.fib_multipath_hash_policy=1" >> /etc/sysctl.conf

# 
for i in {1..100};  do curl -s $LBIP | grep Hostname; done | sort | uniq -c | sort -nr
     59 Hostname: webpod-697b545f57-87lf2
     41 Hostname: webpod-697b545f57-swtdz


# k8s-ctr
kubectl scale deployment webpod --replicas 3
kubectl get pod -owide

# router
ip -c route
for i in {1..100};  do curl -s $LBIP | grep Hostname; done | sort | uniq -c | sort -nr

 

노드 유지보수 시나리오

BGP 노드 제외

유지보수를 위해 특정 노드에서 BGP를 비활성화:

# 모니터링 : 반복 호출
kubectl exec -it curl-pod -- sh -c 'while true; do curl -s --connect-timeout 1 webpod | grep Hostname; echo "---" ; sleep 1; done'

# (참고) BGP Control Plane logs
kubectl logs -n kube-system -l name=cilium-operator -f | grep "subsys=bgp-cp-operator"
kubectl logs -n kube-system -l k8s-app=cilium -f | grep "subsys=bgp-control-plane"


# 유지보수를 위한 설정
kubectl drain k8s-w0 --ignore-daemonsets
kubectl label nodes k8s-w0 enable-bgp=false --overwrite

 

  1. 해당 노드는 BGP 네이버에서 제외
  2. 라우팅 정보에서 해당 노드의 Pod CIDR 제거
  3. 트래픽이 다른 노드로 자동 라우팅

유지보수 완료 후 복구

kubectl label node worker-0 enable-bgp=true
kubectl uncordon worker-0

BGP Status 리포팅 비활성화

대규모 환경에서는 BGP 상태 리포팅이 API 서버에 부하를 줄 수 있으므로 비활성화를 권장합니다:

# 확인
kubectl get ciliumbgpnodeconfigs -o yaml | yq

# 설정
helm upgrade cilium cilium/cilium --version 1.18.0 --namespace kube-system --reuse-values \
  --set bgpControlPlane.statusReport.enabled=false

kubectl -n kube-system rollout restart ds/cilium


# 확인 : CiliumBGPNodeConfig Status 정보가 없다!
kubectl get ciliumbgpnodeconfigs -o yaml | yq
...
      "status": {}

외부 인입 트래픽 처리 방식 비교

권장 방식: BGP(ECMP) + Service(LB EX-IP, ExternalTrafficPolicy:Local) + SNAT + Random

설정 구성:

  • BGP와 ECMP(Equal Cost Multi-Path) 활용
  • LoadBalancer External IP 사용
  • externalTrafficPolicy: Local 설정
  • macLB(Metal LB) 사용 불필요
  • SNAT 활용
  • 기본 랜덤 부하 분산

트래픽 경로:
파드가 있는 노드로 직접 들어와서 바로 나가는 가장 효율적인 경로를 제공합니다.

비권장 방식: BGP(ECMP) + Service(LB EX-IP, ExternalTrafficPolicy:Cluster) + SNAT

문제점:
externalTrafficPolicy: Cluster 설정 시 다음과 같은 비효율적인 라우팅이 발생합니다:

  1. 외부에서 특정 노드로 트래픽 진입
  2. 해당 노드에 파드가 없어도 다른 노드의 파드로 라우팅 가능
  3. SNAT로 인해 원본 클라이언트 IP 손실
  4. 응답 트래픽이 진입 노드를 거쳐 다시 경유하는 비효율적 경로 생성

DSR(Direct Server Return) 방식

DSR은 원래 네트워크에서 비싼 L4 로드밸런서 장비의 성능을 절약하기 위해 개발된 개념입니다. 핵심 특징:

DSR의 동작 원리:

  1. 인입 경로: 클라이언트 → 로드밸런서 → 서버
  2. 응답 경로: 서버 → 라우터 → 클라이언트 (로드밸런서 경유 없음)

이러한 비대칭 경로를 통해 로드밸런서의 부하를 줄이고 응답 성능을 향상시킵니다.

Cilium DSR with Geneve 구현

DSR Geneve 캡슐화 메커니즘

Cilium의 DSR은 Geneve 헤더를 활용한 특별한 구현을 제공합니다:

설정 방법:

loadBalancer:
  mode: dsr
  dsrDispatch: geneve
tunnelProtocol: geneve

동작 과정:

  1. 요청 단계: 노드 간 전달 시 Geneve 헤더에 최초 접근 정보(클라이언트 IP/포트) 포함
  2. 응답 단계: 대상 파드가 Geneve 헤더 정보를 활용해 원본 클라이언트로 직접 응답
  3. 경로 최적화: 중간 노드를 경유하지 않고 직접 응답하여 hop 수 감소

Geneve 헤더 구조

DSR 구간에서만 사용되는 Geneve 캡슐화는 다음 정보를 포함합니다:

  • 최초 클라이언트 접근 IP
  • 최초 클라이언트 접근 포트
  • 서비스 VIP 정보

오버헤드:
Geneve 헤더 추가로 인한 패킷 크기 증가가 발생하며, 이는 BGP + ECMP + Local 방식보다 성능상 불리할 수 있습니다.

백엔드 선택 알고리즘

Random에서 Maglev로 변경

DSR 모드 활성화 시 백엔드 선택 알고리즘이 자동으로 변경됩니다:

  • 기본 모드: Random 알고리즘
  • DSR 모드: Maglev 알고리즘

Maglev의 장점:

  • 연결 지속성 보장
  • 복잡한 경로에서의 세션 유지 개선
  • DSR의 비대칭 라우팅 환경에서 더 안정적인 연결 관리

패킷 캡쳐를 통한 DSR 동작 확인

실제 패킷 분석

요청 패킷:

  • 소스 IP: 라우터(10.200.xxx)
  • 목적지 IP: 워커노드
  • Geneve 헤더에 원본 클라이언트 정보 포함

응답 패킷:

  • 소스 IP: LoadBalancer VIP (172.16.1.1)
  • 목적지 IP/포트: 원본 클라이언트 정보
  • 중간 노드 경유 없이 직접 응답

고급 BGP 설정

다중 서비스 BGP 광고

노드 그룹별 서비스 분산:

# 서비스1: 렉1 노드 그룹에 분산
nodeSelector:
  matchLabels:
    rack: "rack1"

# 서비스2: 렉2 노드 그룹에 분산  
nodeSelector:
  matchLabels:
    rack: "rack2"

BGP Advertisement 통합:
하나의 CiliumBGPAdvertisement CR로 여러 타입 동시 광고 가능:

advertisements:
- advertisementType: "PodCIDR"
- advertisementType: "Service"
  service:
    addresses:
    - LoadBalancerIP
    selector:
      matchLabels:
        app: "service1"

BGP Listen Ranges (고급 기능)

문제 상황:

  • 대규모 클러스터(300-400노드)에서 개별 노드 IP를 수동으로 설정하는 비효율성
  • 네트워크 엔지니어와 Cilium 엔지니어 모두의 작업 부담

해결책: BGP Listen Ranges

# FRR/Cisco 라우터 설정
bgp listen range 192.168.0.0/16 peer-group cilium-nodes

장점:

  • 네트워크 엔지니어: 개별 노드 IP 입력 불필요
  • Cilium 엔지니어: 라우터 IP 개별 입력 불필요
  • 자동 peer 설정으로 관리 복잡성 대폭 감소

이 기능은 약 한 달 전에 출시된 따끈따끈한 기능으로, 온프레미스 환경에서의 Cilium BGP 연동 사례가 계속 증가할 것으로 예상됩니다.

ClusterIP BGP 광고 (참고사항)

기술적으로는 가능하지만 실용성이 낮은 기능입니다:

사용 방법:

advertisementType: "Service"
service:
  addresses:
  - ClusterIP

비권장 이유:

  • 외부에서 ClusterIP로 직접 접근하는 케이스가 매우 제한적
  • LoadBalancer IP를 통한 외부 노출이 일반적으로 더 적절한 방식

internalTrafficPolicy 설정

internalTrafficPolicy: Local도 존재하지만 필요성이 낮습니다:

  • 용도: Kubernetes 클러스터 내부에서 서비스 접근 시의 라우팅 정책
  • 현실적 필요성: 클러스터 내부 통신에서는 일반적으로 불필요

BGP 보안 강화

MD5 Password 설정

실제 환경에서 BGP 네이버 해킹을 통한 트래픽 우회 공격을 방지하기 위해 MD5 패스워드 설정이 권장됩니다:

# CiliumBGPPeerConfig
spec:
  authSecretRef: "bgp-auth-secret"

 

댓글