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

[KANS] 8주차 - Cilium CNI

by ★용호★ 2024. 10. 26.

eBPF를 왜 사용할까?

  • iptables의 단점을 보완하기 위함
    • 같은 NetworkPolicy를 할당받는 Pod가 무수히 많다면 Pod 수 만큼 iptables rule에 해당 NetworkPolicy가 반영되기 때문에 개수가 많아지고, 결과적으로 성능 저하로 이어짐
    • contrack 테이블의 지속적으로 유지 관리해야함
    • iptables의 규칙에 일치할 때까지 모든 규칙을 평가하기 때문에 비효율적임
    • iptables는 iptables는 규칙을 변경할 때 개별 규칙만을 수정하는 것이 아니라, 전체 규칙 세트를 한 번에 교체하기 때문에 incremental update가 불가능함
  • 결과적으로 iptables를 사용하면 클러스터 규모가 커지면 커질 수록 성능 저하가 발생함
  • eBPF는 iptables에서 kernel space와 user space에서 오고가는 prerouting, input, output, postrouting의 절차를 거치지 않고 패킷이 수신되면 eBPF Code가 즉시 처리함. iptables가 제공하는 기능들을 모두 eBPF에서 제공함

  • 리눅스 네트워크 스택의 단점은 복잡하고, 변경에 시간(리눅스 커널이 업데이트되는데 보통 5년)이 걸리고, 레이어를 건너 뛰기가 어려운 점이었는데 BPF는 커널에 코드를 삽입하여 패킷을 통제 할 수 있고 다양한 영역에서 Hook을 통해 접근할 수 있음

https://bit.ly/3EiLsU3

  • BPF를 확장한 것이 eBPF(extended BPF)
    • 리눅스 커널은 업데이트가 반영되는데 보통 3~5년이라는 긴 시간이 소요되기 때문에 커널레벨의 변경을 하기는 쉽지 않음
    • eBPF는 샌드박스 영역을 제공해서 커널 코드를 변경하지 않고도 커널 내에 자유롭게 프로그래밍해서 적용할 수 있기 때문에 최근에 너도나도 시도하고 있음
      • 네트워크 솔루션이나 방화벽을 제작하는 업체 등에서 효과적으로 활용할 수 있음

https://ebps.io

 

 

eBPF는 왜 성능이 더 좋은가?

만약 10Gbps 네트워크 대역폭을 사용한다고 가정할 때 userspace의 application에서 패킷을 차단한다면 어느정도 성능을 낼 수 있을까?

netfilter나 TC, XDP 영역에서 패킷을 차단하면 userspace와 비교해서 어느정도 성능 차이가 날까?

  • TC(Traffic Classfication)은 리눅스 시스템에서 네트워크 트래픽을 제어하고 관리하기 위한 도구로 네트워크 대역폭 관리나 큐잉(송수신 속도 조절), 패킷 분류, QoS(우선순위 부여로 성능 최적화) 등의 기능을 제공
  • XDP(eXpress Data Path)는 Linux 커널에서 고성능 네트워크 패킷 처리를 위해 설계된 프로그래밍 가능한 프레임워크로 eBPF 기반으로 구현됨

  • 패킷을 차단하는 위치가 하드웨어에 가까울 수록 성능이 확연히 좋아짐
  • 심지어 xdp-offload를 지원하는 NIC를 사용하면 10Gbps의 대역폭을 온전히 다 활용할 만큼 성능이 좋음
    • 서버에서 사용되는 CPU 연산을 NIC가 수행하기 때문에 성능이 더 좋아짐

  • 커널 내에서 안전하게 프로그래밍을 해서 적용할 수 있다는 것은 엄청난 기회

Cilium 소개

주요 기능

 

  • eBPF 기술 기반: Linux 커널의 eBPF 기술을 활용하여 고성능 네트워킹과 보안 제공
  • Kubernetes CNI: Kubernetes 클러스터의 네트워킹을 담당하는 CNI(Container Network Interface) 플러그인으로 작동
  • 네트워크 정책: 애플리케이션 계층(Layer 7)까지 세밀한 네트워크 정책 적용가능
  • 로드 밸런싱: 내장된 로드 밸런서 기능으로 서비스 간 트래픽 분산
  • 관찰성: Hubble 컴포넌트를 통해 네트워크 흐름과 성능 모니터링 가능
  • 보안: Tetragon을 통해 런타임 보안 관찰 및 정책 적용 가능
  • 멀티 클러스터 지원: 여러 Kubernetes 클러스터 간 네트워킹 지원
  • 서비스 메시: 마이크로서비스 간 통신을 관리하는 서비스 메시 기능 제공
  • 암호화: IPsec과 WireGuard를 사용한 투명한 네트워크 암호화를 지원
  • 클라우드 네이티브: 주요 클라우드 제공업체의 Kubernetes 서비스에서 채택되어 사용되고 있음

kube-proxy를 완전히 대체 가능

 

iptables나 conntrack을 사용하지 않고 eBPF를 사용하기 때문에 kube-proxy가 필요 없음

  • iptables와 eBPF를 혼용하도록 설정할 수도 있음
  • eBPF만 사용하더라도 Cilium이 장애가 났을 때를 대비해서 핵심적인 네트워킹 규칙은 iptables에 기록함 (예를들어 Pod에서 인터넷으로 트래픽이 나갈 수 있도록 masquerade 규칙 등)

 

Cilium 구성요소

https://github.com/cilium/cilium

  • Cilium Agent : 데몬셋으로 실행, K8S API 설정으로 부터 '네트워크 설정, 네트워크 정책, 서비스 부하분산, 모니터링' 등을 수행하며, eBPF 프로그램 관리
  • Cilium Client (CLI) : Cilium 커멘드툴, eBPF maps 에 직접 접속하여 상태 확인 가능
  • Cilium Operator : K8S 클러스터에 대한 한 번씩 처리해야 하는 작업을 관리
  • Hubble : 네트워크와 보안 모니터링 플랫폼 역할을 하여, 'Server, Relay, Client, Graphical UI' 로 구성
  • Data Store : Cilium Agent 간의 상태를 저장하고 전파하는 데이터 저장소, 2가지 종류 중 선택(K8S CRDs, Key-Value Store)

eBPF 코드를 직접 구현하기는 어렵기 때문에 이 역할을 Cilium이 해줌

 

Cilium이 L7 Policy를 지원하긴 하지만 사용 시 성능 저하가 있음. 원래는 TC 영역에서 바로 패킷을 처리할 수 있지만 L7 Policy를 사용하게 되면 proxy 인스턴스로 envoy를 사용하게 되고 envoy로 트래픽을 redirect 하기 위해서는 아래와 같이 Userspace proxy까지 트래픽을 전달할 수밖에 없음

Amazon EKS에 Cilium 설치하기

# Cilium 설치
helm repo add cilium https://helm.cilium.io/
helm upgrade --install cilium cilium/cilium --version 1.14.7 \
--namespace kube-system \
--set hubble.enabled=true \
--set hubble.tls.auto.enabled=true \
--set hubble.metrics.enabled="{dns,drop,tcp,flow,icmp,http}" \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set hubble.ui.service.type=NodePort \
--set hubble.relay.service.type=NodePort \
--set kubeProxyReplacement=strict \
--set encryption.enabled=false \
--set encryption.nodeEncryption=false \
--set routingMode=native \
--set ipv4NativeRoutingCIDR="0.0.0.0/0" \
--set bpf.masquerade=false \
--set nodePort.enabled=true \
--set autoDirectNodeRoutes=true \
--set hostLegacyRouting=false \
--set ingressController.enabled=true \
--set ingressController.loadbalancerMode=shared \
--set cni.chainingMode=aws-cni \
--set cni.install=true

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

# cilium으로 관리되지 않는 Pod들 재시작
kubectl get pods --all-namespaces -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,HOSTNETWORK:.spec.hostNetwork --no-headers=true | grep '<none>' | awk '{print "-n "$1" "$2}' | xargs -L 1 -r kubectl delete pod

# cilium cli 설치 (mac)
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/$CILIUM_CLI_VERSION/cilium-darwin-$CLI_ARCH.tar.gz
sudo tar xzvfC cilium-darwin-$CLI_ARCH.tar.gz /usr/local/bin
rm cilium-darwin-$CLI_ARCH.tar.gz
cilium status --wait

#----리소스 제거---------------------
helm delete cilium -n kube-system
  • bpf.masquerade : eBPF 기반의 마스커레이딩을 활성화 할지 여부를 지정합니다. (true/false)
    • 기존의 iptables 보다 더 효율적인 eBPF 기술을 사용하여 iptables 규칙을 우회하고 상위 호스트 스택을 완전히 건너뛰어서 네트워크 성능을 향상시킵니다.
  • hostLegacyRouting : 호스트 스택을 통해서 트래픽을 라우팅(true, 기본값)할지, BPF를 통해 트래픽을 라우팅(false)할지 결정합니다.
  • autoDirectNodeRoutes : 클러스터 내 노드 간 직접 라우팅을 자동으로 구성할지 여부를 결정합니다. true로 설정할 경우 각 노드의 PodCIDR에 대한 Direct Route를 자동으로 추가하고 중간 게이트웨이 없이 노드 간 트래픽이 직접 라우팅 되도록 합니다.
    • 여러 클러스터를 연결하는 클러스터 메시 구조가 아니고 같은 네트워크 내에 하나의 클러스터로만 구성되어 있다면 네트워크 성능을 향상 시킬 수 있습니다.
  • cni.chainingMode : Amazon EKS에서는 VPC CNI와 Cilium이 함께 동작하게 되는데 이 때 VPC CNI는 ENI를 통해 IP 주소를 관리하고, Cilium은 VPC CNI가 설정한 네트워크 디바이스에 eBPF를 연결하여 네트워크 정책 적용, 로드밸런싱, 암호화 등의 고급기능을 제공하게 됩니다. 이를 CNI 체이닝 모드라고 합니다.
  • 참고 : https://github.com/aws-samples/cilium-service-mesh-on-eks
 

GitHub - aws-samples/cilium-service-mesh-on-eks

Contribute to aws-samples/cilium-service-mesh-on-eks development by creating an account on GitHub.

github.com

 

댓글