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을 통해 접근할 수 있음
- BPF를 확장한 것이 eBPF(extended BPF)
- 리눅스 커널은 업데이트가 반영되는데 보통 3~5년이라는 긴 시간이 소요되기 때문에 커널레벨의 변경을 하기는 쉽지 않음
- eBPF는 샌드박스 영역을 제공해서 커널 코드를 변경하지 않고도 커널 내에 자유롭게 프로그래밍해서 적용할 수 있기 때문에 최근에 너도나도 시도하고 있음
- 네트워크 솔루션이나 방화벽을 제작하는 업체 등에서 효과적으로 활용할 수 있음
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 구성요소
- 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
'Work > 개발 노트' 카테고리의 다른 글
[KANS] 6주차 - Ingress, Gateway API (0) | 2024.10.13 |
---|---|
[KANS] 5주차 - LoadBalancer(MetalLB, IPVS) (0) | 2024.10.06 |
[KANS] 4주차 - Service (ClusterIP, NodePort) (1) | 2024.09.28 |
[KANS] 3주차 - Calico CNI & Mode 정리 (0) | 2024.09.21 |
[KANS] 2주차 - K8S Flannel CNI & Pause 정리 (0) | 2024.09.07 |
댓글