Mạng Linux & Container/CNI là gì — interface gắn mạng cho pod
17/21
Bài 17 / 21~16 phútKubernetes Networking (nhập môn)Miễn phí lượt xem

CNI là gì — interface gắn mạng cho pod

CNI là interface (không phải implementation): plugin Flannel/Calico/Cilium, lúc tạo pod CNI được gọi, trade-off overlay (VXLAN) vs routed.

TL;DR: CNI (Container Network Interface)hợp đồng giữa container runtime và plugin mạng: runtime gọi binary plugin với lệnh ADD/DEL/CHECK…; plugin tạo iface trong netns pod, gán IP, route, đôi khi policy. Kubernetes không “built-in Calico” — kubelet/CRI nhờ CNI thực hiện pod network model. Flannel / Calico / Ciliumimplementation khác nhau (overlay VXLAN, BGP/routed, eBPF…). Trade-off lớn: overlay (đóng gói dễ qua subnet/cloud) vs routed (L3 thuần, ít encapsulation, ops routing/BGP). Pitfall cứng: cài CNI không implement NetworkPolicy → YAML policy xanh, traffic vẫn full-mesh.

On-call: cluster kind demo “default CNI”, junior apply NetworkPolicy default-deny rồi báo “policy không ăn — K8s bug”. kubectl get networkpolicies có object; kubectl exec pod A vẫn curl pod B. Bạn hỏi: “CNI nào? Plugin có policy enforcement không?” Nhiều lab CNI chỉ lo connectivity (ADD IP + route), không dataplane filter theo NetworkPolicy API. Object API tồn tại; effect = 0. Không phải RBAC, không phải nhãn sai trước — sai expectation về implementation.

Bài 01 chốt contract pod IP + shared netns. Bài này chốt ai gắn cáp: interface CNI, lifecycle ADD/DEL, bản đồ plugin, overlay vs routed.

1. Analogy — Ổ cắm chuẩn, nhiều hãng thiết bị

Pod modelnội quy toà nhà: mỗi căn một số máy, gọi nhau không qua NAT. Ai kéo cáp mỗi lần có cư dân mới?

  1. CNI spec = chuẩn ổ cắm / giao thức thợ: “khi có căn mới, thợ nhận lệnh ADD kèm path netns + tên iface; khi dọn căn, lệnh DEL”.
  2. Runtime (containerd/CRI-O + kubelet) = ban quản lý tạo căn (netns) rồi gọi thợ, không tự viết mọi hãng switch.
  3. Plugin binary (bridge, flannel, calico, cilium-cni…) = đội thợ / hãng thiết bị — cách kéo cáp khác nhau, cùng “ổ” ADD/DEL.
  4. Config JSON trên node (/etc/cni/net.d/…) = hợp đồng gói thầu cố định: subnet, backend VXLAN hay BGP, IPAM…
Đời thườngCNI
Chuẩn gọi thợCNI Specification
Ban quản lýContainer runtime (+ kubelet)
Đội thợPlugin executable (type trong config)
Sổ lệnh ADD/DELCNI_COMMAND + env + JSON stdin
Căn hộ (ns)CNI_NETNS path
Tên cổng trong cănCNI_IFNAME (thường eth0)
💡 Cách nhớ

Học interface trước brand. “Cluster dùng Calico” = chọn implementation cho cùng contract pod model — không phải Kubernetes đổi TCP/IP.

2. CNI là interface — không phải implementation

2.1 Định nghĩa theo spec

CNI Spec định nghĩa:

  1. Format cấu hình mạng (JSON: name, cniVersion, list plugins…).
  2. Protocol runtime → plugin: env vars + config stdin, result/error stdout.
  3. Thứ tự thực thi khi chain nhiều plugin.
  4. Delegation (vd IPAM plugin con).
  5. Result types (IP, iface, route, DNS…).

Ba thuật ngữ spec:

  • container — domain isolation (thường = network namespace).
  • network — nhóm endpoint addressable nói chuyện được với nhau.
  • runtime — chương trình gọi plugin.
  • plugin — chương trình áp cấu hình mạng.

Kubernetes docs nói rõ: phần lớn runtime Linux dùng CNI; các pod network implementation thường được gọi CNI plugins — nhưng model do K8s định nghĩa, cáp do plugin.

2.2 Runtime gọi gì? (operations)

CommandViệc plugin làm (tóm tắt)
ADDTạo/chỉnh iface CNI_IFNAME trong CNI_NETNS; gán IP/route; trả result JSON
DELGỡ iface / hoàn tác ADD; nên succeed cả khi resource đã mất (idempotent-ish)
CHECKĐối chiếu prevResult — iface/IP/route/policy còn đúng?
VERSIONBáo spec versions plugin hỗ trợ
GC / STATUSDọn stale / sẵn sàng nhận ADD (spec hiện đại)

Tham số env cốt lõi: CNI_COMMAND, CNI_CONTAINERID, CNI_NETNS, CNI_IFNAME, CNI_PATH, CNI_ARGS.

sequenceDiagram
    participant RT as Runtime CRI
    participant PL as CNI plugin
    participant NS as Pod netns
    RT->>RT: create netns sandbox
    RT->>PL: ADD + CNI_NETNS + IFNAME
    PL->>NS: veth move IP route
    PL-->>RT: result JSON IPs ifaces
    Note over RT,PL: pod running
    RT->>PL: DEL
    PL->>NS: cleanup iface IPAM

2.3 Lifecycle gắn pod (Linux)

Theo spec Lifecycle & Ordering (rút gọn đúng mental model K8s):

  1. Runtime tạo network namespace (sandbox/pause) trước khi gọi plugin.
  2. ADD (có thể chain nhiều plugin trong list config — plugin sau nhận prevResult).
  3. Pod chạy; IP nằm trong result → kubelet report pod.status.podIP.
  4. Pod xoá / fail path: runtime DEL (spec: ADD fail vẫn nên DEL cleanup); DEL có thể lặp.
  5. Netns cleanup là trách nhiệm runtime.

Không parallel ADD/DEL cùng container; được song song khác container. Plugin phải lock tài nguyên dùng chung (IPAM file, v.v.).

📌 Interface plugin vs chained vs IPAM

Interface plugin tạo eth trong ns + connectivity. Chained (portmap, tuning, firewall…) chỉnh thêm trên prevResult. IPAM thường delegate: plugin chính gọi binary IPAM (host-local, dhcp…) để lấy địa chỉ rồi tự apply lên iface.

3. Bản đồ implementation — Flannel, Calico, Cilium

Không phải catalog marketing đủ feature — bản đồ đủ để đọc architecture review:

Plugin (họ)Hướng dataplane phổ biếnNetworkPolicyGhi chú nhập môn
FlannelThường overlay (VXLAN) hoặc backend host-gwHạn chế / không phải full policy engineĐơn giản lab connectivity; đừng expect zero-trust YAML
CalicoRouted (BGP/route) và/hoặc overlay tuỳ config; iptables/nft/eBPF modes (policy engine mạnh)Hay gặp production “L3 + policy”
CiliumeBPF dataplane; overlay hoặc native routing (+ Hubble observe)Identity/policy giàu; ops eBPF/kernel

Các mảnh khác bạn sẽ gặp tên: Amazon VPC CNI, Azure CNI, Weave (legacy), kindnet (kind), Antrea… Cùng ổ CNI, khác cách implement pod CIDR và policy.

flowchart TB
    MODEL["K8s pod network model"] --> IFACE["CNI interface ADD DEL"]
    IFACE --> FL["Flannel family"]
    IFACE --> CA["Calico family"]
    IFACE --> CI["Cilium family"]
    IFACE --> OT["Cloud VPC CNI kindnet ..."]
    FL --> OV["Often overlay VXLAN"]
    CA --> RT["Often routed BGP"]
    CI --> EB["eBPF dataplane"]

Chọn nhanh (heuristic, không dogma):

  • Lab / “pod ping pod trước”: CNI đơn giản (kindnet/Flannel-style) OK.
  • Cần NetworkPolicy production: chọn plugin document rõ enforce policy (Calico/Cilium/…); verify trên đúng distro/version.
  • Multi-AZ cloud với routing hạn chế: overlay đôi khi “dễ lên”; bare-metal L3 sạch: routed/BGP thường gọn hơn encapsulation.

4. Overlay hay routed — trade-off chọn thế nào?

Cả hai nhằm giữ model: gói giữa pod mang pod IP nguồn/đích (no NAT east-west). Khác nhau ở đường giữa node.

4.1 Overlay — đóng gói

Ý tưởng: trên node A, gói từ pod được bọc (encapsulate) thành gói outer (thường UDP) gửi tới node B; node B tháo vỏ, đưa vào veth pod đích.

VXLAN (ví dụ phổ biến): VNI + VTEP; underlay chỉ cần IP connectivity node-to-node.

flowchart LR
    PA["Pod A IP"] --> NA["Node A VTEP"]
    NA -->|"outer UDP VXLAN"| NB["Node B VTEP"]
    NB --> PB["Pod B IP"]
ƯuNhược
Chạy được khi underlay không biết route pod CIDRMTU/overhead encapsulation; debug thêm lớp outer
“Lấp” multi-subnet/cloud dễ hơn cho team appCPU/throughput encapsulation (mức độ tuỳ offload)
Topology pod logic tách underlayTroubleshooting: tcpdump cả underlay và inner

4.2 Routed — L3 thuần

Ý tưởng: mỗi node quảng bá (static route, BGP, …) “các IP pod của tôi đi qua tôi”. Router/underlay chuyển gói không bọc VXLAN (trong thiết kế pure routed).

flowchart LR
    PA["Pod A"] --> NA["Node A"]
    NA -->|"L3 route pod CIDR"| FAB["Underlay fabric"]
    FAB --> NB["Node B"]
    NB --> PB["Pod B"]
ƯuNhược
Ít overhead encapsulation; MTU đơn giản hơnUnderlay/BGP ops: scale route, policy routing
Dễ “nhìn” gói pod IP trên fabric (tuỳ design)Cloud/VPC có lúc giới hạn route custom → ép overlay hoặc CNI cloud-native
Khớp tư duy L3 thuần Module foundationsSai route table = “pod khác node timeout” dù cùng node OK

4.3 Bảng so sánh một trang

TrụcOverlay (vd VXLAN)Routed (vd BGP/host-gw)
Outer headerCó (node→node)Không (trong pure form)
Underlay cần biết pod CIDR?Không (chỉ VTEP/node IP)Có (route tới node “sở hữu” dải)
MTUPhải trừ encapsulationGần MTU underlay
DebugHai lớpRoute/BGP + veth
Gần lab M2Bridge local + tunnel giữa hostBridge/route local + ip route giữa host
Thử đoán

Hai node, pod CIDR khác nhau. tcpdump trên eth0 underlay node A khi pod A ping pod B. Overlay VXLAN: bạn kỳ vọng thấy ICMP echo trần pod IP hay UDP tới port VXLAN? Routed pure: khác gì?

Đáp án kỳ vọng: Overlay — thường thấy UDP (outer) giữa IP node; inner mang ICMP pod. Routed — thường thấy IP packet dst = pod B (hoặc next-hop) không bọc VXLAN. (Chi tiết port/VNI tuỳ backend — mental model đủ để chọn điểm bắt gói.)

5. Worked: đọc config CNI trên node (minh hoạ)

Tên path phổ biến (có thể khác distro):

# On a Kubernetes node (or kind node shell) — read-only survey
ls /etc/cni/net.d/ 2>/dev/null || echo "no /etc/cni/net.d"
ls /opt/cni/bin/ 2>/dev/null | head

# Example: show JSON list (do not paste secrets; lab only)
# sudo cat /etc/cni/net.d/*.conflist

Skeleton config list (minh hoạ — không copy production):

{
  "cniVersion": "1.1.0",
  "name": "cluster-network",
  "plugins": [
    {
      "type": "bridge",
      "bridge": "cni0",
      "ipam": {
        "type": "host-local",
        "subnet": "10.244.0.0/24"
      }
    }
  ]
}

Đọc field:

FieldÝ nghĩa
typeTên binary trong CNI_PATH (vd /opt/cni/bin/bridge)
ipam.typePlugin IPAM delegated
nameTên network config (unique trên host)
plugins[]Chain: ADD xuôi, DEL ngược

Khi pod Pending mãi với event mạng: kiểm CNI config có không, binary có trong PATH, log runtime/kubelet — trước khi nghi app image.

6. Pitfall — CNI không hỗ trợ NetworkPolicy

Kubernetes luôn có API NetworkPolicy. Docs network model nói thẳng:

  • NetworkPolicy thường do pod network implementation enforce.
  • Một số implementation đơn giản không implement policy, hoặc admin tắt.
  • Khi đó API object vẫn apply (etcd xanh) nhưng không có hiệu lực trên dataplane.
Dấu hiệuDiễn giải
kubectl get networkpolicy có resourceChỉ chứng minh API server — không chứng minh enforce
Traffic full-mesh dù default-denyPlugin không filter / sai CNI / kind lab CNI mỏng
Docs plugin ghi “supports NetworkPolicy”Điều kiện cần — vẫn phải test deny rule thật
Đổi sang Calico/Cilium + rule đơn giản chặn đượcEnforce path đã “có người nghe” API

Quy trình an toàn trước khi tin zero-trust YAML:

  1. Xác định CNI đang chạy (DaemonSet/docs cluster).
  2. Đọc matrix NetworkPolicy support đúng version.
  3. Test: hai pod label khác nhau, policy deny, curl phải fail; xoá policy → pass.
  4. Không pass → đừng ship compliance dựa trên object tồn tại.

Chi tiết design rule: 05 — NetworkPolicy. Bài này chỉ đóng đinh: interface CNI ≠ mọi plugin làm đủ feature matrix.

⚠️ 'CNI hỏng' vs 'sai model expectation'

Pod không có IP / FailedCreatePodSandBox → nghi ADD fail (config, IPAM cạn, binary missing).
Pod IP có, ping khác node fail → nghi route/overlay/underlay.
Policy không chặn → nghi thiếu enforce, không phải “quên apply” nếu object đã có. Ba class khác nhau — đừng một câu “restart CNI”.

📚 Deep Dive — tài liệu gốc

📚 Deep Dive — tài liệu gốc

Spec / docs:

Nội bộ OLHub:

Liên hệ các bài khác

Tóm tắt

  • CNI = spec + protocol plugin; Kubernetes compose model, plugin implement cáp/IP/policy.
  • ADD/DEL (và CHECK…) gắn đời pod sandbox; runtime tạo ns trước, plugin gắn iface.
  • Flannel / Calico / Cilium — bản đồ overlay / routed+policy / eBPF — chọn theo capability, không theo hype.
  • Overlay vs routed: encapsulation vs L3 underlay — MTU, ops, debug khác nhau; cả hai phục vụ no-NAT pod IP model.
  • Pitfall: NetworkPolicy không enforce nếu CNI không support — test deny thật, đừng tin mỗi kubectl get.

7. Tự kiểm tra

Tự kiểm tra
Q1
CNI là 'interface' nghĩa là gì — phân biệt với 'cluster đang chạy Calico'? Ai gọi binary plugin, ai implement veth/IP?
Interface = spec/protocol (config JSON + ADD/DEL/… + result). Calico là một implementation (plugin + agents) tuân thủ/đi cùng CNI. Runtime/CRI+kubelet path gọi binary; plugin implement chi tiết veth/IP/route/policy. K8s không hardcode một vendor trong model pod IP.
Q2
Thứ tự lifecycle: netns tạo trước hay sau CNI ADD? Vì sao DEL vẫn chạy khi ADD fail (theo tinh thần spec)?
Runtime tạo network namespace (sandbox) trước ADD; plugin nhận CNI_NETNS path để gắn iface. ADD fail có thể để lại resource dở; spec yêu cầu cleanup — runtime vẫn nên DEL để plugin gỡ IPAM/iface sót, tránh leak.
Q3
Map nhanh Flannel vs Calico vs Cilium theo hai trục: dataplane điển hình và NetworkPolicy. Lab kind chỉ cần ping pod — chọn họ nào 'đủ', production zero-trust cần thêm gì?
Flannel: thường overlay/host-gw, policy yếu/không đủ. Calico: routed/BGP (hoặc mode khác) + policy mạnh. Cilium: eBPF + policy/observe. Lab ping: CNI mỏng (kindnet/Flannel-style) đủ. Zero-trust: plugin enforce NetworkPolicy (Calico/Cilium/…) + test deny thật.
Q4
So sánh overlay VXLAN và pure routed: underlay có phải biết pod CIDR không? MTU/debug khác gì? Cả hai có phá model 'no NAT pod-to-pod' không?
Overlay: underlay chủ yếu thấy node/VTEP IP; pod CIDR trong inner; MTU trừ header; debug hai lớp. Routed: underlay/route phải đưa gói tới node sở hữu pod CIDR; ít encap. Cả hai giữ src/dst pod IP end-to-end trong model — encapsulation không phải NAT rewrite địa chỉ pod.
Q5
Junior apply NetworkPolicy default-deny, object Ready, traffic pod-to-pod vẫn full. Liệt kê checklist chẩn đoán theo thứ tự ưu tiên (CNI trước hay label trước)?
(1) CNI nào / docs có NetworkPolicy enforce? (2) Test control: policy đơn giản có chặn được không trên cluster này. (3) Nếu CNI không enforce → đổi plugin hoặc chấp nhận API no-op. (4) Nếu CNI có enforce mới soi selector label, namespace, port, direction. Ưu tiên 'có ai enforce không' trước khi mổ YAML label 30 phút.
Q6
Đọc field type và ipam.type trong CNI JSON list — mỗi field trỏ tới object gì trên disk? Sai type binary missing → triệu chứng pod phía K8s gần đúng là gì?
type = tên executable plugin trong CNI_PATH (vd /opt/cni/bin/...). ipam.type = binary IPAM delegated. Thiếu binary/config → ADD fail → pod sandbox lỗi, event kiểu FailedCreatePodSandBox / network not ready, pod không có podIP usable.
Q7
Vì sao học CNI interface trước brand giúp debug 'Service OK, pod-to-pod khác node fail' tốt hơn chỉ đọc YAML Deployment?
Service path (bài 03) giả định endpoint pod IP reachable. Fail khác node là class pod network/CNI/underlay (route, overlay, MTU), không phải image app. Biết ADD tạo path L3 giúp chọn đúng lớp: ip route/VNI/BGP thay vì restart Deployment vòng tròn.

Bài tiếp theo: Service & kube-proxy — traffic tới pod thế nào

Bài này đáng gửi cho bạn học cùng?

Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.

Bài này có giúp bạn hiểu bản chất không?

Hỏi đáp về bài này

Chưa có câu hỏi

Đặt câu hỏi

Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).

Đặt câu hỏi đầu tiên

Bài tiếp theo

Service & kube-proxy — traffic tới pod thế nào