K8s Cilium eBPF 네트워킹

Cilium이란?

CiliumeBPF 기반 CNI(Container Network Interface) 플러그인이다. 기존 Calico, Flannel이 iptables로 네트워크 정책을 구현하는 반면, Cilium은 커널 레벨의 eBPF 프로그램으로 패킷을 처리한다. iptables의 선형 규칙 매칭 대신 eBPF의 해시 맵 기반 O(1) 룩업을 사용하므로, 규칙이 수천 개여도 성능 저하가 없다.

2024년 CNCF Graduated 프로젝트로 승격되었고, GKE, EKS, AKS 모두 Cilium을 기본 또는 선택 CNI로 지원한다. 단순 네트워킹을 넘어 L7 정책, 서비스 메시(사이드카 없는), 투명 암호화, Hubble 옵저버빌리티까지 제공하는 올인원 네트워킹 스택이다.

eBPF가 iptables보다 빠른 이유

비교 항목 iptables (Calico) eBPF (Cilium)
규칙 매칭 O(n) 선형 탐색 O(1) 해시 맵
kube-proxy 필요 (Service → iptables 규칙) 불필요 (eBPF로 대체)
conntrack 커널 conntrack 테이블 사용 자체 CT 맵 (더 효율적)
L7 정책 ❌ L3/L4만 ✅ HTTP, gRPC, Kafka 등
노드당 규칙 10,000개 ⚠️ 수초 지연 ✅ 영향 없음

설치: Helm으로 Cilium 배포

# Cilium CLI 설치
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
curl -L --fail --remote-name-all 
  https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin

# Helm으로 설치 (kube-proxy 대체 모드)
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --version 1.16.5 
  --namespace kube-system 
  --set kubeProxyReplacement=true 
  --set k8sServiceHost=${API_SERVER_IP} 
  --set k8sServicePort=6443 
  --set hubble.relay.enabled=true 
  --set hubble.ui.enabled=true 
  --set encryption.enabled=true 
  --set encryption.type=wireguard

# 설치 상태 확인
cilium status --wait
cilium connectivity test

CiliumNetworkPolicy: L3/L4 정책

Kubernetes 표준 NetworkPolicy도 지원하지만, CiliumNetworkPolicy는 훨씬 강력한 기능을 제공한다.

# 기본 L3/L4 정책: frontend → backend만 허용
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: backend-policy
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: backend
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend
      toPorts:
        - ports:
            - port: "8080"
              protocol: TCP
  egress:
    - toEndpoints:
        - matchLabels:
            app: database
      toPorts:
        - ports:
            - port: "5432"
              protocol: TCP
    # DNS 허용 (필수! 없으면 DNS 조회 실패)
    - toEndpoints:
        - matchLabels:
            k8s:io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP
          rules:
            dns:
              - matchPattern: "*.production.svc.cluster.local"

L7 정책: HTTP/gRPC 레벨 제어

Cilium의 킬러 기능L7 프로토콜 인식 정책이다. HTTP 메서드, 경로, 헤더까지 네트워크 정책으로 제어할 수 있다.

# L7 HTTP 정책: GET만 허용, POST /admin은 차단
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: api-l7-policy
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: api-server
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend
      toPorts:
        - ports:
            - port: "8080"
              protocol: TCP
          rules:
            http:
              # GET /api/products 허용
              - method: GET
                path: "/api/products.*"
              # POST /api/orders 허용
              - method: POST
                path: "/api/orders"
              # 그 외 모든 요청은 암묵적 거부
              # /admin, DELETE 등은 차단됨

gRPC 메서드 레벨 정책

# gRPC 특정 서비스/메서드만 허용
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: grpc-policy
spec:
  endpointSelector:
    matchLabels:
      app: order-grpc
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: api-gateway
      toPorts:
        - ports:
            - port: "50051"
              protocol: TCP
          rules:
            http:  # gRPC도 HTTP/2이므로 http 규칙 사용
              - method: POST
                path: "/order.v1.OrderService/CreateOrder"
              - method: POST
                path: "/order.v1.OrderService/GetOrder"
              # ListOrders, DeleteOrder는 차단

FQDN 기반 Egress 정책

외부 서비스 접근을 도메인 이름 기반으로 제어할 수 있다. IP가 동적으로 변하는 SaaS API에 특히 유용하다.

# 특정 외부 도메인만 허용
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: external-access
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: payment-service
  egress:
    # Stripe API만 허용
    - toFQDNs:
        - matchName: "api.stripe.com"
        - matchName: "hooks.stripe.com"
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP
    # AWS S3 (와일드카드)
    - toFQDNs:
        - matchPattern: "*.s3.amazonaws.com"
        - matchPattern: "*.s3.*.amazonaws.com"
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP
    # DNS 허용
    - toEndpoints:
        - matchLabels:
            k8s:io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP
          rules:
            dns:
              - matchPattern: "*"

CiliumClusterwideNetworkPolicy: 글로벌 정책

# 클러스터 전체 기본 거부 정책
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: default-deny-all
spec:
  endpointSelector: {}  # 모든 Pod에 적용
  ingress:
    - fromEntities:
        - cluster  # 클러스터 내부 트래픽만 허용
  egress:
    - toEntities:
        - cluster
        - world     # 외부 접근은 허용 (필요시 제거)
    - toEndpoints:
        - matchLabels:
            k8s:io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP

WireGuard 투명 암호화

Cilium은 WireGuard를 이용한 노드 간 트래픽 자동 암호화를 지원한다. Istio의 mTLS와 달리 사이드카 없이 커널 레벨에서 동작한다.

# 설치 시 활성화
helm upgrade cilium cilium/cilium 
  --set encryption.enabled=true 
  --set encryption.type=wireguard 
  --set encryption.wireguard.persistentKeepalive=25s

# 암호화 상태 확인
cilium encrypt status
# Encryption: WireGuard
# Keys in use: 2
# Max Seq. Number: 0x1a2b/0xFFFFFFFF

# 노드 간 WireGuard 터널 확인
kubectl exec -n kube-system cilium-xxxxx -- cilium encrypt status
# Node   Encrypt  PublicKey
# node1  Yes      abcd1234...
# node2  Yes      efgh5678...

Hubble: 네트워크 옵저버빌리티

Hubble은 Cilium에 내장된 네트워크 모니터링 도구다. Pod 간 트래픽 흐름을 실시간으로 관찰하고, 정책 위반을 즉시 탐지할 수 있다.

# Hubble CLI 설치
export HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
curl -L --fail --remote-name-all 
  https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-amd64.tar.gz
sudo tar xzvfC hubble-linux-amd64.tar.gz /usr/local/bin

# 포트 포워딩
cilium hubble port-forward &

# 실시간 트래픽 관찰
hubble observe --namespace production

# 특정 Pod의 트래픽만 필터
hubble observe --pod production/api-server-xxx --protocol http

# 거부된 트래픽만 확인 (정책 디버깅)
hubble observe --verdict DROPPED --namespace production

# HTTP 응답 코드별 필터
hubble observe --http-status 500-599 --namespace production

# 출력 예시:
# TIMESTAMP             SOURCE              DESTINATION         TYPE    VERDICT
# Mar 7 14:23:01.123    prod/frontend-abc   prod/api-xxx        HTTP    FORWARDED
#                       GET /api/products → 200 OK (12ms)
# Mar 7 14:23:02.456    prod/frontend-abc   prod/api-xxx        HTTP    DROPPED
#                       DELETE /api/admin → Policy denied (L7)

Hubble UI로 시각화

# Hubble UI 접근
kubectl port-forward -n kube-system svc/hubble-ui 12000:80

# 브라우저에서 http://localhost:12000 접속
# → 네임스페이스별 서비스 맵, 트래픽 흐름, 정책 상태 시각화

kube-proxy 대체: eBPF Service 처리

# kube-proxy 완전 제거 모드
helm upgrade cilium cilium/cilium 
  --set kubeProxyReplacement=true 
  --set loadBalancer.algorithm=maglev 
  --set loadBalancer.mode=dsr 
  --set bpf.masquerade=true

# 기존 kube-proxy DaemonSet 제거
kubectl -n kube-system delete ds kube-proxy
kubectl -n kube-system delete cm kube-proxy

# iptables 규칙 정리
kubectl -n kube-system exec cilium-xxxxx -- 
  iptables-save | grep -c KUBE
# 0 (kube-proxy 규칙 없음)

Maglev 해싱은 일관된 해싱으로 백엔드 Pod가 변경되어도 기존 연결이 최대한 유지된다. DSR(Direct Server Return)은 응답 패킷이 로드밸런서를 거치지 않고 클라이언트에 직접 전달되어 지연이 줄어든다.

운영 트러블슈팅

정책이 적용되지 않을 때

# Cilium 엔드포인트 상태 확인
kubectl -n kube-system exec cilium-xxxxx -- cilium endpoint list

# 특정 Pod의 정책 상태
kubectl -n kube-system exec cilium-xxxxx -- 
  cilium endpoint get <endpoint-id> -o json | 
  jq '.status.policy'

# 정책 적용 이벤트 확인
kubectl -n kube-system exec cilium-xxxxx -- 
  cilium monitor --type policy-verdict

DNS 문제 디버깅

# FQDN 정책의 DNS 캐시 확인
kubectl -n kube-system exec cilium-xxxxx -- 
  cilium fqdn cache list

# DNS Proxy 로그
kubectl -n kube-system exec cilium-xxxxx -- 
  cilium monitor --type l7 --protocol dns

Cilium은 eBPF라는 리눅스 커널의 혁신을 네트워킹에 적용한 결과물이다. iptables의 한계를 근본적으로 극복하면서, L7 정책, 투명 암호화, 사이드카 없는 서비스 메시까지 단일 스택으로 제공한다. 특히 대규모 클러스터(1000+ 노드)에서 iptables 기반 CNI의 성능 병목을 겪고 있다면, Cilium 전환을 적극 검토해야 한다.

관련 글: K8s NetworkPolicy 네트워크 격리 | K8s Istio Service Mesh 심화

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux