eBPF Maps
eBPF Maps (BPF 맵)
Cilium의 데이터 경로는 여러 eBPF 맵을 사용하며, 각 맵에는 상한 용량 제한이 있어요. 이 글에서는 맵별 기본 한도 값과 명령줄 옵션으로 한도를 조정하는 방법, 동적 크기 조정에 대해 설명해요.
출처: eBPF Maps
본문
모든 BPF 맵은 상한 용량 제한과 함께 생성돼요. 이 한도를 넘어 삽입하려 하면 실패하고, 그 결과 데이터 경로의 확장성이 제한돼요. 아래 표는 맵의 기본값을 보여줘요. 각 한도는 소스 코드에서 늘릴 수 있고, 필요가 생기면 요청에 따라 설정 옵션이 추가되기도 해요.
| Map Name | Scope | Default Limit | Scale Implications |
|---|---|---|---|
| Auth | node | 512k | Max 512k authenticated relations per node |
| Connection Tracking | node | 512k TCP/256k UDP | Max 512k concurrent TCP connections, max 256k expected UDP answers |
| NAT | node | 512k | Max 512k NAT entries |
| Neighbor Table | node | 512k | Max 512k neighbor entries |
| Endpoints | node | 64k | Max 64k local endpoints + host IPs per node |
| IP cache | node | 512k | Max 256k endpoints (IPv4+IPv6), max 512k endpoints (IPv4 or IPv6) across all clusters |
| Service Load Balancer | node | 64k | Max ~3k clusterIP/nodePort Services across all clusters (see: service map sizing section for details). |
| Service Backends | node | 64k | Max 64k cumulative unique backends across all services across all clusters |
| Service Source Ranges | node | 64k | Max 64k cumulative LB source ranges across all services |
| Service Session Affinity | node | 64k | Max 64k affinities from different clients |
| Policy | endpoint | 16k | Max 16k allowed identity + port + protocol pairs for specific endpoint |
| IPv4 Fragmentation | node | 8k | Max 8k fragmented datagrams in flight simultaneously on the node |
| IPv6 Fragmentation | node | 8k | Max 8k fragmented datagrams in flight simultaneously on the node |
| IPv4 Masq | node | 16k | Max 16k IPv4 cidrs used by BPF-based ip-masq-agent |
| IPv6 Masq | node | 16k | Max 16k IPv6 cidrs used by BPF-based ip-masq-agent |
| Egress Policy | node | 16k | Max 16k endpoints across all destination CIDRs across all clusters |
| Node | node | 16k | Max 16k distinct node IPs (IPv4 & IPv6) across all clusters. |
일부 BPF 맵은 cilium-agent의 명령줄 옵션으로 상한 용량을 재정의할 수 있어요. 특정 용량은 --bpf-auth-map-max, --bpf-ct-global-tcp-max, --bpf-ct-global-any-max, --bpf-nat-global-max, --bpf-neigh-global-max, --bpf-policy-map-max, --bpf-fragments-map-max, --bpf-lb-map-max 옵션으로 설정할 수 있어요.
Note
--bpf-ct-global-tcp-max또는--bpf-ct-global-any-max를 지정한 경우, NAT 테이블 크기(--bpf-nat-global-max)는 결합된 CT 테이블 크기(TCP + UDP)의 2/3을 초과하면 안 돼요. 이 값은--bpf-nat-global-max를 명시적으로 설정하지 않았거나 동적 BPF 맵 크기 조정을 사용할 때 자동으로 설정돼요 (아래 참고).
--bpf-map-dynamic-size-ratio 플래그를 사용하면 여러 큰 BPF 맵의 상한 용량이 에이전트 시작 시 전체 시스템 메모리의 주어진 비율을 기준으로 결정돼요. 예를 들어 비율 0.0025를 주면 전체 시스템 메모리의 0.25%를 이 맵들에 사용하게 돼요.
이 플래그는 시스템에서 메모리를 가장 많이 사용하는 다음 BPF 맵에 영향을 줘요: cilium_ct_{4,6}_global, cilium_ct_{4,6}_any, cilium_nodeport_neigh{4,6}, cilium_snat_v{4,6}_external, cilium_lb{4,6}_reverse_sk.
kube-proxy는 머신의 코어 수를 기준으로 리눅스 커넥션 트래킹 테이블의 최대 항목 수를 설정해요. kube-proxy는 코어당 최대 32768개 항목을 기본값으로 하고, 코어 수와 무관하게 최소 131072개 항목을 보장해요.
Cilium은 자체 커넥션 트래킹 테이블을 BPF 맵으로 갖고 있으며, 이 맵의 항목 수는 노드의 총 메모리 양을 기준으로 계산돼요. 머신의 메모리 양과 무관하게 최소 131072개 항목을 보장해요.
Cilium을 --bpf-map-dynamic-size-ratio: 0.0025로 설정했을 때 kube-proxy와 Cilium이 각자의 커넥션 트래킹 테이블에 설정하는 값을 아래 표에서 보여줘요.
| vCPU | Memory (GiB) | Kube-proxy CT entries | Cilium CT entries |
|---|---|---|---|
| 1 | 3.75 | 131072 | 131072 |
| 2 | 7.5 | 131072 | 131072 |
| 4 | 15 | 131072 | 131072 |
| 8 | 30 | 262144 | 284560 |
| 16 | 60 | 524288 | 569120 |
| 32 | 120 | 1048576 | 1138240 |
| 64 | 240 | 2097152 | 2276480 |
| 96 | 360 | 3145728 | 4552960 |
Service LB Map Sizing
Cilium은 cilium_lb{4,6}_services_v2라는 이름의 LB 서비스 맵을 사용해서 clusterIP 및 nodePort 서비스 타입의 Service 로드 밸런서 항목을 보관해요. 이 맵들은 --bpf-lb-map-max 플래그로 설정되며 기본값은 64k예요. 이 맵이 가득 차면 Cilium이 Service 업데이트를 동기화하지 못할 수 있고, 이는 서비스 IP 연결성에 영향을 주거나 새 서비스를 만들지 못하게 할 수 있어요.
서비스 LB 맵의 필요 크기는 여러 요인에 따라 달라져요. 각 clusterIP/nodePort 서비스는 해당 Service가 선택한 Pod 백엔드 수에 서비스 spec의 포트/프로토콜 항목 수를 곱한 만큼의 항목을 생성해요.
(\text{LB map entries per Service} = (\text{number of endpoints per service}) * (\text{number of port/protocols per service}))
이를 이용해 필요한 맵 크기를 대략 이렇게 구할 수 있어요:
(\text{LB map entries} \approx (\text{number of LB services}) * (\text{avg number of endpoints per service}) * (\text{avg number of port/protocols per service}))
Note 이 휴리스틱은 서비스별 선택된 Pod 수와 포트/프로토콜 항목 수가 대략 정규분포를 따른다고 가정해요. 사용 사례에 큰 이상치가 있다면 (예: 매우 많은 Pod 백엔드를 선택하는 서비스), 더 정밀한 추정이 필요할 수 있어요.
Cilium이 노드의 서비스 LB 맵을 생성한 후(즉, 노드에서 Cilium 에이전트를 처음 실행했을 때) 맵 크기 파라미터를 바꾸고 Cilium을 재시작하면, 새 맵이 기존 서비스 항목으로 다시 채워지면서 커넥션 중단이 발생해요. 따라서 이런 중단이 우려된다면 Cilium을 설치하기 전에 맵 요구 사항을 신중히 검토하는 것이 중요해요.