1. 쿠버네티스 성능 측정 및 최적화 환경 구축
쿠버네티스의 성능과 Cilium CNI의 성능 테스트를 위해 kind 클러스터를 사용하여 환경을 구성했습니다.
실습 환경 구성
먼저 kind 클러스터를 생성하고, 성능 모니터링을 위한 도구들을 설치했습니다:
kind create cluster --name myk8s --image kindest/node:v1.33.2 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 30000
- containerPort: 30001
hostPort: 30001
- containerPort: 30002
hostPort: 30002
- containerPort: 30003
hostPort: 30003
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
controllerManager:
extraArgs:
bind-address: 0.0.0.0
etcd:
local:
extraArgs:
listen-metrics-urls: http://0.0.0.0:2381
scheduler:
extraArgs:
bind-address: 0.0.0.0
- |
kind: KubeProxyConfiguration
metricsBindAddress: 0.0.0.0
EOF
이 구성에서는 Prometheus가 클러스터 구성요소(kube-controller-manager, kube-scheduler, etcd, kube-proxy)의 메트릭을 수집할 수 있도록 bind-address 설정을 추가했습니다.
추가로 모니터링 도구를 설치했습니다:
- kube-ops-view: 클러스터 노드와 파드 상태를 시각화
- metrics-server: 기본적인 리소스 메트릭 수집
- kube-prometheus-stack: 완전한 모니터링 스택(Prometheus, Grafana)
특히 그라파나에는 두 가지 중요한 대시보드를 추가했습니다:
- K8S NEW 대시보드(ID: 15661): 전반적인 클러스터 상태 모니터링
- K8S API 대시보드(ID: 12006): API 서버의 성능 관련 지표 모니터링
2. Kube-burner를 이용한 성능 테스트
쿠버네티스의 성능을 측정하기 위해 kube-burner라는 도구를 사용했습니다. 이 도구는 쿠버네티스 리소스를 대규모로 생성, 삭제, 수정하면서 성능을 측정할 수 있습니다.
kube-burner 설치
curl -LO https://github.com/kube-burner/kube-burner/releases/download/v1.17.3/kube-burner-V1.17.3-darwin-arm64.tar.gz
tar -xvf kube-burner-V1.17.3-darwin-arm64.tar.gz
sudo cp kube-burner /usr/local/bin
시나리오 1: 단일 디플로이먼트 생성 및 삭제 테스트
첫 번째 테스트에서는 간단한 디플로이먼트 1개를 생성하고 삭제하는 시나리오를 실행했습니다. 이 과정에서 jobIterations, qps, burst 매개변수의 의미를 살펴보겠습니다.
global:
measurements:
- name: none
jobs:
- name: create-deployments
jobType: create
jobIterations: 1 # 작업 반복 횟수
qps: 1 # 초당 최대 요청 수
burst: 1 # 일시적 최대 요청 버퍼 크기
namespace: kube-burner-test
namespaceLabels: {kube-burner-job: delete-me}
waitWhenFinished: true
verifyObjects: false
preLoadImages: true
preLoadPeriod: 30s
objects:
- objectTemplate: s1-deployment.yaml
replicas: 1
여기서 중요한 매개변수들의 의미를 실험을 통해 확인했습니다:
- jobIterations: 작업을 몇 번 반복할 것인지 결정
- qps: 초당 처리할 수 있는 최대 요청 수 (평균 속도 제한)
- burst: 순간적으로 처리할 수 있는 최대 요청 수 (버퍼)
- preLoadImages: 테스트 전에 노드에 컨테이너 이미지를 미리 로드할지 여부
다양한 매개변수 조합으로 테스트한 결과:
qps: 1, burst: 10, jobIterations: 10: 버스트 값이 jobIterations보다 크면 모든 작업이 한 번에 처리qps: 1, burst: 1, jobIterations: 10: 1초에 1개씩 순차적으로 처리qps: 1, burst: 10, jobIterations: 20: 처음에 버스트 값만큼 처리하고, 나머지는 qps에 따라 처리
이런 테스트를 통해 kube-burner가 쿠버네티스 API 서버에 요청을 어떻게 전송하는지, 그리고 API 서버가 어떻게 반응하는지 관찰할 수 있었습니다.
시나리오 2: 노드 1대에 최대 파드 배포 시도
두 번째 시나리오에서는 단일 노드에 최대한 많은 파드를 배포하는 테스트를 진행했습니다. 기본적으로 쿠버네티스 노드는 최대 110개의 파드만 호스팅할 수 있도록 제한되어 있습니다.
100개 이상의 파드를 배포하려고 시도했을 때, 다음과 같은 오류가 발생했습니다:
0/1 nodes are available: 1 Too many pods. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.
이 문제를 해결하기 위해 kubelet 설정을 수정했습니다:
docker exec -it myk8s-control-plane bash
vim /var/lib/kubelet/config.yaml
# maxPods: 150 으로 수정
systemctl restart kubelet
maxPods 값을 150으로 증가시킨 후에는 더 많은 파드를 배포할 수 있었습니다.
시나리오 3: 노드 1대에 300개 이상 파드 배포 시도
세 번째 시나리오에서는 최대 파드 수를 400으로 늘리고 300개의 파드를 배포하려 했지만, 새로운 제한에 도달했습니다:
Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox: failed to allocate for range 0: no IP addresses available in range set: 10.244.0.1-10.244.0.254
이 문제는 노드의 CIDR 할당이 /24(256 IP 주소)로 제한되어 있어서 발생했습니다. 노드가 할당받은 IP 범위를 확인해보니:
kubectl describe node | grep -i podcidr
PodCIDR: 10.244.0.0/24
이 문제를 해결하려면 노드의 CIDR 마스크 크기를 조정해야 합니다. 클러스터 생성 시 다음과 같이 설정할 수 있습니다:
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
controllerManager:
extraArgs:
node-cidr-mask-size: "22" # 더 많은 IP 할당 가능 (1024개 IP)
3. 쿠버네티스 성능 고려사항 및 튜닝
대규모 클러스터 운영 가이드라인
쿠버네티스 v1.33 기준 단일 클러스터의 최대 지원 규모:
- 최대 5,000대의 노드
- 노드당 최대 110개 파드
- 최대 150,000개 총 파드
- 최대 300,000개 총 컨테이너
API 서버와 etcd 성능 이슈
API 서버와 etcd에서 발생할 수 있는 성능 이슈에 대해 자세히 살펴보았습니다. 특히 LIST 요청이 문제가 될 수 있습니다.
파드 10,000개에 대한 LIST 요청 실험 결과:
- 응답 시간: 약 2.1초 (100개 요청 대비 70배 이상 증가)
- 응답 크기: 약 44.4MB (100개 대비 약 100배)
더 심각한 문제는 메모리 사용량입니다:
- etcd: 요청당 약 30-60MB 메모리 필요
- kube-apiserver: 요청당 약 100MB 메모리 필요 (JSON 데이터 크기의 2.5배)
100개의 동시 요청이 오면 API 서버는 몇 초 만에 6GB 이상의 메모리를 사용하게 되어 OOM(Out Of Memory) 상황이 발생할 수 있습니다.
성능 문제 해결 방법
API 성능 문제를 해결하기 위한 주요 접근법:
- Limit/Continue 사용:
- 한 번에 모든 리소스를 요청하지 않고, 페이지네이션 활용
- 대부분의 쿠버네티스 클라이언트는 최대 500개씩 요청하도록 구현
- ResourceVersion/ResourceVersionMatch 활용:
resourceVersion=0으로 설정하면 API 서버 캐시에서 데이터 제공- etcd로 요청이 가지 않아 부하 감소
- API Priority and Fairness (APF) 설정:
- 중요한 요청과 덜 중요한 요청에 대해 다른 우선순위 부여
- FlowSchema와 PriorityLevelConfiguration 리소스를 사용하여 설정
- 운영 관점의 접근:
- 불필요한 리소스 주기적으로 정리
- 클러스터 크기에 맞게 etcd 최적화 (로컬 SSD 사용 등)
- Event API를 별도의 etcd 클러스터로 분리
OpenAI의 대규모 클러스터 운영 사례
OpenAI가 2,500대에서 7,500대로 클러스터를 확장한 사례를 공유했습니다.
- etcd를 네트워크 스토리지에서 로컬 SSD로 이동시켜 지연 시간 200μs 감소
- 과도한 LIST 요청을 하는 Fluentd와 Datadog 설정 조정
- ARP 캐시 설정 최적화:
net.ipv4.neigh.default.gc_thresh1 = 80000 net.ipv4.neigh.default.gc_thresh2 = 90000 net.ipv4.neigh.default.gc_thresh3 = 100000- 7,500대 클러스터에서 각 API 서버는 약 70GB 메모리 사용
- EndpointSlices 사용으로 네트워크 대역폭 요구량 1/1000 이하로 감소
API 서버 플래그 최적화
성능 최적화를 위한 주요 API 서버 플래그:
--max-requests-inflight=400 # 비변경(GET, LIST) 요청 최대 처리량
--max-mutating-requests-inflight=200 # 변경(POST, PUT, DELETE) 요청 최대 처리량
기본값은 비변경 요청 400개, 변경 요청 200개로, 총 600개의 동시 요청을 처리할 수 있습니다. 클러스터 크기와 요청 패턴에 따라 이 값을 조정할 수 있습니다.
4. Cilium 성능 및 최적화
두 번째 파트에서는 Cilium CNI의 성능과 최적화 방법을 알아봅니다.
Cilium 설치 및 성능 테스트
Cilium을 kind 클러스터에 설치했습니다:
cilium install --version 1.18.1 --set ipam.mode=kubernetes \
--set ipv4NativeRoutingCIDR=172.20.0.0/16 \
--set routingMode=native --set autoDirectNodeRoutes=true --set endpointRoutes.enabled=true \
--set kubeProxyReplacement=true --set bpf.masquerade=true \
--set hubble.enabled=true --set hubble.relay.enabled=true --set hubble.ui.enabled=true
네트워크 성능 측정을 위해 iperf3를 사용했습니다:
- TCP 테스트:
iperf3 -c iperf3-server -t 5(5초간 TCP 성능 측정) - 양방향 TCP 테스트:
iperf3 -c iperf3-server -t 5 --bidir(양방향 동시 측정) - 다중 스트림 테스트:
iperf3 -c iperf3-server -t 10 -P 2(2개 병렬 스트림)
테스트 결과:
- 양방향 TCP 테스트: Client→Server: 53.6 Gbps, Server→Client: 39.9 Gbps
- 약간의 패킷 손실(Retransmit TX=11, RX=14)이 있었지만 전반적으로 우수한 성능
Cilium Endpoint Slices (CES)


대규모 클러스터에서 Cilium의 성능을 향상시키는 중요한 기능인 Cilium Endpoint Slices(CES)를 살펴봅니다:
- 기존 방식: 노드 5,000개 x 파드 100개 = 500,000개의 CiliumEndpoint 개체 관리
- CES 사용: CiliumEndpointSlice로 여러 엔드포인트를 그룹화하여 API 서버 부하 감소
CES를 활성화하는 방법:
helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \
--set ciliumEndpointSlice.enabled=true
CES 활성화 후 결과:

- 1,000개 노드 클러스터에서 API 서버 지연 시간 87% 감소
- 개별 CiliumEndpoint 대신 소수의 CiliumEndpointSlice로 관리
eBPF Host Routing과 Netkit
Cilium의 네트워크 성능을 향상시키는 두 가지 중요한 기술인 eBPF Host Routing과 Netkit에 대해 알아봅니다:
- eBPF Host Routing:
bpf_redirect_peer함수를 사용하여 호스트 네트워크 네임스페이스에 도착한 패킷을 직접 파드 네임스페이스로 전달- 전통적인 veth 인터페이스 방식보다 성능 향상
- 현재 상태 확인:
cilium status | grep Routing→Routing: Network: Native Host: BPF
- Netkit 디바이스:
- veth와 유사하지만 인그레스와 이그레스 큐 대기 시간 없이 패킷 전달
- 호스트 네트워크 성능과 거의 동일한 수준의 컨테이너 네트워킹 성능 제공
- 요구사항: 커널 6.7 이상 및 CONFIG_NETKIT 지원
helm upgrade cilium cilium/cilium --set bpf.datapathMode=netkit
BIG TCP
Cilium의 최신 성능 향상 기능인 BIG TCP에 대해서도 알아봅니다:
- 100Gbps 이상 환경에서 패킷 처리 성능 향상을 위한 기술
- 기존 GRO/TSO는 64KB로 제한되지만, BIG TCP는 최대 512KB 패킷 사용
- IPv6 BIG TCP: IPv6의 Hop-by-Hop 확장 헤더를 사용해 더 큰 패킷 크기 지원
- IPv4 BIG TCP: Linux 커널 6.3부터 지원, 소켓 버퍼에 저장된 페이로드 길이 활용
BIG TCP 활성화 방법:
helm upgrade cilium cilium/cilium --version 1.18.0 --reuse-values --set enableIPv4BIGTCP=true
BIG TCP 활성화 후 결과:
- TPS 42% 증가
- 파드 간 지연 시간 2.2배 감소
- MTU 변경 없이도 성능 향상 (점보 프레임과 달리 물리적 네트워크 설정 변경 불필요)
기타 Cilium 성능 최적화 방법
- XDP 기반 가속:
- L4 로드 밸런싱을 위한 XDP 가속 기능
- 하드웨어 지원 필요
cilium status --verbose | grep -i xdp
- eBPF 맵 사이징:
- 노드 총 메모리 비율에 따라 eBPF 맵 크기 조정
helm upgrade cilium cilium/cilium --reuse-values --set bpf.mapDynamicSizeRatio=0.01
- 노드 총 메모리 비율에 따라 eBPF 맵 크기 조정
- Kubernetes API 서버 연결 최적화:
- Cilium 1.18부터 여러 API 서버 지원
```bash - -set k8s.apiServerURLs="[https://172.21.0.4:6443 https://172.21.0.5:6443 https://172.21.0.6:6443]"
- Cilium 1.18부터 여러 API 서버 지원
5. Linux 커널 네트워크 최적화
마지막으로, 리눅스 커널 수준에서의 네트워크 최적화에 대해 살펴봅니다.
- TuneD 프로필 사용:
- network-latency 또는 network-throughput 프로필 적용
tuned-adm profile network-throughput
- network-latency 또는 network-throughput 프로필 적용
- TCP 파라미터 최적화:
- TCP 타임스탬프, 윈도우 스케일링, 혼잡 제어 알고리즘 등 조정
- 대부분의 커널 파라미터 중 약 1/3이 네트워크 관련 설정
- TSO, GRO 활용:
- TSO(TCP Segmentation Offload): 큰 TCP 세그먼트를 NIC가 분할하도록 함
- GRO(Generic Receive Offload): 수신 패킷을 더 큰 버퍼로 병합
ethtool -k eth1 | grep tcp-segmentation-offload ethtool -k eth1 | grep generic-receive-offload
클러스터 규모와 워크로드 특성에 따라 적절한 최적화 기법을 적용하고, 지속적인 모니터링을 통해 성능 문제를 조기에 발견하고 해결하는 것이 중요합니다. 특히 쿠버네티스와 Cilium 모두 버전이 올라갈수록 성능이 크게 개선되므로, 정기적인 버전 업그레이드 계획을 세우는 것도 중요한 운영 전략입니다.
댓글