Cilium 스터디 - Networking 노드에 파드들간 통신 2 & K8S 외부 노출

Kevin·2025년 8월 9일

4주차 학습정리 - Cilium 네트워킹: 라우팅 모드 및 서비스 외부 노출

🌐 실습 환경 구성 및 아키텍처

1. 확장된 실습 환경 구성

1.1 실습 환경 개요

4주차 실습 환경은 더욱 복잡한 네트워킹 시나리오를 다루기 위해 4노드 환경으로 확장되었습니다:

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   k8s-ctr       │    │    k8s-w1       │    │    k8s-w0       │    │     router      │
│ (Control Plane) │    │ (Worker Node 1) │    │ (Worker Node 2) │    │  (외부 서버)     │
├─────────────────┤    ├─────────────────┤    ├─────────────────┤    ├─────────────────┤
│ eth0: NAT       │    │ eth0: NAT       │    │ eth0: NAT       │    │ eth0: NAT       │
│ eth1:192.168.10.│    │ eth1:192.168.10.│    │ eth1:192.168.20.│    │ eth1:192.168.10.│
│      100        │    │      101        │    │      100        │    │      200        │
│                 │    │                 │    │                 │    │ eth2:192.168.20.│
│ PodCIDR:        │    │ PodCIDR:        │    │ PodCIDR:        │    │      200        │
│ 172.20.0.0/24   │    │ 172.20.1.0/24   │    │ 172.20.2.0/24   │    │                 │
│                 │    │                 │    │                 │    │ loop1: 10.10.1. │
│                 │    │                 │    │                 │    │        200/24   │
│                 │    │                 │    │                 │    │ loop2: 10.10.2. │
│                 │    │                 │    │                 │    │        200/24   │
└─────────────────┘    └─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │                       │
         └───────────────────────┼───────────────────────┤                       │
                    Host-Only Network                     │                       │
                    (192.168.10.0/24)                    │                       │
                                                          │                       │
                                            Host-Only Network                     │
                                            (192.168.20.0/24)                    │
                                                          │                       │
                                                          └───────────────────────┘
                                                                  │
                                                      ┌─────────────────┐
                                                      │ 사내망 시뮬레이션  │
                                                      │ 10.10.0.0/16    │
                                                      └─────────────────┘

핵심 구성 요소:

  1. k8s-ctr: Control Plane 노드 (192.168.10.100)
  2. k8s-w1: Worker 노드 1 (192.168.10.101)![]
  3. k8s-w0: Worker 노드 2 (192.168.20.100) - 다른 네트워크 대역
  4. router: 외부 서버 (192.168.10.200, 192.168.20.200)
    • 두 네트워크 대역을 연결하는 라우터 역할
    • loop1/loop2 인터페이스를 통한 사내망 시뮬레이션

1.2 실습 환경 배포 및 확인

Vagrant를 통한 자동 배포:

# 실습 환경 배포
vagrant up

# 네트워크 인터페이스 정보 확인
# router 서버 네트워크 확인
sshpass -p 'vagrant' ssh vagrant@router ip -br -c -4 addr
# Expected output:
# lo       UNKNOWN  127.0.0.1/8
# eth0     UP       10.0.2.15/24 metric 100 
# eth1     UP       192.168.10.200/24 
# eth2     UP       192.168.20.200/24 
# loop1    UNKNOWN  10.10.1.200/24
# loop2    UNKNOWN  10.10.2.200/24

# k8s 노드들 네트워크 확인
ip -c -4 addr show dev eth1                                # k8s-ctr
sshpass -p 'vagrant' ssh vagrant@k8s-w1 ip -c -4 addr show dev eth1    # k8s-w1
sshpass -p 'vagrant' ssh vagrant@k8s-w0 ip -c -4 addr show dev eth1    # k8s-w0

# 라우팅 정보 확인
ip -c route | grep static
sshpass -p 'vagrant' ssh vagrant@router ip -c route

네트워크 연결성 테스트:

# 기본 통신 확인
ping -c 1 10.10.1.200     # router loop1
ping -c 1 192.168.20.100  # k8s-w0 eth1

# 경로 추적 (Path MTU Discovery)
tracepath -n 192.168.20.100
# Expected output:
# 1?: [LOCALHOST] pmtu 1500
# 1:  192.168.10.200  1.222ms 
# 1:  192.168.10.200  0.980ms 
# 2:  192.168.20.100  1.620ms reached
# Resume: pmtu 1500 hops 2 back 2

1.3 Cilium v1.18 설치 상태

기본 설정 확인:

# Cilium 버전 및 상태 확인
cilium version
cilium status

# 현재 설정된 라우팅 모드 확인
cilium config view | grep routing-mode
cilium config view | grep auto-direct-node-routes
# Expected: routing-mode: native, auto-direct-node-routes: true

🛣️ Native Routing Mode 심화 분석

1. Native Routing의 특징 및 동작 원리

1.1 autoDirectNodeRoutes 동작 이해

Native Routing 모드의 핵심 설정:

  • --set routingMode=native
  • --set autoDirectNodeRoutes=true

이 설정은 Cilium이 각 노드의 PodCIDR에 대한 직접 경로를 자동으로 생성하도록 합니다.

# 현재 라우팅 테이블 확인
ip -c route

# 각 노드별 PodCIDR 확인
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'
# Expected output:
# k8s-ctr   172.20.0.0/24
# k8s-w1    172.20.1.0/24  
# k8s-w0    172.20.2.0/24

# Worker 노드들의 라우팅 테이블 확인
sshpass -p 'vagrant' ssh vagrant@k8s-w1 ip -c route
sshpass -p 'vagrant' ssh vagrant@k8s-w0 ip -c route

1.2 샘플 애플리케이션 배포 및 라우팅 분석

애플리케이션 배포:

# 3개 노드에 분산 배포될 webpod 애플리케이션 생성
cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webpod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webpod
  template:
    metadata:
      labels:
        app: webpod
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - webpod
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: webpod
        image: traefik/whoami
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: webpod
  labels:
    app: webpod
spec:
  selector:
    app: webpod
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
EOF

# 테스트 클라이언트 Pod 배포
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: curl-pod
  labels:
    app: curl
spec:
  nodeName: k8s-ctr
  containers:
  - name: curl
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
    terminationGracePeriodSeconds: 0
EOF

1.3 Cilium 로드밸런싱 및 서비스 분석

배포 상태 확인:

# 배포 확인
kubectl get deploy,svc,ep webpod -owide
kubectl get endpointslices -l app=webpod
kubectl get ciliumendpoints

# Cilium 서비스 목록 확인
kubectl exec -n kube-system ds/cilium -- cilium-dbg service list

# eBPF 로드밸런서 맵 확인
kubectl exec -n kube-system ds/cilium -- cilium-dbg bpf lb list
kubectl exec -n kube-system ds/cilium -- cilium-dbg bpf lb list | grep 10.96.32.212

# NAT 테이블 확인
kubectl exec -n kube-system ds/cilium -- cilium-dbg bpf nat list

eBPF 맵 상세 분석:

# eBPF 맵 목록 (빈 엔트리 제외)
kubectl exec -n kube-system ds/cilium -- cilium-dbg map list | grep -v '0 0'

# 주요 eBPF 맵들:
# - cilium_lb4_services_v2: 서비스 정의
# - cilium_lb4_backends_v3: 백엔드 Pod 정보  
# - cilium_lb4_reverse_nat: 역방향 NAT
# - cilium_ipcache_v2: IP 캐시

# 서비스 맵 상세 정보
kubectl exec -n kube-system ds/cilium -- cilium-dbg map get cilium_lb4_services_v2 | grep 10.96.32.212

# 백엔드 맵 정보
kubectl exec -n kube-system ds/cilium -- cilium-dbg map get cilium_lb4_backends_v3

# IP 캐시 맵 정보
kubectl exec -n kube-system ds/cilium -- cilium-dbg map get cilium_ipcache_v2

1.4 k8s-w0 통신 문제 및 분석

문제 상황:
k8s-w0 노드는 다른 네트워크 대역(192.168.20.0/24)에 위치하여 직접 통신이 불가능합니다.

# 기본 통신 테스트
kubectl exec -it curl-pod -- curl webpod | grep Hostname

# k8s-w0 노드의 Pod IP 확인
export WEBPOD=$(kubectl get pod -l app=webpod --field-selector spec.nodeName=k8s-w0 -o jsonpath='{.items[0].status.podIP}')
echo $WEBPOD

# 직접 통신 시도 (실패 예상)
kubectl exec -it curl-pod -- ping -c 2 -w 1 -W 1 $WEBPOD

패킷 추적 분석:

# router에서 ICMP 패킷 모니터링
# (router 서버에서 실행)
tcpdump -i any icmp -nn

# 예상 결과: k8s-ctr → router → 라우팅 실패
# 22:08:20.123415 eth1 In  IP 172.20.0.89 > 172.20.2.36: ICMP echo request
# 22:08:20.123495 eth0 Out IP 172.20.0.89 > 172.20.2.36: ICMP echo request

# router의 라우팅 테이블 확인
ip route get 172.20.2.36
# Expected: 172.20.2.36 via 10.0.2.2 dev eth0 src 10.0.2.15 uid 0

해결 방안:
1. 방안 1: BGP를 통한 동적 라우팅 (5주차에서 다룸)
2. 방안 2: Overlay Network (Encapsulation) 사용
3. 방안 3: Static Route 수동 설정 (임시 해결책)

🌐 Overlay Network (Encapsulation) Mode

1. VXLAN Encapsulation 개념

1.1 VXLAN 터널링 원리

VXLAN(Virtual eXtensible Local Area Network)은 UDP 기반의 오버레이 터널링 프로토콜입니다:

VXLAN 헤더 구조:

  • 외부 이더넷 헤더 (14 bytes)
  • 외부 IP 헤더 (20 bytes)
  • 외부 UDP 헤더 (8 bytes)
  • VXLAN 헤더 (8 bytes)
  • 내부 이더넷 헤더 (14 bytes)
  • 총 오버헤드: 50 bytes

VXLAN vs GENEVE 비교:

특징VXLANGENEVE
헤더 크기8 bytes (고정)8+ bytes (가변)
메타데이터제한적확장 가능
성능높음보통
확장성제한적우수
사용 사례일반적인 오버레이OpenStack, 복잡한 메타데이터

1.5 Calico와의 라우팅 모드 비교

Calico Direct 모드:

Pod A (Node 1) → Node1 Route Table → Physical Network → Node2 Route Table → Pod B (Node 2)
  • 캡슐화 없음
  • 높은 성능
  • 네트워크 인프라 의존성
  • BGP 필수

Calico IPIP 모드:

Pod A → Node1 IPIP → Internet Protocol in IP → Node2 IPIP → Pod B
  • IP-in-IP 캡슐화 (20 bytes 오버헤드)
  • 네트워크 제약 극복
  • VXLAN 대비 낮은 오버헤드

Cilium vs Calico 라우팅 비교:

특징Cilium NativeCilium VXLANCalico DirectCalico IPIP
오버헤드없음50 bytes없음20 bytes
네트워크 요구사항높음낮음높음낮음
성능최고보통최고높음
eBPF 활용완전완전제한적제한적
L7 정책지원지원제한적제한적

1.2 VXLAN 모드로 전환

커널 모듈 확인:

# VXLAN/GENEVE 커널 지원 확인
grep -E 'CONFIG_VXLAN=y|CONFIG_VXLAN=m|CONFIG_GENEVE=y|CONFIG_GENEVE=m|CONFIG_FIB_RULES=y' /boot/config-$(uname -r)
# Expected output:
# CONFIG_FIB_RULES=y      # 커널에 내장됨
# CONFIG_VXLAN=m          # 모듈로 컴파일됨 → 커널에 로드해서 사용
# CONFIG_GENEVE=m         # 모듈로 컴파일됨 → 커널에 로드해서 사용

# 커널 모듈 로드
lsmod | grep -E 'vxlan|geneve'
modprobe vxlan
lsmod | grep -E 'vxlan|geneve'

# Worker 노드들에도 VXLAN 모듈 로드
for i in w1 w0 ; do 
  echo ">> node : k8s-$i <<"
  sshpass -p 'vagrant' ssh vagrant@k8s-$i sudo modprobe vxlan
  echo
done

Cilium VXLAN 모드 업그레이드:

# 기존 통신 상태 유지 (백그라운드)
kubectl exec -it curl-pod -- ping $WEBPOD1 &

# VXLAN 터널 모드로 업그레이드
helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --version 1.18.0 \
  --reuse-values \
  --set routingMode=tunnel \
  --set tunnelProtocol=vxlan \
  --set autoDirectNodeRoutes=false \
  --set installNoConntrackIptablesRules=false

# Cilium 재시작
kubectl rollout restart -n kube-system ds/cilium

1.3 VXLAN 설정 확인

VXLAN 인터페이스 및 설정 확인:

# Cilium 기능 상태 확인
cilium features status
cilium features status | grep datapath_network

# 라우팅 모드 확인
kubectl exec -it -n kube-system ds/cilium -- cilium status | grep ^Routing
cilium config view | grep tunnel

# VXLAN 인터페이스 확인
ip -c addr show dev cilium_vxlan

# 모든 노드의 VXLAN 인터페이스 확인
for i in w1 w0 ; do 
  echo ">> node : k8s-$i <<"
  sshpass -p 'vagrant' ssh vagrant@k8s-$i ip -c addr show dev cilium_vxlan
  echo
done

1.4 VXLAN 라우팅 분석

라우팅 테이블 변화:

# Control Plane 노드 라우팅
ip -c route | grep cilium_host

# Expected routes:
# 172.20.0.238 dev cilium_host proto kernel scope link
# 172.20.0.0/24 via 172.20.0.238 dev cilium_host proto kernel src 172.20.0.238
# 172.20.1.0/24 via 172.20.0.238 dev cilium_host proto kernel src 172.20.0.238 mtu 1450
# 172.20.2.0/24 via 172.20.0.238 dev cilium_host proto kernel src 172.20.0.238 mtu 1450

# 경로 확인
ip route get 172.20.1.10  # k8s-w1 Pod
ip route get 172.20.2.10  # k8s-w0 Pod

# Worker 노드들 라우팅 확인
for i in w1 w0 ; do 
  echo ">> node : k8s-$i <<"
  sshpass -p 'vagrant' ssh vagrant@k8s-$i ip -c route | grep cilium_host
  echo
done

2. VXLAN 통신 분석

2.1 eBPF 터널 엔드포인트 확인

각 노드의 Cilium Pod 이름 확인:

# 노드별 Cilium Pod 이름 지정
export CILIUMPOD0=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-ctr -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD1=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w1 -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD2=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w0 -o jsonpath='{.items[0].metadata.name}')

echo $CILIUMPOD0 $CILIUMPOD1 $CILIUMPOD2

# 각 노드의 router IP 확인
kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- cilium status --all-addresses | grep router
kubectl exec -it $CILIUMPOD1 -n kube-system -c cilium-agent -- cilium status --all-addresses | grep router  
kubectl exec -it $CILIUMPOD2 -n kube-system -c cilium-agent -- cilium status --all-addresses | grep router

eBPF 맵 상태 확인:

# IP 캐시 맵 (노드별 터널 엔드포인트 정보)
kubectl exec -n kube-system $CILIUMPOD0 -- cilium-dbg bpf ipcache list
kubectl exec -n kube-system $CILIUMPOD1 -- cilium-dbg bpf ipcache list
kubectl exec -n kube-system $CILIUMPOD2 -- cilium-dbg bpf ipcache list

# Socket NAT 맵 (터널링 관련)
kubectl exec -n kube-system $CILIUMPOD0 -- cilium-dbg bpf socknat list
kubectl exec -n kube-system $CILIUMPOD1 -- cilium-dbg bpf socknat list
kubectl exec -n kube-system $CILIUMPOD2 -- cilium-dbg bpf socknat list

2.2 VXLAN 패킷 분석

패킷 캡처 및 분석:

# k8s-w0 노드의 Pod IP 확인
export WEBPOD=$(kubectl get pod -l app=webpod --field-selector spec.nodeName=k8s-w0 -o jsonpath='{.items[0].status.podIP}')
echo $WEBPOD

# 터미널 1: router에서 VXLAN 패킷 모니터링
tcpdump -i any udp port 8472 -nn

# 터미널 2: ICMP 테스트
kubectl exec -it curl-pod -- ping -c 2 -w 1 -W 1 $WEBPOD

# 패킷 분석 예시:
# 08:49:29.969241 eth1 In  IP 192.168.10.100.54386 > 192.168.20.100.8472: 
#   OTV, flags I 0x08, overlay 0, instance 23926 
#   IP 172.20.0.44 > 172.20.2.43: ICMP echo request

VXLAN 트래픽 상세 분석:

# 터미널 1: 패킷을 파일로 저장
tcpdump -i any udp port 8472 -w /tmp/vxlan.pcap

# 터미널 2: HTTP 트래픽 생성
kubectl exec -it curl-pod -- sh -c 'while true; do curl -s --connect-timeout 1 webpod | grep Hostname; echo "---" ; sleep 1; done'

# 패킷 분석 도구 사용
tshark -r /tmp/vxlan.pcap -d udp.port==8472,vxlan
termshark -r /tmp/vxlan.pcap
termshark -r /tmp/vxlan.pcap -d udp.port==8472,vxlan

2.3 Hubble을 통한 오버레이 트래픽 모니터링

# Hubble 플로우 모니터링
hubble observe -f --protocol tcp --pod curl-pod

# VXLAN 모드에서의 플로우 로그 예시:
# Aug 3 00:02:26.403: default/curl-pod:40332 ID:23926 -> default/webpod-697b545f57-76lt6:80 ID:12438 to-overlay FORWARDED TCP Flags: SYN
# Aug 3 00:02:26.405: default/curl-pod:40332 ID:23926 <- default/webpod-697b545f57-76lt6:80 ID:12438 to-endpoint FORWARDED TCP Flags: SYN, ACK
# Aug 3 00:02:26.405: default/curl-pod:40332 ID:23926 -> default/webpod-697b545f57-76lt6:80 ID:12438 to-overlay FORWARDED TCP Flags: ACK

# 주요 상태 설명:
# - to-overlay: 패킷이 오버레이 네트워크로 전송됨
# - to-endpoint: 패킷이 대상 엔드포인트로 전달됨

3. MTU 고려사항

3.1 VXLAN MTU 문제

MTU 제한 확인:

# VXLAN 인터페이스 MTU 확인
ip -c addr show dev cilium_vxlan
# Expected: mtu 1450 (1500 - 50 bytes VXLAN overhead)

# MTU 테스트
kubectl exec -it curl-pod -- ping -M do -s 1500 $WEBPOD
# Expected error: ping: sendmsg: Message too long

# 적절한 크기로 테스트 (1450 - 28 = 1422 bytes payload)
kubectl exec -it curl-pod -- ping -M do -s 1422 $WEBPOD

MTU 관련 설명:

  • Don't Fragment (DF) 플래그: -M do 옵션으로 설정하여 조각화 방지
  • Payload 크기: -s 옵션으로 ICMP 데이터 크기 지정
  • VXLAN 오버헤드: 50 bytes 추가로 유효 MTU 감소 (1500 → 1450)

🚀 Kubernetes Service 심화

1. Service 타입별 특징 및 발전 단계

1.1 Service 발전 과정

  • ClusterIP 타입

  • NodePort 타입

  • LoadBalancer 타입

1단계: Pod 생성

  • 쿠버네티스 클러스터 내부에서만 접속 가능
  • Pod IP는 동적으로 변경됨
  • 직접 Pod IP로 접근 시 Pod 재시작 시 연결 끊김

2단계: Service (ClusterIP 타입)

  • 클러스터 내부에서만 접속 가능
  • 고정 Virtual IP와 Domain 주소 제공
  • 다수 Pod에 대한 로드밸런싱
  • 내부 DNS를 통한 서비스 디스커버리

3단계: Service (NodePort 타입)

  • 외부 클라이언트가 노드 IP와 특정 포트를 통해 접속
  • 모든 노드에서 동일한 포트로 서비스 접근 가능
  • 포트 범위 제한 (30000-32767)
  • 높은 포트 번호로 인한 사용성 문제

4단계: Service (LoadBalancer 타입)

  • 클라우드 제공자의 로드밸런서 활용
  • 단일 External IP를 통한 서비스 접근
  • 프라이빗 클라우드에서는 MetalLB나 Cilium L2/BGP 필요
  • 가장 운영 친화적인 외부 노출 방식

Service 타입별 특성 비교:

특징ClusterIPNodePortLoadBalancerExternalName
외부 접근N/A
로드밸런싱
포트 제한N/A
클라우드 의존성
운영 복잡성낮음보통낮음낮음

1.2 네트워크 주소 변환 (NAT) 개념

주요 용어:

  • S.IP: Source IP (출발지 IP)
  • D.IP: Destination IP (도착지 IP)
  • S.Port: Source Port (출발지 포트)
  • D.Port: Destination Port (도착지 포트)
  • SNAT: Source NAT (출발지 IP 변환)
  • DNAT: Destination NAT (목적지 IP/포트 변환)

2. kube-proxy 모드 비교

2.1 kube-proxy 역할

kube-proxy는 각 노드에서 실행되는 네트워크 프록시로 Kubernetes Service 개념의 일부를 구현합니다:

  • 실행 위치: 각 노드에서 데몬셋으로 실행
  • 지원 프로토콜: UDP, TCP, SCTP
  • 주요 기능: 로드밸런싱, 서비스 엔드포인트 관리
  • 제한사항: HTTP 레벨 처리는 불가능

2.2 프록시 모드별 특징

kube-proxy 모드별 성능 비교:

특징User SpaceiptablesIPVSnftableseBPF (Cilium)
성능낮음보통높음높음최고
확장성나쁨제한적우수우수우수
커널 의존성낮음보통높음높음높음
메모리 사용량높음보통낮음낮음낮음
CPU 사용량높음보통낮음낮음낮음

1. User Space 프록시 모드 (미사용)

클라이언트 → iptables REDIRECT → kube-proxy → Pod
  • SPOF(Single Point of Failure) 위험
  • 사용자 공간과 커널 공간 간 변환 오버헤드
  • 현재는 사용하지 않음

2. iptables 프록시 모드

클라이언트 → iptables DNAT → Pod (직접)
  • netfilter 서브시스템의 iptables API 활용
  • kube-proxy는 규칙만 관리, 실제 데이터 트래픽은 netfilter가 처리
  • 데몬셋으로 동작하여 SPOF 해결
  • User Space 모드 대비 안정성과 성능 향상

3. IPVS 프록시 모드

클라이언트 → IPVS (kernel space) → Pod
  • Linux 커널의 L4 로드밸런서인 IPVS 활용
  • 해시 테이블 기반으로 iptables보다 높은 성능
  • 커널 공간에서 동작하여 낮은 지연시간
  • 높은 네트워크 트래픽 처리량 지원

4. nftables 프록시 모드

클라이언트 → nftables API → Pod
  • iptables의 후속 기술, 향상된 성능과 확장성
  • 커널 5.13 이상에서 지원
  • 서비스 엔드포인트 변경을 더 빠르고 효율적으로 처리
  • 아직 상대적으로 새로운 기술

5. eBPF 모드 + XDP

클라이언트 → eBPF (XDP) → Pod
  • 기존 netfilter/iptables 우회
  • 최고 성능의 패킷 처리
  • XDP(eXpress Data Path)로 커널 바이패스
  • Cilium에서 활용하는 고성능 방식

🎯 Service LoadBalancer IP Address Management (LB IPAM)

1. LB IPAM 개념 및 필요성

1.1 LB IPAM 소개

LoadBalancer IP Address Management는 LoadBalancer 타입의 서비스에 External IP를 할당할 수 있게 해주는 기능입니다:

주요 특징:

  • 클라우드 제공업체 의존성 해결
  • 프라이빗 클라우드 환경에서 LoadBalancer 서비스 지원
  • Cilium BGP Control Plane 및 L2 Announcements와 통합

동작 방식:
1. IP 풀 생성: CiliumLoadBalancerIPPool CRD로 IP 범위 정의
2. 자동 할당: LoadBalancer 서비스 생성 시 IP 자동 할당
3. 광고 메커니즘: BGP 또는 L2 Announcements를 통한 IP 광고

1.2 지원 기능

핵심 기능들:

  • Service Selectors: 특정 서비스에만 IP 할당
  • Pool 비활성화: 특정 풀 일시 중단
  • Service 사용 확인: IP 할당 상태 모니터링
  • LoadBalancerClass: BGP 또는 L2 방식 지정
  • IP 직접 요청: 특정 IP 지정 할당
  • Sharing Keys: 하나의 IP를 여러 포트로 공유

2. LB IPAM 실습

2.1 CiliumLoadBalancerIPPool 생성

# 기존 IP Pool 확인
kubectl get CiliumLoadBalancerIPPool -A

# IP Pool 생성 (충돌하지 않는 대역 사용)
cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2"
kind: CiliumLoadBalancerIPPool
metadata:
  name: "cilium-lb-ippool"
spec:
  blocks:
  - start: "192.168.10.211"
    stop: "192.168.10.215"
EOF

# CiliumLoadBalancerIPPool 축약어 확인
kubectl api-resources | grep -i CiliumLoadBalancerIPPool
# 축약어: ippools, ippool, lbippool, lbippools

# IP Pool 상태 확인
kubectl get ippools
# Expected output:
# NAME               DISABLED   CONFLICTING   IPS         AVAILABLE   AGE
# cilium-lb-ippool   false      False         5           5           20s

2.2 LoadBalancer 서비스 생성

# webpod 서비스를 LoadBalancer 타입으로 변경
kubectl patch svc webpod -p '{"spec":{"type":"LoadBalancer"}}'

# 서비스 상태 확인
kubectl get svc webpod
# Expected output:
# NAME     TYPE           CLUSTER-IP     EXTERNAL-IP      PORTS         AGE
# webpod   LoadBalancer   10.96.32.212   192.168.10.211   80:32039/TCP  150m

# External IP 확인
LBIP=$(kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "LoadBalancer IP: $LBIP"

2.3 LoadBalancer IP 통신 테스트

클러스터 내부에서 테스트:

# 클러스터 내부에서 LB IP로 접근
curl -s $LBIP
kubectl exec -it curl-pod -- curl -s $LBIP
kubectl exec -it curl-pod -- curl -s $LBIP | grep Hostname

# 소스 IP 확인 (Pod 관점)
kubectl exec -it curl-pod -- curl -s $LBIP | grep RemoteAddr

# 로드밸런싱 확인
for i in {1..100}; do 
  kubectl exec -it curl-pod -- curl -s $LBIP | grep Hostname
done | sort | uniq -c | sort -nr

IP 할당 상태 확인:

# IP Pool 상태 상세 확인
kubectl get ippools
kubectl get ippools -o jsonpath='{.items[*].status.conditions[?(@.type!="cilium.io/PoolConflict")]}' | jq

# 서비스 상태 JSON 확인
kubectl get svc webpod -o json | jq
kubectl get svc webpod -o jsonpath='{.status}' | jq

2.4 외부 접근 문제

클러스터 외부에서 접근 시도:

# router에서 LB IP 접근 시도 (실패 예상)
# (router 서버에서 실행)
LBIP=192.168.10.211
curl --connect-timeout 1 $LBIP

# ARP 테이블 확인
arping -i eth1 $LBIP -c 1

# 지속적인 ARP 요청 (응답 없음)
arping -i eth1 $LBIP -c 100000

문제 원인:

  • LoadBalancer IP가 할당되었지만 외부 광고가 없음
  • BGP 또는 L2 Announcements가 필요
  • 네트워크 인프라가 해당 IP에 대한 경로를 모름

🌊 Cilium L2 Announcements

1. L2 Announcements 개념

1.1 MetalLB Layer2 모드 vs Cilium L2 Announcements

MetalLB Layer2 모드 동작:
1. Speaker Pod가 LoadBalancer IP에 대한 ARP 응답
2. 특정 노드에서만 IP 소유권 주장 (리더 선출)
3. MAC 주소 학습을 통한 트래픽 전달
4. 장애 시 다른 노드로 IP 이동

Cilium L2 Announcements 장점:

  • MetalLB 대체 가능한 네이티브 기능
  • eBPF 기반 고성능 처리
  • Cilium 에코시스템과 완전 통합
  • 더 나은 성능과 안정성

1.2 L2 Announcements 활성화

Cilium L2 Announcements 설정:

# L2 Announcements 활성화
helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --set l2announcements.enabled=true

# 설정 확인
cilium config view | grep l2-announcements
# Expected: l2-announcements-enabled: true

# L2 Announcements 정책 생성
cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2alpha1"
kind: CiliumL2AnnouncementPolicy
metadata:
  name: default-l2-announcement-policy
spec:
  serviceSelector:
    matchLabels:
      app: webpod
  nodeSelector:
    matchExpressions:
    - key: node-role.kubernetes.io/control-plane
      operator: DoesNotExist
  interfaces:
  - eth1
  externalIPs: true
  loadBalancerIPs: true
EOF

# 정책 확인
kubectl get CiliumL2AnnouncementPolicy
kubectl describe CiliumL2AnnouncementPolicy default-l2-announcement-policy

2. L2 Announcements 동작 확인

2.1 ARP 테이블 및 트래픽 확인

# LoadBalancer IP 재확인
LBIP=$(kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "LoadBalancer IP: $LBIP"

# k8s 노드들에서 ARP 테이블 확인
ip -c neigh | grep $LBIP
sshpass -p 'vagrant' ssh vagrant@k8s-w1 ip -c neigh | grep $LBIP
sshpass -p 'vagrant' ssh vagrant@k8s-w0 ip -c neigh | grep $LBIP

# router에서 ARP 요청 및 응답 확인
# (router 서버에서 실행)
arping -i eth1 $LBIP -c 3

# ARP 테이블에서 응답 확인
arp -a | grep $LBIP

2.2 외부에서 LoadBalancer 서비스 접근

# router에서 HTTP 접근 (성공 예상)
# (router 서버에서 실행)
curl -s $LBIP
curl -s $LBIP | grep Hostname

# 지속적인 접근 테스트
while true; do 
  curl -s --connect-timeout 1 $LBIP | grep Hostname
  sleep 1
done

2.3 L2 Announcements 로그 및 상태 확인

# Cilium L2 Announcements 관련 로그 확인
kubectl logs -n kube-system -l k8s-app=cilium -c cilium-agent | grep -i l2

# L2 Announcements 상태 확인
cilium status | grep -i l2

# LoadBalancer 서비스에 대한 L2 광고 확인
kubectl exec -n kube-system ds/cilium -c cilium-agent -- cilium service list | grep LoadBalancer

3. L2 Announcements 트러블슈팅

3.1 일반적인 문제점

문제 1: ARP 응답 없음

# L2 정책 확인
kubectl get CiliumL2AnnouncementPolicy -o yaml

# 노드 셀렉터 확인
kubectl get nodes --show-labels

# 인터페이스 설정 확인
ip -c addr show dev eth1

문제 2: 특정 노드에서만 응답

# 리더 선출 상태 확인
kubectl logs -n kube-system -l k8s-app=cilium -c cilium-agent | grep leader

# 모든 노드의 L2 상태 확인
for node in k8s-ctr k8s-w1 k8s-w0; do
  echo "=== Node: $node ==="
  kubectl get pods -n kube-system -l k8s-app=cilium --field-selector spec.nodeName=$node
done

3.2 성능 및 모니터링

# L2 Announcements 메트릭 확인
kubectl exec -n kube-system ds/cilium -c cilium-agent -- curl -s localhost:9962/metrics | grep l2

# 네트워크 인터페이스 통계
ip -s link show dev eth1

# ARP 캐시 만료 시간 확인
cat /proc/sys/net/ipv4/neigh/eth1/base_reachable_time_ms

📊 (참고) 프로메테우스 스택

1. 모니터링 스택 구성

1.1 주요 구성 요소

핵심 컴포넌트:

  • Prometheus: 메트릭 수집 및 저장
  • Grafana: 시각화 및 대시보드
  • AlertManager: 알림 관리
  • Node Exporter: 노드 메트릭 수집

Cilium 관련 메트릭:

  • Cilium Agent 메트릭 (포트 9962)
  • Cilium Operator 메트릭 (포트 9963)
  • Hubble 메트릭 (포트 9965)

1.2 메트릭 수집 확인

# Cilium Agent 메트릭 확인
kubectl exec -n kube-system ds/cilium -c cilium-agent -- curl -s localhost:9962/metrics | head -20

# Cilium Operator 메트릭 확인  
kubectl exec -n kube-system deploy/cilium-operator -- curl -s localhost:9963/metrics | head -20

# Hubble 메트릭 확인
kubectl exec -n kube-system deploy/hubble-relay -- curl -s localhost:9965/metrics | head -20

2. 권장 모니터링 지표

2.1 Cilium 핵심 메트릭

성능 지표:

# eBPF 맵 사용률
cilium_datapath_conntrack_gc_entries
cilium_bpf_map_pressure

# 엔드포인트 재생성
cilium_endpoint_regenerations_total

# 패킷 드롭
cilium_drop_count_total
cilium_drop_bytes_total

서비스 지표:

# 로드밸런서 백엔드
cilium_services_events_total
cilium_k8s_client_api_calls_total

# L2 Announcements
cilium_l2_announcements_total

2.2 L2 Announcements 특화 메트릭

# L2 광고 성공/실패
kubectl exec -n kube-system ds/cilium -c cilium-agent -- curl -s localhost:9962/metrics | grep l2_announcement

📚 참고 자료 및 추가 학습

1. YouTube eCHO Episode 시리즈

권장 시청 영상:

  • eCHO Episode 1: Cilium 소개 및 기본 개념
  • eCHO Episode 7: DNS with Laurent Bernaille
  • eCHO Episode 39: Local Redirect Policy
  • eCHO Episode 56: Service Mesh with Cilium
  • eCHO Episode 72: BGP on Cilium

2. 공식 문서 및 블로그

핵심 문서:

3. 실무 적용 고려사항

3.1 성능 최적화

Native Routing vs Overlay:

  • 성능: Native > VXLAN > GENEVE
  • 복잡성: Overlay > Native
  • 호환성: Overlay > Native

권장 시나리오:

  • Native Routing: 동일 L2 네트워크, BGP 지원 환경
  • VXLAN Overlay: 복잡한 네트워크 토폴로지
  • GENEVE: OpenStack 환경, 확장된 메타데이터 필요

3.2 LoadBalancer 서비스 운영

L2 Announcements 적합 환경:

  • 단일 L2 네트워크 세그먼트
  • 작은 규모의 클러스터 (< 50 노드)
  • 간단한 네트워크 토폴로지

BGP 권장 환경:

  • 대규모 클러스터 (> 50 노드)
  • 복잡한 네트워크 라우팅
  • 클라우드 네이티브 환경

4. 트러블슈팅 가이드

4.1 일반적인 문제점

Native Routing 문제:

# 라우팅 테이블 확인
ip route show table main

# BGP 피어 상태 확인 (BGP 사용 시)
cilium bgp peers

# 노드 간 연결성 확인
ping <other-node-ip>

L2 Announcements 문제:

# L2 정책 상태 확인
kubectl get CiliumL2AnnouncementPolicy -o yaml

# ARP 테이블 확인
ip neigh show

# 인터페이스 상태 확인
ip link show

4.2 성능 분석

네트워크 성능 측정:

# iperf3를 통한 대역폭 측정
kubectl run iperf3-server --image=networkstatic/iperf3 --port=5201
kubectl run iperf3-client --image=networkstatic/iperf3 --rm -it -- -c <server-ip>

# 지연시간 측정
kubectl exec -it curl-pod -- ping -c 100 <target-ip> | tail -1

🎯 4주차 학습 요약

1. 핵심 성취 목표

네트워킹 모드 이해:

  • ✅ Native Routing과 Overlay Network 차이점 파악
  • ✅ VXLAN/GENEVE 터널링 메커니즘 이해
  • ✅ autoDirectNodeRoutes 동작 원리 학습
  • ✅ MTU 고려사항 및 성능 영향 분석

Service 외부 노출:

  • ✅ LoadBalancer IPAM을 통한 IP 관리
  • ✅ L2 Announcements로 외부 접근 활성화
  • ✅ kube-proxy 모드별 특징 비교
  • ✅ 실제 운영 환경에서의 고려사항

2. 실무 적용 포인트

아키텍처 선택 기준:

  • 네트워크 토폴로지: 단일 L2 vs 복잡한 라우팅
  • 성능 요구사항: 지연시간 vs 처리량
  • 운영 복잡성: 관리 편의성 vs 기능 풍부함

스케일링 고려사항:

  • 소규모: L2 Announcements
  • 대규모: BGP Control Plane (5주차)
  • 클라우드: Provider 네이티브 통합

3. 다음 단계 학습

5주차 예상 내용:

  • BGP Control Plane을 통한 동적 라우팅
  • 대규모 클러스터에서의 네트워킹
  • 멀티클러스터 연결 (Cluster Mesh)
  • 고급 보안 정책 및 암호화

추가 실습 권장:

  • 다양한 터널링 프로토콜 성능 비교
  • 클라우드 환경에서의 LoadBalancer 통합
  • Prometheus/Grafana를 통한 네트워킹 메트릭 모니터링

이로써 Cilium의 핵심 네트워킹 기능과 서비스 외부 노출 메커니즘에 대한 포괄적인 이해를 완성하였습니다. 다음 주차에서는 이러한 기반 위에 더욱 고급화된 BGP 라우팅과 멀티클러스터 네트워킹을 학습하게 될 것입니다.

profile
성장해나가는 개발자입니다.

0개의 댓글