Kubernetes BGP 완벽 가이드: 언제, 왜, 어떻게?

문한성·2025년 10월 27일
0

🤔 "클러스터 내부는 CNI가 알아서 하는데, BGP는 왜 필요하죠?"

Kubernetes CNI와 BGP의 경계를 명확히 이해하고, 실전에서 BGP가 필요한 순간을 알아봅시다.

목차

  1. BGP란 무엇인가?
  2. CNI vs BGP: 역할 구분
  3. BGP가 필요한 순간
  4. BGP 설정 완전 분석
  5. 실전 시나리오
  6. 라우터와 스위치
  7. AS Number 관리
  8. 장애 대응
  9. FAQ

BGP란 무엇인가?

BGP (Border Gateway Protocol)

BGP는 인터넷의 백본을 구성하는 라우팅 프로토콜입니다. 서로 다른 네트워크(Autonomous System) 간에 "어떤 IP 주소가 어디에 있는지" 정보를 교환합니다.

🏢 현실 세계 비유

우편 시스템:
  - 서울 우체국: "06xxx 우편번호는 우리가 관리해요!"
  - 부산 우체국: "48xxx 우편번호는 우리가 관리해요!"
  
BGP:
  - 네이버 네트워크: "210.89.160.0/24 IP는 우리 네트워크예요!"
  - 카카오 네트워크: "211.249.220.0/24 IP는 우리 네트워크예요!"

🌐 인터넷에서의 BGP

사용자가 www.google.com 접속 시:

1. 사용자 ISP: "142.250.x.x는 어디로 보내지?"
2. BGP 조회: "Google AS (15169)로 보내!"
3. 최적 경로 선택: SKT → 해외 회선 → Google
4. 페이지 로딩 완료

CNI vs BGP: 역할 구분

🎯 핵심 차이점

구분CNIBGP
범위클러스터 내부클러스터 외부
역할Pod 간 네트워킹네트워크 간 라우팅
필요성항상 필수특수한 경우만
설정 주체DevOpsDevOps + 네트워크팀

CNI의 역할 (클러스터 내부)

┌─────────────────────────────────────┐
│     Kubernetes Cluster              │
│                                     │
│  Pod A (10.244.1.5)                │
│     ↓                              │
│  CNI가 자동 라우팅                  │
│     ↓                              │
│  Pod B (10.244.2.10)               │
│                                     │
│  ✅ BGP 불필요!                     │
└─────────────────────────────────────┘

CNI가 자동으로 처리하는 것:

  • Pod IP 할당
  • 노드 간 라우팅
  • 네트워크 정책 (Calico의 경우)
  • Service 네트워킹

BGP의 역할 (클러스터 외부)

┌─────────────────────┐      ┌─────────────────────┐
│  K8s Cluster A      │      │  K8s Cluster B      │
│  (서울)             │      │  (도쿄)             │
│  10.244.0.0/16      │      │  10.245.0.0/16      │
└──────────┬──────────┘      └──────────┬──────────┘
           │                            │
           └────────┬───────────────────┘
                    │ BGP 필요!
           ┌────────▼────────┐
           │  Global Router  │
           │  "경로 알려줘!" │
           └─────────────────┘

BGP가 필요한 이유:

  • 서로 다른 네트워크 연결
  • 경로 정보 교환
  • 자동 장애 대응
  • 최적 경로 선택

BGP가 필요한 순간

✅ Case 1: 멀티 클러스터

상황

서울 클러스터:
  - Pod CIDR: 10.244.0.0/16
  - Service CIDR: 10.96.0.0/12

도쿄 클러스터:
  - Pod CIDR: 10.245.0.0/16
  - Service CIDR: 10.97.0.0/12

문제

// 서울 클러스터의 Pod에서
const response = await axios.post(
  'http://10.245.1.50:8080/api',  // 도쿄 클러스터 Pod IP
  data
);

// ❌ Error: Network unreachable
// 왜? 서울 클러스터는 10.245.x.x가 어디 있는지 몰라!

해결: BGP 설정

서울 클러스터:

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64512  # 서울 클러스터 AS

---
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: to-tokyo-cluster
spec:
  peerIP: 203.0.113.1  # 도쿄 클러스터 게이트웨이
  asNumber: 64513      # 도쿄 클러스터 AS

도쿄 클러스터:

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64513  # 도쿄 클러스터 AS

---
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: to-seoul-cluster
spec:
  peerIP: 203.0.113.2  # 서울 클러스터 게이트웨이
  asNumber: 64512      # 서울 클러스터 AS

동작 흐름

1. 서울 Calico: "10.244.0.0/16은 우리 거야!" (BGP 광고)
2. 도쿄 Calico: "10.245.0.0/16은 우리 거야!" (BGP 광고)
3. 라우터들이 학습: 
   - "10.244.x.x → 서울로"
   - "10.245.x.x → 도쿄로"
4. ✅ 서울 ↔ 도쿄 Pod 간 직접 통신 가능!

✅ Case 2: 온프레미스 통합

상황

Kubernetes Cluster: 10.244.0.0/16 (AWS)
온프레미스 데이터센터: 192.168.0.0/16
  - 레거시 ERP: 192.168.100.50
  - 은행 연동 시스템: 192.168.200.30
  - Oracle DB: 192.168.150.10

문제

# Kubernetes Pod에서 온프레미스 DB 접근
import cx_Oracle

# ❌ 연결 실패!
connection = cx_Oracle.connect(
    'user/password@192.168.150.10:1521/ORCL'
)

# 왜? 
# 1. Pod → 192.168.150.10 경로를 몰라
# 2. 온프레미스 → 10.244.x.x 응답 경로를 몰라

해결: BGP + Direct Connect

AWS 측 설정:

# Terraform
resource "aws_vpn_gateway" "main" {
  vpc_id          = aws_vpc.main.id
  amazon_side_asn = 64512  # AWS 측 AS
}

resource "aws_customer_gateway" "onprem" {
  bgp_asn    = 65000  # 온프레미스 AS
  ip_address = "203.0.113.100"  # 온프레미스 공인 IP
  type       = "ipsec.1"
}

resource "aws_vpn_connection" "main" {
  vpn_gateway_id      = aws_vpn_gateway.main.id
  customer_gateway_id = aws_customer_gateway.onprem.id
  type                = "ipsec.1"
  static_routes_only  = false  # BGP 사용
}

Calico 설정:

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64513  # Kubernetes AS (AWS와 다름!)

---
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: aws-vpn-gateway
spec:
  peerIP: 10.0.0.1  # VPN Gateway 내부 IP
  asNumber: 64512   # AWS VGW AS

온프레미스 라우터 설정:

router bgp 65000
  neighbor 203.0.113.100 remote-as 64512
  network 192.168.0.0 mask 255.255.0.0
  
  ! Kubernetes Pod IP 학습
  neighbor 203.0.113.100 route-map ACCEPT-K8S in

동작 흐름

Pod (10.244.1.5) → Oracle DB (192.168.150.10)

1. Pod: "192.168.150.10으로 가고 싶어"
2. Calico: "BGP 테이블 확인... VPN Gateway로!"
3. VPN Gateway → Direct Connect
4. 온프레미스 라우터: "192.168.150.10은 내부 네트워크"
5. ✅ DB 도달

응답:
DB (192.168.150.10) → Pod (10.244.1.5)

1. 온프레미스 라우터: "10.244.1.5? BGP 테이블 확인..."
2. "아, AWS VPN으로 보내면 되겠네"
3. VPN → AWS VGW → Calico
4. ✅ Pod 도달

✅ Case 3: 데이터센터의 ToR Switch 연동

상황

온프레미스 데이터센터 구조:

┌────────────────────────────────┐
│  Core Router (192.168.0.1)    │
│  AS 65000                      │
└────────┬───────────────────────┘
         │
    ┌────┴────┬────────┐
    │         │        │
┌───▼───┐ ┌──▼───┐ ┌──▼───┐
│ToR-1  │ │ToR-2 │ │ToR-3 │
│.1.1   │ │.1.2  │ │.1.3  │
│AS     │ │AS    │ │AS    │
│65001  │ │65001 │ │65001 │
└───┬───┘ └──┬───┘ └──┬───┘
    │        │        │
  [노드]   [노드]   [노드]

왜 BGP가 필요한가?

BGP 없이 (VXLAN Overlay):

문제점:
1. 모든 트래픽이 캡슐화됨 (Overhead 증가)
2. ToR Switch가 Pod IP를 몰라 → 비효율적 라우팅
3. 물리 네트워크의 성능을 100% 활용 못 함

예시:
  Pod A → Pod B (같은 랙)
  실제 거리: 1 홉
  VXLAN: 3 홉 (캡슐화/복호화 오버헤드)

BGP 사용 (Native Routing):

장점:
1. 캡슐화 없음 → 오버헤드 제거
2. ToR Switch가 Pod IP 인지 → 최적 경로
3. 물리 네트워크 성능 100% 활용

예시:
  Pod A → Pod B (같은 랙)
  실제 거리: 1 홉
  BGP: 1 홉 (직접 전송)

BGP 설정

ToR Switch 1:

router bgp 65001
  neighbor 192.168.1.10 remote-as 64512  # K8s Node 1
  neighbor 192.168.1.11 remote-as 64512  # K8s Node 2
  
  ! Pod IP 학습
  address-family ipv4
    neighbor 192.168.1.10 activate
    neighbor 192.168.1.11 activate

Calico (모든 노드):

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64512
  nodeToNodeMeshEnabled: false  # Node Mesh 비활성화
  
---
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: tor-switch-1
spec:
  peerIP: 192.168.1.1
  asNumber: 65001

성능 비교

벤치마크 (10Gbps 네트워크):

VXLAN Overlay:
  처리량: 8.2 Gbps (18% 오버헤드)
  레이턴시: 0.8ms
  CPU 사용률: 25%

BGP Native Routing:
  처리량: 9.7 Gbps (3% 오버헤드)
  레이턴시: 0.3ms
  CPU 사용률: 8%

결과: BGP가 3배 효율적!

✅ Case 4: 외부 로드밸런서 직접 연동

상황

요구사항:
- F5 하드웨어 로드밸런서 (물리 장비)
- Pod IP로 직접 트래픽 전송 (Service 거치지 않음)
- DSR (Direct Server Return) 구현

왜 필요한가?

일반적인 방법 (NodePort/LoadBalancer):

사용자 → F5 → NodePort (30080)
       → kube-proxy NAT
       → Pod

문제:
1. kube-proxy 병목
2. NAT 오버헤드
3. Source IP 손실
4. 높은 레이턴시

BGP 방법:

사용자 → F5 → Pod IP 직접!

장점:
1. kube-proxy 우회
2. NAT 없음
3. Source IP 보존
4. 낮은 레이턴시

설정

Calico:

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: f5-load-balancer
spec:
  peerIP: 192.168.10.100  # F5 IP
  asNumber: 65100

---
# 특정 Service의 Pod IP만 광고
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  serviceExternalIPs:
    - cidr: 10.244.0.0/16  # Pod CIDR

F5 설정:

ltm pool k8s-payment-pool {
  members {
    10.244.1.50:8080 { }  # Pod IP 직접 사용!
    10.244.2.30:8080 { }
    10.244.3.80:8080 { }
  }
  monitor tcp
}

동작

1. Calico가 BGP로 광고:
   "10.244.1.50은 192.168.1.10 (노드)에 있어요"
   
2. F5가 학습:
   "10.244.1.50으로 가려면 192.168.1.10으로 보내면 되겠네"
   
3. 트래픽:
   사용자 → F5 → 192.168.1.10 → Pod (10.244.1.50)
   
4. 응답 (DSR):
   Pod → 사용자 (직접! F5 거치지 않음)
   
결과: 초고속 처리!

BGP 설정 완전 분석

YAML 각 필드 상세 설명

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: rack-tor-switch
spec:
  peerIP: 192.168.1.1
  asNumber: 64512

1. apiVersion: projectcalico.org/v3

의미:

  • Calico API v3 사용 선언
  • Kubernetes CRD (Custom Resource Definition)

버전 히스토리:

  • v1: 초기 버전 (deprecated)
  • v3: 현재 안정 버전 (권장)

2. kind: BGPPeer

의미:

  • 생성할 리소스 타입: BGP Peer
  • 외부 BGP 라우터와의 연결 정의

Calico의 다른 kinds:

BGPPeer           # 외부 BGP 라우터 연결
BGPConfiguration  # BGP 전역 설정
NetworkPolicy     # 네트워크 보안 정책
IPPool            # IP 주소 풀
FelixConfiguration # Felix 데몬 설정

3. metadata.name: rack-tor-switch

의미:

  • BGP Peer 리소스의 고유 식별자
  • 클러스터 내에서 유일해야 함

네이밍 컨벤션:

# 위치 기반
name: rack1-tor-switch
name: datacenter-seoul-tor1

# 기능 기반
name: production-bgp-peer
name: edge-router-primary

# 조합
name: seoul-dc-rack1-tor1

실제 데이터센터 용어:

  • rack: 서버 랙 (서버들이 꽂혀있는 선반)
  • tor: Top of Rack (랙 맨 위의 스위치)
  • switch: 네트워크 스위치
데이터센터 구조:

┌─────────────────┐
│  Core Router    │
└────────┬────────┘
         │
    ┌────▼────┐
    │ToR Switch│ ← 여기!
    │(랙 상단) │
    └────┬────┘
         │
    ┌────┴────┐
    │Server 1 │
    │Server 2 │
    │Server 3 │
    └─────────┘

4. spec.peerIP: 192.168.1.1

의미:

  • 연결할 외부 BGP 라우터의 IP 주소
  • Calico 노드들이 이 IP로 BGP 연결 시도

선택 기준:

✅ 모든 Kubernetes 노드에서 접근 가능한 IP
✅ 일반적으로 관리 네트워크의 IP
✅ 물리 라우터/스위치의 관리 인터페이스 IP
❌ NAT 뒤의 IP는 피할 것
❌ DHCP로 변경될 수 있는 IP 피할 것

실제 환경 예시:

# 온프레미스
peerIP: 192.168.1.1  # ToR Switch 관리 IP

# AWS
peerIP: 10.0.0.1  # Virtual Private Gateway

# GCP
peerIP: 10.1.0.1  # Cloud Router

5. spec.asNumber: 64512

의미:

  • Peer (상대방 라우터)의 AS Number
  • BGP에서 네트워크를 구분하는 고유 번호

AS Number 범위:

1 - 64511:           공인 AS (Public)
                     예: Google(15169), Amazon(16509)
                     
64512 - 65534:       사설 AS (Private) ← 대부분 여기 사용
                     내부 네트워크용, 인터넷 광고 안 됨
                     
4200000000 - 4294967294: 4바이트 사설 AS
                          대규모 조직용

왜 64512를 많이 사용하나?

  • 사설 AS 범위의 시작 번호
  • RFC 6996에서 정의된 표준
  • 많은 문서와 예제에서 사용

추가 설정 옵션

nodeSelector로 특정 노드만 연결

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: payment-nodes-tor
spec:
  peerIP: 192.168.1.1
  asNumber: 64512
  nodeSelector: "service == 'payment'"  # 결제 노드만
# 노드 레이블 설정
kubectl label node worker-1 service=payment
kubectl label node worker-2 service=payment

다중 BGP Peer (고가용성)

# Primary
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: tor-switch-primary
spec:
  peerIP: 192.168.1.1
  asNumber: 64512

---
# Backup
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: tor-switch-backup
spec:
  peerIP: 192.168.1.2
  asNumber: 64512

동작:

정상: 모든 노드가 2개 스위치와 BGP 세션
Switch 1 장애: 자동으로 Switch 2만 사용
Switch 1 복구: 다시 2개 모두 사용

라우터와 스위치

기본 개념

스위치 (Switch)

역할: 같은 네트워크 내 연결
계층: L2 (데이터 링크)
주소: MAC 주소 사용
범위: 로컬 네트워크

예시:
  컴퓨터 A → 스위치 → 컴퓨터 B
  (같은 사무실 내)

라우터 (Router)

역할: 다른 네트워크 간 연결
계층: L3 (네트워크)
주소: IP 주소 사용
범위: 인터넷, WAN

예시:
  회사 네트워크 → 라우터 → 인터넷

L3 스위치 (Layer 3 Switch)

역할: 스위칭 + 라우팅
계층: L2 + L3
기능: 스위치처럼 빠르고, 라우터처럼 똑똑함

데이터센터의 ToR Switch는 보통 L3 스위치!
→ BGP 사용 가능

스위치 2개 설정 예시

환경

Kubernetes 클러스터
  Node 1: 192.168.1.10
  Node 2: 192.168.1.11
  Node 3: 192.168.1.12

ToR Switch 1: 192.168.1.1 (AS 64512)
ToR Switch 2: 192.168.1.2 (AS 64512) ← 이중화

BGP 설정

# 첫 번째 스위치
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: tor-switch-1
spec:
  peerIP: 192.168.1.1
  asNumber: 64512

---
# 두 번째 스위치
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: tor-switch-2
spec:
  peerIP: 192.168.1.2
  asNumber: 64512

네트워크 구조

        [인터넷]
           |
    [Core Router]
           |
     ┌─────┴─────┐
     |           |
[ToR Switch 1]  [ToR Switch 2]
192.168.1.1     192.168.1.2
AS 64512        AS 64512
     |               |
     |   이중 연결   |
     └───────┬───────┘
             |
    ┌────────┼────────┐
    |        |        |
  Node1    Node2    Node3
  .1.10    .1.11    .1.12
  
각 Node는 Switch 1, 2 모두와 BGP 세션

검증

# BGP Peer 확인
$ calicoctl get bgppeer

NAME            PEERIP         NODE   ASN
tor-switch-1   192.168.1.1    (all)  64512
tor-switch-2   192.168.1.2    (all)  64512

# BGP 세션 상태
$ calicoctl node status

IPv4 BGP status
+--------------+-------+----------+-------------+
| PEER ADDRESS | STATE |  SINCE   |    INFO     |
+--------------+-------+----------+-------------+
| 192.168.1.1  | up    | 10:52:33 | Established |
| 192.168.1.2  | up    | 10:52:35 | Established |
+--------------+-------+----------+-------------+

# 2개 모두 "Established" = 정상!

AS Number 관리

AS Number는 어디서 설정?

양쪽 모두 설정 필요!

1. 라우터/스위치 측 (네트워크팀)

# Cisco 라우터
router bgp 64512
  bgp router-id 192.168.1.1
  neighbor 192.168.1.10 remote-as 64513  # K8s 노드
  neighbor 192.168.1.11 remote-as 64513
  
# "나는 AS 64512이고, 상대방은 AS 64513이야"

2. Kubernetes/Calico 측 (DevOps팀)

# 우리 클러스터 AS
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64513  # "우리는 AS 64513"
  
---
# Peer 정보
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: tor-switch
spec:
  peerIP: 192.168.1.1
  asNumber: 64512  # "상대방은 AS 64512"

설정 순서

1단계: 네트워크 설계 회의
   "온프레미스는 AS 65000"
   "AWS 서울은 AS 64512"
   "K8s 서울은 AS 64514"

2단계: 네트워크팀이 라우터 설정
   router bgp 64512
   neighbor x.x.x.x remote-as 64514

3단계: DevOps팀이 Calico 설정
   asNumber: 64514 (우리)
   peerIP: x.x.x.x
   asNumber: 64512 (상대방)

AS Number 충돌 방지

❌ 잘못된 예시

라우터: AS 64512
Calico: AS 64512  ← 같으면 안 됨!

문제:
- iBGP (Internal BGP)로 동작
- 라우팅 루프 방지로 경로 광고 안 됨
- 연결은 되지만 라우팅 안 됨

✅ 올바른 예시

라우터: AS 64512
Calico: AS 64513  ← 다른 AS

결과:
- eBGP (External BGP)로 동작
- 정상적으로 라우팅 정보 교환

AS Number 할당 전략

예시 1: 용도별

65000: 온프레미스 데이터센터
65001: AWS 서울 VPC
65002: AWS 도쿄 VPC
65010: K8s 서울 프로덕션
65011: K8s 도쿄 DR
65020: K8s 개발 환경

예시 2: 계층별

64512: 코어 라우터
64520-64529: ToR Switch
64530-64539: Kubernetes 클러스터
64540-64549: 개발/테스트

예시 3: 리전별

65001: 서울 (SEL)
  65001: 인프라
  65011: K8s 프로덕션
  65021: K8s 개발

65002: 도쿄 (TYO)
  65002: 인프라
  65012: K8s 프로덕션
  65022: K8s 개발

장애 대응

자동 장애 대응 (기본)

# 이것만으로도 자동 장애 대응!
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: switch-1
spec:
  peerIP: 192.168.1.1
  asNumber: 64512
---
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: switch-2
spec:
  peerIP: 192.168.1.2
  asNumber: 64512

동작:

정상:
  Node → Switch 1 (Active)
  Node → Switch 2 (Standby)
  
Switch 1 장애:
  10초 후 자동 감지
  → Switch 2로 전환
  
Switch 1 복구:
  자동으로 원래대로

우선순위 설정

라우터 측 (Weight)

# Primary 라우터
router bgp 64512
  neighbor 192.168.1.10 remote-as 64513
  neighbor 192.168.1.10 weight 100  # 높은 우선순위

# Backup 라우터
router bgp 64512
  neighbor 192.168.1.10 remote-as 64513
  neighbor 192.168.1.10 weight 50   # 낮은 우선순위

라우터 측 (AS Path Prepend)

# Primary: 짧은 경로
router bgp 64512
  neighbor 192.168.1.10 route-map PRIMARY in
  
route-map PRIMARY permit 10
  set as-path prepend 64512  # AS Path: 64512

# Backup: 긴 경로 (우선순위 낮음)
router bgp 64512
  neighbor 192.168.1.10 route-map BACKUP in
  
route-map BACKUP permit 10
  set as-path prepend 64512 64512 64512  # AS Path: 64512 64512 64512

빠른 장애 감지 (BFD)

기본 BGP: 30-90초 감지

# 기본 설정
keepAliveTime: 30s
holdTime: 90s

# → 최대 90초 후 장애 감지

BFD 사용: 1초 이내 감지

# 라우터 설정
interface GigabitEthernet0/0
  bfd interval 200 min_rx 200 multiplier 3
  # 200ms * 3 = 600ms 후 장애 감지

router bgp 64512
  neighbor 192.168.1.10 remote-as 64513
  neighbor 192.168.1.10 fall-over bfd

멀티 리전 DR 시나리오

환경 설정

# 서울 리전 (Primary)
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64512

---
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: global-router
spec:
  peerIP: 203.0.113.1
  asNumber: 64500

---
# 도쿄 리전 (DR)
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64513

---
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: global-router
spec:
  peerIP: 203.0.113.1
  asNumber: 64500

장애 시나리오

정상 시:
  사용자 → 서울 (AS Path 짧음)
  
서울 장애:
  1. 서울 BGP 광고 중단 (30초)
  2. 라우터가 서울 경로 제거
  3. 도쿄 경로만 남음
  4. 모든 트래픽 → 도쿄 (자동!)
  
서울 복구:
  1. 서울 BGP 광고 재개
  2. 라우터가 경로 추가
  3. AS Path 비교 (서울이 짧음)
  4. 다시 서울 우선 사용

실전 시나리오

시나리오 1: 스타트업 → 유니콘 성장

Phase 1: MVP (Flannel, BGP 없음)

상황:
- 시드 투자 직후, 팀 10명
- AWS 서울 단일 리전
- 10 노드 클러스터

선택: Flannel
이유: 빠른 구축, 운영 단순화

BGP: 불필요

Phase 2: 성장기 (Flannel 유지)

상황:
- 시리즈 A, 팀 50명, MAU 10만
- 여전히 단일 리전
- 30 노드로 확장

선택: Flannel 계속 사용
이유: 충분한 성능, 안정적

BGP: 여전히 불필요

Phase 3: 스케일업 (Calico + BGP)

상황:
- 시리즈 B, 팀 200명, MAU 100만
- 멀티 리전 필요 (서울 + 도쿄)
- 리전당 100+ 노드

트리거:
✓ 엔터프라이즈 고객 요구 (네트워크 격리)
✓ SOC2 인증 필요
✓ 글로벌 확장
✓ 온프레미스 레거시 연동

선택: Calico + BGP

BGP 설정:

# 서울 클러스터
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64512
  nodeToNodeMeshEnabled: false

---
# AWS 서울 VGW 연결
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: aws-seoul-vgw
spec:
  peerIP: 10.0.0.1
  asNumber: 64500

---
# 도쿄 클러스터 연결
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: tokyo-dr
spec:
  peerIP: 203.0.113.2
  asNumber: 64513

---
# 온프레미스 연결
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: onprem-dc
spec:
  peerIP: 192.168.1.1
  asNumber: 65000

Phase 4: 엔터프라이즈

상황:
- 시리즈 C+, 팀 500명, MAU 500만+
- 글로벌 10개 리전
- 리전당 200+ 노드

BGP 사용:
✓ 멀티 리전 자동 장애 전환
✓ 온프레미스 통합 (레거시 시스템)
✓ 하이브리드 클라우드 (AWS + GCP + 온프레미스)
✓ 고성능 라우팅 (eBPF + BGP)

시나리오 2: 금융 서비스 (토스/카카오뱅크)

요구사항

규제:
✓ 금융 데이터는 국내에만
✓ PCI-DSS 준수
✓ 모든 트래픽 암호화
✓ 네트워크 감사 추적

기술:
✓ 온프레미스 은행 연동
✓ 초저 레이턴시 (<5ms)
✓ 99.99% 가용성
✓ 멀티 리전 DR

BGP 아키텍처

# 1. 온프레미스 은행 연동
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: bank-mainframe
spec:
  peerIP: 192.168.1.1  # 은행 연동 라우터
  asNumber: 65000
  nodeSelector: "service == 'payment'"  # 결제 노드만

---
# 2. AWS 서울 (Primary)
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: aws-seoul-primary
spec:
  peerIP: 10.0.0.1
  asNumber: 64512

---
# 3. AWS 서울 (Backup)
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: aws-seoul-backup
spec:
  peerIP: 10.0.0.2
  asNumber: 64512

---
# 4. AWS 부산 DR
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: aws-busan-dr
spec:
  peerIP: 10.1.0.1
  asNumber: 64513

네트워크 정책 + BGP

# BGP로 라우팅 + NetworkPolicy로 보안
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: payment-isolation
spec:
  selector: app == 'payment'
  ingress:
    - action: Allow
      protocol: TCP
      source:
        selector: app == 'api-gateway'
      destination:
        ports: [8080]
  egress:
    - action: Allow
      protocol: TCP
      destination:
        nets:
          - 192.168.100.0/24  # 은행 시스템만
        ports: [3000]

시나리오 3: 글로벌 게임 회사

요구사항

성능:
✓ 초저 레이턴시 (<2ms)
✓ 초당 100만+ 패킷
✓ DDoS 방어

가용성:
✓ 99.99% 가동률
✓ 자동 리전 전환
✓ 글로벌 Anycast

BGP + eBPF 조합

# eBPF 활성화
apiVersion: projectcalico.org/v3
kind: FelixConfiguration
metadata:
  name: default
spec:
  bpfEnabled: true
  bpfLogLevel: Info

---
# BGP Configuration
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64520
  
---
# 서울 리전
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: seoul-edge
spec:
  peerIP: 203.0.113.1
  asNumber: 64500

---
# 도쿄 리전
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: tokyo-edge
spec:
  peerIP: 103.0.113.1
  asNumber: 64501

---
# 싱가포르 리전
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: singapore-edge
spec:
  peerIP: 123.0.113.1
  asNumber: 64502

Anycast 구현

같은 Service IP를 모든 리전에서 광고:

서울: "1.2.3.4는 우리한테 있어요!" (BGP 광고)
도쿄: "1.2.3.4는 우리한테 있어요!" (BGP 광고)
싱가포르: "1.2.3.4는 우리한테 있어요!" (BGP 광고)

결과:
- 한국 플레이어 → 자동으로 서울 리전
- 일본 플레이어 → 자동으로 도쿄 리전
- 동남아 플레이어 → 자동으로 싱가포르 리전

서울 장애 시:
- 한국 플레이어도 자동으로 도쿄로 전환

FAQ

Q1: BGP 없이도 Kubernetes가 잘 동작하는데?

A: 맞습니다! 대부분의 경우 BGP 불필요합니다.

BGP 불필요 (90%):
✓ 단일 클러스터
✓ Service를 통한 Pod 접근
✓ Ingress 사용
✓ 같은 클러스터 내 통신

BGP 필요 (10%):
✓ 멀티 클러스터
✓ 온프레미스 통합
✓ 물리 네트워크 직접 연동
✓ 외부에서 Pod IP 직접 접근

Q2: Flannel에서 Calico로 마이그레이션 시 다운타임은?

A: 방법에 따라 다릅니다.

단일 클러스터 교체:
- 다운타임: 10-30분
- Pod 전체 재시작 필요

Blue-Green 방식:
- 다운타임: 0분
- 새 클러스터 구축 후 전환

Rolling Update:
- 다운타임: 노드당 2-5분
- 노드를 하나씩 전환

Q3: AS Number는 누가 정하나요?

A: 네트워크팀과 협의하여 결정합니다.

절차:
1. 네트워크팀과 회의
   "우리 온프레미스는 AS 65000 사용 중"
   
2. 네트워크팀이 AS 할당
   "K8s 서울은 AS 64512 써주세요"
   
3. DevOps팀이 Calico 설정
   asNumber: 64512

주의: 임의로 변경하면 안 됨!

Q4: BGP 세션이 Established 안 되면?

A: 체크리스트:

# 1. 핑 테스트
ping 192.168.1.1

# 2. BGP 포트 확인 (TCP 179)
telnet 192.168.1.1 179

# 3. 방화벽 확인
# AWS: Security Group에서 TCP 179 허용
# 온프레미스: 방화벽 규칙 확인

# 4. AS Number 확인
# 라우터와 Calico 설정이 서로 일치하는지

# 5. 라우터 설정 확인
# 네트워크팀에게 라우터 로그 요청

Q5: eBPF와 BGP는 같이 써야 하나요?

A: 아닙니다. 독립적입니다.

eBPF: 패킷 처리 성능 향상 (커널 레벨)
BGP: 네트워크 간 라우팅 정보 교환

조합:
✓ eBPF만: 가능 (고성능 단일 클러스터)
✓ BGP만: 가능 (멀티 클러스터)
✓ 둘 다: 가능 (고성능 멀티 클러스터) ← 최고!
✓ 둘 다 안 씀: 가능 (일반 Flannel)

Q6: 라우터 설정은 누가 하나요?

A: 역할 분담:

네트워크팀:
- 물리/가상 라우터 설정
- AS Number 할당
- BGP 정책 설정
- 방화벽 규칙

DevOps팀:
- Calico BGP 설정
- Kubernetes 리소스 관리
- 모니터링 및 트러블슈팅

협업:
- AS Number 결정
- IP 대역 계획
- 장애 대응 절차

Q7: BGP 모니터링은 어떻게?

A: 여러 방법 사용:

# Calico 상태
calicoctl node status

# 상세 정보
sudo birdc show protocols all

# Prometheus 메트릭
felix_route_table_list_seconds
felix_int_dataplane_failures
bgp_peers_up

# 알림 설정
BGP 세션 Down → Slack 알림
경로 개수 급변 → 담당자 호출

Q8: 비용은 얼마나 차이 나나요?

A: 주로 운영 복잡도 차이:

Flannel:
- 설정 시간: 30분
- 학습 시간: 1일
- 운영 인력: 최소

Calico + BGP:
- 설정 시간: 2-4시간
- 학습 시간: 1주일
- 운영 인력: 네트워크 지식 필요

하드웨어 비용:
- 거의 차이 없음
- BGP 때문에 추가 장비 불필요

결론

핵심 요약

1. BGP는 언제 필요한가?

✅ 필요한 경우 (10%):
- 멀티 클러스터
- 온프레미스 통합
- 물리 네트워크 직접 연동
- 고성능 요구사항

❌ 불필요한 경우 (90%):
- 단일 클러스터
- Service/Ingress 사용
- 일반적인 마이크로서비스

2. BGP 설정 핵심

# 3가지만 기억하세요
1. asNumber: 우리 클러스터 AS
2. peerIP: 상대방 라우터 IP
3. asNumber (peer): 상대방 AS

# 나머지는 자동!

3. 장애는 자동 대응

BGP가 자동으로:
✓ 장애 감지 (10-30초)
✓ 대체 경로 선택
✓ 트래픽 우회
✓ 복구 시 원복

개발자는 신경 안 써도 됨!

4. 개발자 관점

// 코드는 항상 똑같음
await axios.post('http://service:8080/api', data);

// BGP가 있든 없든
// 멀티 클러스터든 단일 클러스터든
// 코드 변경 없음!

의사결정 가이드

시작 단계:
→ Flannel (간단함)

성장 단계:
→ Flannel 유지 (충분함)

스케일업:
→ Calico (성능/보안)

멀티 클러스터:
→ Calico + BGP (필수)

엔터프라이즈:
→ Calico + BGP + eBPF (최고)

마지막 조언

"BGP는 복잡하지만, 진짜 필요할 때까지는 쓰지 마세요.
하지만 필요한 순간이 오면, BGP만큼 강력한 게 없습니다."


참고 자료

공식 문서

추천 학습 자료

실전 케이스 스터디


마치며

BGP는 복잡해 보이지만, 핵심 개념만 이해하면 됩니다:

  1. 클러스터 내부는 CNI가 처리 (BGP 불필요)
  2. 클러스터 외부는 BGP가 필요 (멀티 클러스터, 온프레미스 등)
  3. 설정은 간단하지만 네트워크팀과 협업 필수
  4. 장애는 자동으로 대응 (BGP의 진가!)

이 글이 BGP에 대한 두려움을 없애고, 실전에서 올바른 선택을 하는 데 도움이 되었기를 바랍니다!

Happy Networking!

profile
기록하고 공유하려고 노력하는 DevOps 엔지니어

0개의 댓글