CNI 성능 벤치마크

CNI 성능 벤치마크 (CNI Performance Benchmark)

이 장은 다양한 시나리오의 성능 벤치마크 수치를 포함해요. 모든 테스트는 100Gbit/s 네트워크 인터페이스로 백투백 연결된 두 대의 베어메탈 노드에서 실행되는 컨테이너 사이에서 수행됩니다. 많은 요청에 따라 비교를 위해 Calico의 성능 수치도 포함했습니다.

출처: CNI Performance Benchmark

본문

이 장은 다양한 시나리오의 성능 벤치마크 수치를 포함합니다. 모든 테스트는 100Gbit/s 네트워크 인터페이스로 백투백 연결된 두 대의 서로 다른 베어메탈 노드에서 실행되는 컨테이너 사이에서 수행됩니다. 많은 요청에 따라 비교를 위해 Calico의 성능 수치도 포함했습니다.

Video

Cilium 공동 창업자 Thomas Graf가 이 장을 깊이 있게 설명하는 eCHO episode 5: Network performance benchmarking을 볼 수도 있어요.

Tip

이런 성능 결과를 얻으려면 튜닝 가이드를 따르세요.

사용된 시스템과 구성에 대한 자세한 내용은 테스트 하드웨어를, 테스트된 모든 구성에 대한 자세한 내용은 테스트 구성을 참고하세요.

다음 메트릭이 수집·보고됩니다. 각 메트릭은 워크로드에 필요할 수 있는 서로 다른 트래픽 패턴을 나타냅니다. 각 벤치마크가 어떤 유형의 워크로드를 나타내는지에 대한 설명은 해당 섹션을 참고하세요.

  • 처리량 (Throughput) — 단일 TCP 연결을 통한 최대 전송 속도와 누적된 32개 연결의 총 전송 속도.

  • 요청/응답 속도 (Request/Response Rate) — 단일 TCP 연결과 32개 병렬 TCP 연결을 통해 전송할 수 있는 초당 요청/응답 메시지 수.

  • 연결 속도 (Connections Rate) — 각 새 연결에 대해 단일 요청/응답 페이로드 메시지와 함께 순차로 수립할 수 있는 초당 연결 수. 단일 프로세스와 32개 병렬 프로세스가 테스트됩니다.

다양한 벤치마크에 대해 netperf가 워크로드 생성과 메트릭 수집에 사용되었습니다. 병렬 netperf 세션 생성에는 super_netperf를 사용했습니다. netperf와 super_netperf는 모두 Linux 커널 네트워킹 커뮤니티에서 벤치마킹에 자주 사용되고 잘 정립된 도구예요.

TCP 처리량 (TCP_STREAM)

처리량 테스트(TCP_STREAM)는 특정 구성으로 달성할 수 있는 최대 처리량을 이해하는 데 유용해요. 충분한 CPU 리소스를 부하에 투입하면 모든 또는 대부분의 구성이 라인레이트 또는 그에 가까운 성능을 달성할 수 있습니다. 따라서 특정 처리량을 달성하는 데 필요한 CPU 리소스의 양을 이해하는 것이 중요해요. 이 CPU 리소스는 더 이상 머신에서 실행되는 워크로드에 사용할 수 없기 때문입니다.

이 테스트는 스트리밍 서비스나 데이터 업로드/다운로드를 수행하는 서비스 같은 대량 데이터 전송 워크로드를 나타냅니다.

단일 스트림 (Single-Stream)

이 테스트에서는 컨테이너 사이에 단일 TCP 스트림이 열리며 최대 처리량을 달성합니다:

../../../_images/bench_tcp_stream_1_stream.png

eBPF 기반 솔루션이 추가 작업(컨테이너의 네트워크 네임스페이스로의 포워딩, 정책 적용 등)을 수행함에도 불구하고 현대 커널에서 노드 간 베이스라인조차 능가할 수 있음을 볼 수 있어요. eBPF는 노드 간 베이스라인에서도 여전히 트래버스되는 노드의 iptables 레이어를 우회할 수 있기 때문입니다.

다음 그래프는 벤치마크 실행 중 시스템 전체의 총 CPU 소비를 50Gbit 처리량에 정규화해 보여줍니다:

../../../_images/bench_tcp_stream_1_stream_cpu.png

Tip

커널 지혜: TCP 흐름 성능은 수신자가 제한하는데, 송신자가 TSO super-패킷을 둘 다 사용할 수 있기 때문입니다. 이는 위의 서버 측 CPU 지출 증가에서 관찰할 수 있어요.

다중 스트림 (Multi-Stream)

이 테스트에서는 32개 프로세스가 32개의 병렬 TCP 연결을 엽니다. 각 프로세스가 최대 처리량을 달성하려 시도하며 총합이 보고됩니다:

../../../_images/bench_tcp_stream_32_streams.png

여러 프로세스가 사용되므로 모든 테스트 구성이 네트워크 인터페이스 라인레이트에 가까운 전송 속도를 달성할 수 있어요. 주요 차이는 이를 달성하는 데 필요한 CPU 리소스예요:

../../../_images/bench_tcp_stream_32_streams_cpu.png

요청/응답 속도 (TCP_RR)

요청/응답 속도(TCP_RR)는 개별 네트워크 패킷의 라운드트립 포워딩을 처리하는 지연과 효율을 주로 측정합니다. 이 벤치마크는 선상에서 가능한 초당 최대 패킷 수를 만들어 네트워크 패킷 하나가 부담하는 비용에 부하를 줍니다. 이는 각 네트워크 패킷의 크기를 최대화하는 처리량 테스트의 반대예요.

이 테스트에서 잘하는 구성(높은 초당 요청 수 제공)은 더 나은(더 낮은) 네트워크 지연도 제공합니다.

이 테스트는 영구 연결을 유지하고 다른 서비스와 요청/응답 유형 상호작용을 교환하는 서비스를 나타냅니다. REST나 gRPC API를 사용하는 서비스에서 흔히 볼 수 있어요.

1 프로세스

이 테스트에서는 컨테이너 사이에 단일 TCP 연결이 열리고 컨테이너 사이에서 단일 바이트가 왕복 전송됩니다. 각 라운드트립마다 하나의 요청이 계산됩니다:

../../../_images/bench_tcp_rr_1_process.png

현대 커널의 eBPF는 베이스라인과 거의 같은 요청/응답 속도를 달성하면서 CPU 리소스를 약간만 더 소비할 수 있습니다:

../../../_images/bench_tcp_rr_1_process_cpu.png

32 프로세스

이 테스트에서는 32개 프로세스가 32개의 병렬 TCP 연결을 엽니다. 각 프로세스는 단일 바이트 라운드트립을 수행합니다. 초당 총 요청 수가 보고됩니다:

../../../_images/bench_tcp_rr_32_processes.png

Cilium은 이 테스트에서 약 100만 요청/초에 가까운 성능을 달성하면서 송신자·수신자 모두 시스템 리소스의 약 30%를 소비합니다:

../../../_images/bench_tcp_rr_32_processes_cpu.png

연결 속도 (TCP_CRR)

연결 속도(TCP_CRR) 테스트는 새 연결을 처리하는 효율을 측정합니다. 요청/응답 속도 테스트와 유사하지만 각 라운드트립마다 새 TCP 연결을 만듭니다. 이는 연결 수립, 양방향으로 한 바이트 전송, 연결 종료의 비용을 측정합니다. TCP_RR 테스트보다 비용이 더 들며 새 연결 처리와 관련된 비용에 부하를 줍니다.

이 테스트는 많은 TCP 연결을 받거나 시작하는 워크로드를 나타냅니다. 예를 들어 많은 클라이언트로부터 연결을 받는 공개적으로 노출된 서비스가 여기에 해당합니다. L4 프록시나 외부 엔드포인트에 많은 연결을 여는 서비스가 좋은 예시예요. 이 벤치마크는 하드웨어로 오프로드되는 작업이 가장 적어 시스템에 가장 큰 부하를 주므로, 테스트된 구성 사이에서 가장 큰 차이를 볼 수 있을 것으로 기대합니다.

이 테스트에서 잘하는 구성(높은 연결 속도 제공)은 압도적인 연결 속도를 가진 상황을 훨씬 잘 처리하며, 시스템의 워크로드에 더 많은 CPU 리소스를 남겨줍니다.

1 프로세스

이 테스트에서는 단일 프로세스가 가능한 한 많은 TCP 연결을 순차로 엽니다:

../../../_images/bench_tcp_crr_1_process.png

다음 그래프는 벤치마크 실행 중 시스템 전체의 총 CPU 소비를 보여줍니다:

../../../_images/bench_tcp_crr_1_process_cpu.png

Tip

커널 지혜: 모든 컨테이너 워크로드 벤치마크가 이 비용의 징후를 보이므로, 네트워크 네임스페이스 격리가 수행되는 즉시 송신자 측에서 추가 커널 비용이 발생한다는 것이 CPU 리소스 그래프에서 분명합니다. 이 측면은 향후 릴리스에서 조사·최적화할 예정입니다.

32 프로세스

이 테스트에서는 병렬로 실행되는 32개 프로세스가 가능한 한 많은 TCP 연결을 순차로 엽니다. 이는 시스템에 가장 부담이 큰 테스트입니다.

../../../_images/bench_tcp_crr_32_processes.png

이 벤치마크는 테스트된 구성 사이의 주요 차이를 보여줍니다. 특히 연결당 필요한 대부분의 작업을 수행한 후 결과를 캐시하도록 최적화된 iptables의 총 비용을 보여줍니다. 이는 많은 새 연결이 예상될 때 최악의 성능 시나리오를 만들어냅니다.

Note

Calico eBPF 데이터패스에 대해서는 안정적인 결과를 측정하지 못했습니다. 이유는 확실하지 않아요. 네트워크 패킷 흐름이 결코 안정적이지 않았습니다. 따라서 결과를 포함하지 않았습니다. Calico 팀이 함께 조사한 후 다시 테스트할 것을 초대합니다.

다음 그래프는 벤치마크 실행 중 시스템 전체의 총 CPU 소비를 보여줍니다:

../../../_images/bench_tcp_crr_32_processes_cpu.png

암호화 (WireGuard/IPsec)

Cilium은 WireGuard®와 IPsec을 통한 암호화를 지원합니다. 이 첫 섹션은 WireGuard를 살펴보고 WireGuard 암호화에 Calico를 사용하는 것과 비교합니다. IPsec 성능과 WireGuard와의 비교에 관심이 있다면 WireGuard vs IPsec을 참고하세요.

WireGuard 처리량

먼저 TCP 처리량을 보면, 다음 그래프는 1500바이트 MTU와 9000바이트 MTU 둘 다의 결과를 보여줍니다:

../../../_images/bench_wireguard_tcp_1_stream.png

Note

Cilium eBPF kube-proxy 대체와 WireGuard의 조합은 현재 Cilium eBPF + kube-proxy보다 약간 느립니다. 문제를 식별했으며 다음 릴리스 중 하나에서 이 차이를 해결할 예정입니다.

다음 그래프는 WireGuard 암호화 벤치마크 실행 중 시스템 전체의 총 CPU 소비를 보여줍니다:

../../../_images/bench_wireguard_tcp_1_stream_cpu.png

WireGuard 요청/응답

다음 벤치마크는 WireGuard로 암호화하면서 요청/응답 속도를 측정합니다. 이 테스트가 실제로 무엇을 하는지에 대한 자세한 내용은 요청/응답 속도 (TCP_RR)를 참고하세요.

../../../_images/bench_wireguard_rr_1_process.png

테스트된 모든 구성이 거의 비슷하게 수행되었습니다. 다음 그래프는 WireGuard 암호화 벤치마크 실행 중 시스템 전체의 총 CPU 소비를 보여줍니다:

../../../_images/bench_wireguard_rr_1_process_cpu.png

WireGuard vs IPsec

이 섹션에서는 WireGuard와 IPsec을 사용한 Cilium 암호화를 비교합니다. WireGuard가 더 높은 최대 처리량을 달성할 수 있어요:

../../../_images/bench_wireguard_ipsec_tcp_stream_1_stream.png

하지만 10Gbit/s의 처리량을 달성하는 데 필요한 CPU 리소스를 보면 WireGuard가 같은 처리량을 달성하는 데 덜 효율적입니다:

../../../_images/bench_wireguard_ipsec_tcp_stream_1_stream_cpu.png

Tip

이 테스트에서 IPsec이 WireGuard보다 더 잘하는 것은 어떤 면에서 예상 밖이에요. 가능한 설명은 IPsec 암호화가 AES-NI 명령어를 사용하는 반면 WireGuard 구현은 그렇지 않다는 것입니다. 이는 AES-NI 오프로드를 사용할 수 있을 때 IPsec이 더 효율적이고, 명령어 세트를 사용할 수 없을 때 WireGuard가 더 효율적이게 만듭니다.

요청/응답 속도를 보면 우리 테스트에서 IPsec이 WireGuard를 능가하고 있어요. 처리량 테스트와 달리 패킷 크기가 작게 유지되므로 MTU는 아무 효과가 없습니다:

../../../_images/bench_wireguard_ipsec_tcp_rr_1_process.png

../../../_images/bench_wireguard_ipsec_tcp_rr_1_process_cpu.png

테스트 환경 (Test Environment)

테스트 하드웨어 (Test Hardware)

모든 테스트는 일반 판매용 하드웨어를 사용해 수행됩니다.

| 항목 | 설명 | | CPU | AMD Ryzen 9 3950x, AM4 플랫폼, 3.5GHz, 16코어 / 32스레드 | | 메인보드 | x570 Aorus Master, PCIe 4.0 x16 지원 | | 메모리 | HyperX Fury DDR4-3200 128GB, XMP 3.2GHz 클록 | | 네트워크 카드 | Intel E810-CQDA2, 듀얼 포트, 포트당 100Gbit/s, PCIe 4.0 x16 | | 커널 | Linux 5.10 LTS, 튜닝 가이드 참고 |

테스트 구성 (Test Configurations)

모든 테스트는 표준화된 구성을 사용해 수행됩니다. 직접 비교를 위해 많은 요청에 따라 Calico에 대한 측정을 포함했습니다.

| 구성 이름 | 설명 | | Baseline (Node to Node) | Kubernetes 없음 | | Cilium | Cilium 1.9.6, eBPF host-routing, kube-proxy 대체, No CT | | Cilium (legacy host-routing) | Cilium 1.9.6, legacy host-routing, kube-proxy 대체, No CT | | Calico | Calico 3.17.3, kube-proxy | | Calico eBPF | Calico 3.17.3, eBPF 데이터패스, No CT |

재현 방법 (How to reproduce)

재현을 쉽게 하기 위해 이 보고서는 cilium/cilium-perf-networking에서 찾을 수 있는 스크립트 집합과 함께 제공됩니다. 이 문서의 모든 스크립트는 이 저장소를 참조합니다. 구체적으로 Terraform과 Ansible을 사용해 환경을 설정하고 벤치마크를 실행합니다. 하드웨어 플랫폼으로 Packet 베어메탈 서버를 사용하지만, 가이드는 다른 환경에 쉽게 적응할 수 있도록 구성되어 있어요.

Cilium 성능 평가 스크립트를 내려받으세요:

$ git clone https://github.com/cilium/cilium-perf-networking.git
$ cd cilium-perf-networking

Packet 서버

캡슐화와 네이티브 라우팅을 모두 평가하기 위해 Packet 머신을 "Mixed/Hybrid" 네트워크 모드로 구성하는데, 여기서 머신의 보조 인터페이스가 평평한 L2 네트워크를 공유합니다. 이는 Packet 웹 UI에서 할 수 있지만, 이 과정을 자동화하는 적절한 Terraform(버전 0.13) 파일을 포함했습니다.

$ cd terraform
$ terraform init
$ terraform apply -var 'packet_token=API_TOKEN' -var 'packet_project_id=PROJECT_ID'
$ terraform output ansible_inventory  | tee ../packet-hosts.ini
$ cd ../

위 명령은 c3.small.x86 유형의 knb-0과 knb-1이라는 두 서버를 프로비저닝하고, 공통 VLAN knb 아래에서 "Mixed/Hybrid" 네트워크 모드를 사용하도록 구성합니다. 머신은 ubuntu_20_04 OS로 프로비저닝됩니다. 또한 Ansible의 인벤토리 파일로 사용할 packet-hosts.ini 파일을 만듭니다.

서버에 ad-hoc uptime 명령을 실행해 성공적으로 프로비저닝되었는지 확인하세요.

$ cat packet-hosts.ini
[master]
136.144.55.223 ansible_python_interpreter=python3 ansible_user=root prv_ip=10.67.33.131 node_ip=10.33.33.10 master=knb-0
[nodes]
136.144.55.225 ansible_python_interpreter=python3 ansible_user=root prv_ip=10.67.33.133 node_ip=10.33.33.11
$ ansible -i packet-hosts.ini all -m shell -a 'uptime'
136.144.55.223 | CHANGED | rc=0 >>
09:31:43 up 33 min,  1 user,  load average: 0.00, 0.00, 0.00
136.144.55.225 | CHANGED | rc=0 >>
  09:31:44 up 33 min,  1 user,  load average: 0.00, 0.00, 0.00

다음으로 packet-disbond.yaml 플레이북을 사용해 머신의 네트워크 인터페이스를 구성합니다. 이렇게 하면 bond0 인터페이스가 파괴되고 첫 번째 물리 인터페이스에 공용·사설 IP(prv_ip), 두 번째에 평가에 사용할 노드 IP(node_ip)가 구성됩니다(Packet 문서와 스크립트 참고).

$ ansible-playbook -i packet-hosts.ini playbooks/packet-disbond.yaml

Note

Packet이 아닌 하드웨어 플랫폼의 경우 사용자가 자체 인벤토리 파일(packet-hosts.ini)을 제공하고 후속 단계를 따라야 해요.

필요한 소프트웨어 설치

netperf 설치(원시 호스트 간 측정용):

$ ansible-playbook -i packet-hosts.ini playbooks/install-misc.yaml

kubeadm과 그 의존성 설치:

$ ansible-playbook -i packet-hosts.ini playbooks/install-kubeadm.yaml

kubenetbench를 사용해 Kubernetes 환경에서 netperf 벤치마크를 실행합니다. kubenetbench는 클러스터가 배포된 CNI나 네트워킹 플러그인에 종속되지 않는 Kubernetes 벤치마킹 프로젝트예요. 이 보고서에서는 서로 다른 노드 사이의 파드 간 통신에 초점을 맞춥니다. kubenetbench를 설치하려면:

$ ansible-playbook -i packet-hosts.ini playbooks/install-kubenetbench.yaml

벤치마크 실행

터널링 (Tunneling)

터널링(캡슐화) 모드로 Cilium을 구성하세요:

$ ansible-playbook -e mode=tunneling -i packet-hosts.ini playbooks/install-k8s-cilium.yaml
$ ansible-playbook -e conf=vxlan -i packet-hosts.ini playbooks/run-kubenetbench.yaml

첫 번째 명령은 Cilium을 터널링(-e mode=tunneling)을 사용하도록 구성하며, 기본적으로 VXLAN 오버레이를 사용합니다. 두 번째는 벤치마크 스위트를 실행합니다(conf 변수는 이 벤치마크 실행을 식별하는 데 사용). 실행이 끝나면 conf 변수 이름(이 경우 vxlan)의 폴더에 결과 디렉터리가 복사됩니다. 이 디렉터리에는 kubenetbench가 생성한 모든 벤치마크 결과(netperf 출력과 시스템 정보 포함)가 들어 있어요.

네이티브 라우팅 (Native Routing)

이전과 같은 작업을 반복하되, Cilium을 네이티브 라우팅(-e mode=directrouting)을 사용하도록 구성합니다.

$ ansible-playbook -e mode=directrouting -i packet-hosts.ini playbooks/install-k8s-cilium.yaml
$ ansible-playbook -e conf=routing -i packet-hosts.ini playbooks/run-kubenetbench.yaml

암호화 (Encryption)

네이티브 라우팅과 함께 암호화를 사용하려면:

$ ansible-playbook -e kubeproxyfree=disabled -e mode=directrouting -e encryption=yes -i packet-hosts.ini playbooks/install-k8s-cilium.yaml
$ ansible-playbook -e conf=encryption-routing -i packet-hosts.ini playbooks/run-kubenetbench.yaml

베이스라인 (Baseline)

결과의 기준점을 위해 Kubernetes가 실행되지 않는 호스트 사이에서 같은 벤치마크를 실행합니다. 이는 Cilium이 달성하는 성능의 효과적인 상한을 제공합니다.

$ ansible-playbook -i packet-hosts.ini playbooks/reset-kubeadm.yaml
$ ansible-playbook -i packet-hosts.ini playbooks/run-rawnetperf.yaml

첫 번째 명령은 Kubernetes를 제거하고 시스템에 잔여물이 없도록 머신을 재부팅하며, 두 번째는 호스트 사이에서 같은 벤치마크 집합을 실행합니다. 대안은 Cilium을 설정하기 전에 원시 벤치마크를 실행하는 것으로, 이 경우 두 번째 명령만 필요합니다.

정리 (Cleanup)

벤치마킹이 끝나면 할당된 Packet 리소스를 다음으로 해제할 수 있어요:

$ cd terraform && terraform destroy -var 'packet_token=API_TOKEN' -var 'packet_project_id=PROJECT_ID'

더 알아보기 (Learn more)