CNI là thứ quyết định pod nhận IP thế nào và gói tin đi từ node này sang node kia ra sao. Bài này dựng hai cụm giống hệt nhau, đổi mỗi CNI, và đo.

Thông lượng hai CNI và nguyên nhân trong bảng định tuyến

Số đo

Cùng máy, cùng iperf3, cùng cấu hình cụm — chỉ khác plugin mạng:

Cùng node Khác node
kindnet 121 Gbit/s 87,4 Gbit/s
Calico 89,3 Gbit/s 45,6 Gbit/s

Khác node là chỗ chênh nhau nhiều nhất: Calico chậm 48%.

Bộ nhớ node: kindnet 431,2 MB, Calico 487,8 MB — +13%.

Nguyên nhân nằm trong bảng định tuyến

kindnet — định tuyến thuần, không đóng gói:

10.244.1.0/24 via 172.21.0.7 dev eth0
10.244.2.0/24 via 172.21.0.8 dev eth0

Mỗi node có một dải pod riêng, và các node biết dải của nhau qua tuyến tĩnh. Gói tin đi từ pod này sang pod kia là gói tin IP bình thường, không thêm gì.

Calico — đường hầm IPIP, định tuyến bằng BGP:

blackhole 192.168.95.128/26 proto bird
192.168.146.64/26 via 172.21.0.9 dev tunl0 proto bird onlink

Hai chi tiết:

dev tunl0 — mỗi gói tin liên node bị bọc thêm một lớp IP header. Đó là 20 byte mỗi gói, cộng công đóng gói và mở gói ở hai đầu.

proto bird — tuyến do daemon BGP học được, không phải khai tay. Đây là điểm mạnh của Calico: nó tự lan truyền tuyến trong mạng lớn, không cần ai cấu hình.

Đó là 48% chênh lệch, và nó chỉ xuất hiện khi đi giữa các node. Cùng node thì cả hai đều đi qua veth cục bộ, và chênh lệch nhỏ hơn.

Qua Service tốn thêm gần như không có gì

pod -> pod khác node, trực tiếp     87,4 Gbit/s
pod -> pod khác node, qua Service   85,9 Gbit/s      -1,7%

Chặng DNAT của iptables (phần 56) gần như miễn phí.

Điều này đáng nhớ khi tối ưu: cái đắt là đóng gói, không phải chuyển địa chỉ. Bỏ Service để gọi thẳng podIP không mua lại gì đáng kể, và mất hết lợi ích về khám phá dịch vụ.

Ba kiểu CNI

Định tuyến thuần (kindnet, Calico chế độ BGP không đóng gói, Cilium chế độ native routing) — nhanh nhất, nhưng đòi mạng bên dưới biết đường tới dải pod. Trong một mạng phẳng thì được; qua nhiều mạng con thì cần cấu hình router.

Đóng gói (Calico IPIP/VXLAN, Flannel VXLAN) — chạy được ở mọi nơi, kể cả khi mạng bên dưới không biết gì về pod. Cái giá là con số ở trên.

eBPF (Cilium) — thay iptables bằng chương trình eBPF trong kernel. Nhanh hơn ở phần Service khi số service lớn (phần 56 đã đo iptables tăng tuyến tính), và cho khả năng quan sát tốt hơn nhiều. Tôi không đo được nó trong bài này.

Chọn thế nào

Mạng phẳng, mọi node cùng mạng con → chế độ định tuyến thuần. Nhanh nhất, đơn giản nhất.

Calico bật được chế độ này: CALICO_IPV4POOL_IPIP=Never. Khi ấy nó không đóng gói và thông lượng gần với kindnet, nhưng vẫn giữ BGP và NetworkPolicy đầy đủ.

Node ở nhiều mạng con, hoặc trên đám mây không cho tuyến tuỳ ý → đóng gói. Trả 48% và đổi lấy việc nó chạy ở mọi nơi.

Cụm lớn, nhiều nghìn service, cần quan sát sâu → Cilium với eBPF.

Cụm nhỏ, học tập, CI → cái gì có sẵn. kindnet đủ, và phần 59 cho thấy nó thực thi cả NetworkPolicy.

Điểm quan trọng: CNI rất khó đổi trên cụm đang chạy. Nó là quyết định lúc dựng, và đổi thường có nghĩa là dựng cụm mới rồi chuyển tải sang.

MTU: chỗ hay hỏng nhất

Với CNI đóng gói, MTU của giao diện pod phải nhỏ hơn MTU mạng bên dưới, đủ chỗ cho header thêm vào — 20 byte cho IPIP, 50 byte cho VXLAN.

Đặt sai thì triệu chứng rất khó chịu: gói nhỏ đi bình thường, gói lớn im lặng biến mất. ping chạy, curl trang nhỏ chạy, tải tệp lớn thì treo. Và nó chỉ xuất hiện giữa các node, không xuất hiện trong cùng node.

kubectl exec <pod> -- ip link show eth0 | grep -o "mtu [0-9]*"

Nếu MTU pod bằng đúng MTU của node mà CNI có đóng gói, đó là cấu hình sai đang chờ lộ ra.

Ghi chú về con số tuyệt đối

Các con số ở đây rất cao — 121 Gbit/s không phải tốc độ mạng thật. MTU pod trong môi trường đo là 65535, và mọi node đều nằm trong một máy ảo Docker trên cùng một máy vật lý, nên không có dây nào cả.

Trên phần cứng thật với MTU 1500 và mạng 10 Gbit, con số tuyệt đối sẽ nhỏ hơn nhiều lần.

Nhưng tỉ lệ giữa hai CNI thì giữ nguyên, vì nguyên nhân là chi phí đóng gói trên mỗi gói tin, không phải tốc độ dây. Đó là lý do phép đo này vẫn nói lên điều gì đó dù chạy trong một hộp.

Thử ba mươi giây

Xem CNI của bạn có đóng gói không:

# trên một node
ip route | grep -E "tunl|vxlan|flannel"

Có dòng nào chứa tunl0, vxlan, hoặc flannel.1 nghĩa là mọi gói tin liên node đang bị bọc thêm một lớp. Không có dòng nào nghĩa là định tuyến thuần — nhanh hơn, và phụ thuộc vào mạng bên dưới nhiều hơn.

Phần sau đo ConfigMap và Secret: cấu hình vào pod bằng cách nào, và thay đổi có tự lan tới không.