CNI Evolution & Dataplane V2 — kubenet, Calico, eBPF/Cilium
Vì sao chủ đề này quan trọng
Lựa chọn dataplane là một trong những quyết định bất biến khi tạo cluster GKE: trên nhiều phiên bản, bạn không thể bật Dataplane V2 cho một cluster đã tạo theo mô hình cũ (GKE Dataplane V2). Chọn sai nghĩa là hoặc chấp nhận sống với trần hiệu năng của iptables, hoặc phải tạo lại cluster và migrate toàn bộ workload — một dự án tốn kém.
Quan trọng hơn, dataplane quyết định ba thứ định hình toàn bộ trải nghiệm vận hành mạng: (1) Service được cân bằng tải bằng iptables hay eBPF; (2) NetworkPolicy được thực thi theo IP/iptables hay theo identity/eBPF; (3) bạn có công cụ quan sát cấp kernel (Hubble) hay không. Hiểu sự tiến hóa từ kubenet → Calico → Dataplane V2 không phải để hoài niệm lịch sử, mà để biết chính xác mình đang đứng ở đâu trên trục đánh đổi và vì sao Google đẩy mọi cluster mới về eBPF.
Internal model: ba thế hệ dataplane
kubenet (legacy): đơn giản nhưng đã cạn đường
kubenet là plugin mạng tối giản của Kubernetes. Trên GKE, kubenet kết hợp với route của VPC để định tuyến Pod: kubelet tạo một Linux bridge (cbr0) trên node, mỗi Pod nối vào bridge qua một veth pair, và traffic ra ngoài node dựa vào route do GKE quản lý.
Đặc điểm và giới hạn:
- Không hỗ trợ NetworkPolicy bản thân nó. kubenet chỉ lo connectivity cơ bản; muốn có policy phải thêm thành phần khác.
- Gắn với mô hình routes-based ở nhiều cấu hình, kéo theo các giới hạn route quota đã nói ở file 1.
- Ít observability. Không có cơ chế nhìn sâu vào quyết định drop/allow.
kubenet đang bị loại bỏ dần khỏi Kubernetes upstream và không phải lựa chọn cho cluster GKE production hiện đại. Nó chỉ còn ý nghĩa khi bạn gặp một cluster rất cũ chưa migrate.
Calico CNI: mang NetworkPolicy đến iptables
Trước khi có Dataplane V2, cách phổ biến để có NetworkPolicy trên GKE là bật add-on dựa trên Calico (Network policy enforcement with Calico). Calico (ở chế độ GKE dùng) dịch các đối tượng NetworkPolicy của Kubernetes thành quy tắc iptables và ipset trên từng node.
Mô hình này hoạt động và phổ biến nhiều năm, nhưng có trần cấu trúc:
- NetworkPolicy theo IP. Calico khớp policy dựa trên IP/CIDR của Pod nguồn và đích. Khi Pod churn cao (scale, rollout), tập IP thay đổi liên tục, kéo theo việc cập nhật ipset/iptables liên tục.
- iptables là tuyến tính. Như sẽ phân tích kỹ ở file 4, iptables đánh giá rule theo chuỗi; số rule tăng theo số Service × Endpoint và số policy × Pod, dẫn tới chi phí CPU và latency điều khiển tăng phi tuyến ở cluster lớn.
- Lock contention. Cập nhật iptables phải giữ lock kernel, serialize các thay đổi; ở cluster có nhiều thay đổi đồng thời, đây là điểm nghẽn.
Nói cách khác, Calico giải quyết được vấn đề “có NetworkPolicy” nhưng kế thừa toàn bộ trần hiệu năng của iptables.
GKE Dataplane V2: eBPF/Cilium thay thế iptables
GKE Dataplane V2 là dataplane dựa trên Cilium, dùng eBPF để xử lý gói ngay trong kernel thay vì duyệt chuỗi iptables (GKE Dataplane V2). Đây là thay đổi kiến trúc, không phải tinh chỉnh.
Các thành phần chính:
anetd DaemonSet. Google triển khai một agent dựa trên Cilium dưới dạng DaemonSet tên anetd, chạy trên mỗi node trong namespace kube-system. anetd đọc các đối tượng Kubernetes (Service, Endpoint/EndpointSlice, NetworkPolicy, Pod) và lập trình topology mạng vào eBPF — tức nạp/ cập nhật các chương trình eBPF và eBPF map tương ứng vào kernel của node.
eBPF programs trong kernel. Thay vì DNAT/filtering bằng chuỗi iptables, các quyết định (Service load balancing, policy enforcement, masquerade) được thực hiện bởi chương trình eBPF gắn vào các hook của kernel (ví dụ tại tc/XDP, socket). Tra cứu backend của Service trở thành tra hash map O(1) thay vì duyệt chuỗi rule O(n).
Không cần kube-proxy. Vì eBPF tự đảm nhiệm cân bằng tải Service, các phiên bản Dataplane V2 loại bỏ kube-proxy và do đó loại bỏ luôn nút thắt iptables (GKE Dataplane V2). Đây là khác biệt cốt lõi sẽ được mổ xẻ ở file 4.
NetworkPolicy luôn bật + logging tích hợp. Trên cluster Dataplane V2, thực thi NetworkPolicy là một phần của dataplane (không cần add-on riêng), và Google cung cấp network policy logging tích hợp để quan sát kết nối được phép/bị chặn thông qua một CRD cấu hình (Network policy logging). Chi tiết ở file 5.
Cilium identity model: vì sao “theo label” thắng “theo IP”
Đây là điểm khác biệt khái niệm quan trọng nhất giữa Dataplane V2 và Calico, và nó giải thích vì sao eBPF/Cilium scale tốt hơn ở môi trường churn cao.
Trong mô hình truyền thống, policy được biểu diễn theo IP: “cho phép 10.4.1.5 nói chuyện với 10.4.2.9”. Vấn đề là Pod IP thay đổi liên tục — mỗi lần Pod restart, scale, hay reschedule, IP đổi, và toàn bộ rule liên quan phải được tính lại và nạp lại. Ở cluster lớn với rollout thường xuyên, đây là dòng cập nhật bất tận.
Cilium thay bằng security identity: nó gom các Pod có cùng tập label bảo mật thành một identity (một số nguyên). Policy được biểu diễn theo identity, không theo IP. Khi một Pod mới của cùng workload xuất hiện (cùng label), nó nhận lại đúng identity đã có; eBPF map ánh xạ IP → identity được cập nhật, nhưng các rule policy theo identity không cần thay đổi.
Hệ quả thực chiến:
- Ổn định khi churn cao. Scale từ 10 lên 100 Pod của cùng một Deployment không tạo ra 90 rule mới — chỉ cập nhật ánh xạ IP→identity.
- Policy dễ suy luận. Bạn nghĩ theo “workload nào nói chuyện với workload nào”, đúng với cách Kubernetes mô hình hóa bằng label selector.
- Nền tảng cho L7/FQDN. Vì xử lý ở eBPF với ngữ cảnh identity, Cilium hỗ trợ được policy phong phú hơn (ví dụ egress theo FQDN), điều iptables thuần khó làm sạch sẽ.
eBPF vs iptables: số liệu và đánh đổi
Giới hạn quy mô của Dataplane V2
Google công bố các giới hạn quy mô cụ thể cho cluster Dataplane V2 (GKE Dataplane V2 scalability):
| Hạng mục | Giới hạn |
|---|---|
| Node mỗi cluster regional | ~5.000 (lên tới ~15.000 với Private Service Connect) |
| Pod mỗi cluster | 400.000 |
| Pod mỗi Service | 10.000 |
| ClusterIP Service | 10.000 |
| LoadBalancer Service | 750 |
| Tổng dung lượng endpoint map | ~260.000 entry |
Con số đáng chú ý nhất với kiến trúc sư là 260.000 entry trong endpoint map — đây là giới hạn cứng của eBPF map ánh xạ Service backend. Ở cluster cực lớn, tổng số (Service × Endpoint) phải nằm dưới ngưỡng này. Đây là lý do giới hạn “10.000 Pod mỗi Service” tồn tại, và là điểm cần tính khi thiết kế các Service có rất nhiều backend.
So sánh bản chất
| Tiêu chí | iptables (kube-proxy/Calico) | eBPF (Dataplane V2) |
|---|---|---|
| Tra cứu backend Service | Duyệt chuỗi rule, ~O(n) | Hash map, ~O(1) |
| Cập nhật khi endpoint đổi | Resync chuỗi, có thể tốn kém | Cập nhật map cục bộ |
| Mô hình policy | Theo IP/CIDR | Theo identity (label) |
| kube-proxy | Cần | Không cần |
| Observability cấp kernel | Hạn chế | Hubble (built-in) |
| Lock contention | Có (iptables lock) | Giảm mạnh |
Đánh đổi và giới hạn của Dataplane V2
Không có bữa trưa miễn phí. Tài liệu Google nêu rõ một số ràng buộc (GKE Dataplane V2):
- Không bật được trên cluster đã tạo (ở nhiều phiên bản). Phải tạo cluster mới — quyết định ngay từ đầu.
- Không hỗ trợ chương trình eBPF tùy biến của người dùng. Nạp eBPF riêng có thể xung đột với chương trình của Dataplane V2.
- Xung đột với một số công cụ eBPF bên thứ ba. Các agent observability/security dựa trên eBPF có thể không tương thích.
- Gói ICMP phân mảnh có thể bị drop. Cần lưu ý với các giao thức/path nhạy cảm MTU.
- CPU cao khi vòng đời TCP connection quay vòng quá nhanh. Pattern tạo/đóng kết nối liên tục có thể đẩy CPU agent lên cao.
Production architecture patterns
Pattern 1: Mặc định Dataplane V2 cho cluster mới
Trừ khi có lý do tương thích cụ thể (ví dụ phụ thuộc một agent eBPF bên thứ ba không tương thích), cluster production mới nên bật Dataplane V2 ngay từ lúc tạo để có sẵn NetworkPolicy, logging và Hubble, đồng thời tránh trần iptables. Quyết định này không lùi được dễ dàng nên đừng để mặc định ngẫu nhiên.
Pattern 2: Thiết kế Service tránh chạm endpoint map limit
Với các Service “fan-out” cực lớn (hàng nghìn backend), cần tính tổng (Service × Endpoint) so với trần ~260.000. Cân nhắc tách Service, dùng EndpointSlice hợp lý, hoặc kiến trúc lại để không dồn quá nhiều backend vào một Service.
Pattern 3: Đánh giá tương thích eBPF trước khi onboard agent bên thứ ba
Vì Dataplane V2 không cho nạp eBPF tùy biến, mọi công cụ security/observability dựa trên eBPF phải được kiểm thử tương thích trên cluster staging trước. Đừng giả định một agent eBPF chạy tốt trên cluster thường sẽ chạy trên Dataplane V2.
Real-world scenarios
Scenario A: Cluster lớn “nghẹt” vì iptables resync
Một cluster Calico ~3.000 Service, hàng chục nghìn endpoint. Mỗi rollout lớn kích hoạt resync iptables tốn kém; p99 latency điều khiển tăng, đôi khi kube-proxy/Calico tụt hậu so với thực tế endpoint, gây traffic đến Pod đã chết trong vài giây.
Hướng xử lý dài hạn: migrate sang cluster Dataplane V2 (tạo mới + blue-green), nơi cập nhật endpoint là thao tác map cục bộ thay vì resync chuỗi.
Scenario B: Team cần biết “vì sao gói bị drop” nhưng không có dữ liệu
Trên cluster Calico/iptables, khi NetworkPolicy chặn một kết nối, gói im lặng biến mất, team mất hàng giờ đoán. Trên Dataplane V2, network policy logging ghi lại kết nối allow/deny và Hubble cho phép truy vết flow theo identity.
Bài học: observability không phải tính năng phụ; nó là lý do chính đáng để chọn Dataplane V2.
Scenario C: Agent bảo mật eBPF bên thứ ba làm cluster bất ổn
Một đội cài agent runtime-security dựa trên eBPF lên cluster Dataplane V2 mà không kiểm thử. Agent cố gắn vào hook đã được anetd dùng, gây hành vi mạng bất thường.
Bài học: tôn trọng ràng buộc “không eBPF tùy biến”; kiểm thử tương thích trên staging.
Common mistakes / anti-patterns
- Để dataplane ở giá trị mặc định mà không quyết chủ động. Đây là quyết định bất biến, phải cân nhắc kỹ.
- Giả định có thể bật Dataplane V2 sau. Ở nhiều phiên bản thì không; phải tạo cluster mới.
- Dồn quá nhiều backend vào một Service. Có thể chạm trần endpoint map ở cluster lớn.
- Nạp eBPF tùy biến hoặc agent eBPF chưa kiểm thử. Rủi ro xung đột với
anetd. - Vẫn dùng Calico/kubenet cho cluster lớn mới. Tự nhận trần iptables và thiếu observability.
- Bỏ qua cảnh báo CPU
anetdkhi connection churn cao. Cần tối ưu connection pooling/keep-alive ở ứng dụng.
GCP-native implementation guidance
Tạo cluster bật Dataplane V2
gcloud container clusters create prod-cluster \
--region=asia-southeast1 \
--enable-dataplane-v2 \
--enable-ip-alias \
--network=prod-vpc \
--subnetwork=gke-subnet \
--cluster-secondary-range-name=pods \
--services-secondary-range-name=servicesKiểm tra dataplane và thành phần anetd
# Xác nhận Dataplane V2 đang bật
gcloud container clusters describe prod-cluster \
--region=asia-southeast1 \
--format="value(networkConfig.datapathProvider)"
# Kỳ vọng: ADVANCED_DATAPATH
# Kiểm tra anetd DaemonSet
kubectl -n kube-system get daemonset anetd -o wide
kubectl -n kube-system get pods -l k8s-app=cilium -o wideBật network policy logging (Dataplane V2)
apiVersion: networking.gke.io/v1alpha1
kind: NetworkLogging
metadata:
name: default
spec:
cluster:
allow:
log: true
delegate: false
deny:
log: true
delegate: falseKết nối với Architecture Framework
- Performance optimization: chuyển từ tra cứu O(n) của iptables sang O(1) của eBPF là một quyết định kiến trúc có tác động trực tiếp tới hiệu năng ở scale (Architecture Framework).
- Operational excellence: observability built-in (logging + Hubble) giảm thời gian chẩn đoán sự cố mạng, đúng tinh thần giảm toil (Operational excellence).
References
- GKE Dataplane V2
- Network policy enforcement (Calico)
- Network policy logging
- GKE network overview
- Cilium eBPF datapath (tham khảo upstream)
- Kubernetes Network Plugins (CNI)
- Google Cloud Architecture Framework
Phụ lục: đọc hiểu kiến trúc Dataplane V2 ở mức vận hành
anetd làm gì mỗi giây
Hình dung anetd như một “trình biên dịch” liên tục: nó theo dõi (watch) các đối tượng từ API server — Service, EndpointSlice, NetworkPolicy, Pod, Node — và mỗi khi có thay đổi, nó cập nhật eBPF map và chương trình tương ứng trên node của mình. Khác với kube-proxy phải viết lại chuỗi iptables, anetd chỉ cập nhật entry trong map; chi phí cập nhật nhỏ và cục bộ.
Khi debug, hai câu hỏi đầu tiên thường là: (1) anetd trên node đó có khỏe không (kubectl -n kube-system get pods); (2) eBPF map có phản ánh đúng endpoint hiện tại không (kiểm tra qua Hubble/cilium CLI — xem file 6).
Vì sao endpoint map limit là con số cần nhớ
eBPF map có dung lượng cố định được cấp khi nạp. Endpoint map ~260.000 entry là “ngân sách” cho toàn bộ ánh xạ Service→backend của cluster. Khác với iptables (rule tăng thì chậm dần nhưng không có “trần cứng” rõ ràng), eBPF map có giới hạn cứng — chạm trần là lỗi, không phải chỉ chậm. Đây là khác biệt tư duy: với eBPF bạn phải capacity plan cho map như một tài nguyên hữu hạn.
Identity model và bảo mật
Vì policy theo identity, một cuộc tấn công lateral movement khó hơn: kẻ tấn công chiếm được một Pod không tự động “thành” một identity khác chỉ bằng đổi IP, vì identity gắn với label do control plane cấp. Tuy nhiên điều này cũng nghĩa là quản trị label trở thành vấn đề bảo mật — gán label cẩu thả có thể vô tình mở rộng quyền truy cập của một workload.
Khi nào Dataplane V2 không phải lựa chọn
- Khi bạn bắt buộc phải nạp chương trình eBPF tùy biến cho mục đích khác.
- Khi phụ thuộc một công cụ eBPF bên thứ ba không tương thích và không thể thay thế.
- Khi workload cực kỳ nhạy cảm với gói ICMP phân mảnh và không thể điều chỉnh MTU/path.
Trong các trường hợp này, cần đánh giá kỹ và có thể phải chấp nhận mô hình cũ — nhưng đây là ngoại lệ, không phải mặc định.
Lộ trình migrate sang Dataplane V2 ở cấp cluster
Vì ở nhiều phiên bản không bật được Dataplane V2 in-place, migration thực tế là một dự án blue-green cấp cluster:
- Dựng cluster mới đã bật Dataplane V2, dùng đúng IP plan đã chuẩn hóa (file 1) để tránh chồng lấn với cluster cũ.
- Chuyển trạng thái nền tảng: cài lại các add-on (ingress controller, service mesh, observability) và đối chiếu NetworkPolicy — lưu ý policy theo IP/CIDR cũ cần viết lại theo label để tận dụng identity model.
- Migrate workload theo nhóm: bắt đầu từ stateless ít rủi ro, dùng DNS/traffic weighting để chuyển dần (multi-cluster DNS hoặc cập nhật bản ghi), quan sát kỹ NetworkPolicy logging để bắt các đường bị chặn nhầm.
- Soak rồi cutover: giữ cả hai cluster song song một thời gian, theo dõi Hubble và metrics, rồi rút cluster cũ.
Điểm dễ sai nhất khi migrate là NetworkPolicy: trên cluster cũ Calico theo IP, một số policy “tình cờ đúng” nhờ IP cố định; trên Dataplane V2 theo identity, chúng phải được biểu diễn lại theo label, nếu không sẽ chặn nhầm hoặc mở rộng quá mức.
CiliumEndpoint và cách identity hiện diện trong cluster
Trên Dataplane V2, mỗi Pod được Cilium đại diện bằng một endpoint nội bộ, và identity được chia sẻ giữa các Pod cùng tập label. Điều quan trọng với người vận hành: identity là tài nguyên cấp cluster có số lượng hữu hạn về mặt thực tế — nếu bạn tạo ra quá nhiều tổ hợp label bảo mật khác nhau (ví dụ nhúng giá trị động, unique vào label dùng cho policy), số identity phình ra, làm tăng chi phí quản lý và cập nhật map. Nguyên tắc: label dùng cho policy nên thuộc một tập hữu hạn, ổn định (như app, tier, team), không nên là giá trị có cardinality cao (như request ID, pod hash).
FAQ thực chiến
Có bật Dataplane V2 cho cluster đang chạy được không?
Ở nhiều phiên bản thì không bật in-place được; cách phổ biến là tạo cluster mới với Dataplane V2 rồi migrate workload. Hãy kiểm tra tài liệu phiên bản hiện hành trước khi lên kế hoạch.
Dataplane V2 có còn dùng kube-proxy không?
Không — eBPF đảm nhận cân bằng tải Service, nên kube-proxy bị loại bỏ, đồng thời loại bỏ nút thắt iptables tương ứng.
NetworkPolicy trên Dataplane V2 khác Calico thế nào?
Calico dịch policy thành iptables/ipset theo IP; Dataplane V2 thực thi bằng eBPF theo Cilium identity (label), ổn định hơn khi Pod churn cao và hỗ trợ logging/observability tích hợp.
Giới hạn 260.000 endpoint map có ý nghĩa gì với tôi?
Đó là trần cứng cho tổng ánh xạ Service→backend. Ở cluster rất lớn, cần thiết kế Service để tổng (Service × Endpoint) nằm dưới ngưỡng, tránh dồn quá nhiều backend vào một Service.
Tôi có thể chạy agent eBPF bên thứ ba cùng Dataplane V2 không?
Phải kiểm thử tương thích trên staging trước; Dataplane V2 không hỗ trợ eBPF tùy biến và một số agent có thể xung đột với anetd.