OVS Phần 19: OVS trong Kubernetes (OVN-Kubernetes, Antrea CNI)
Phần 19/21 trong loạt Open vSwitch (OVS) — Bài 18 vừa cho thấy một Cloud Management System (CMS) là OpenStack Neutron có thể cắm thẳng vào OVN core (Bài 17) qua đúng vai trò "OVN/CMS Plugin", trong khi vẫn giữ song song một kiến trúc khác hoàn toàn không dùng OVN (ML2/OVS, agent Python tự tính flow). Bài 19 lặp lại đúng cấu trúc câu chuyện đó ở một CMS khác hẳn: Kubernetes. Container Network Interface (CNI) — lớp plugin chịu trách nhiệm cấp mạng cho Pod — cũng có một nhánh cắm thẳng vào OVN core (OVN-Kubernetes) và một nhánh dùng OVS nhưng tự tính OpenFlow không qua OVN (Antrea). Điểm khác quan trọng nhất so với Bài 18: OVN-Kubernetes không dùng lại nguyên xi mô hình triển khai OVN "giáo khoa" đã học ở Bài 17 — nó đổi hẳn sang một kiến trúc mới gọi là "interconnect", đây sẽ là trọng tâm Mục 2-3 của bài.
Mục tiêu bài học: sau bài này bạn xác nhận được OVN-Kubernetes dùng lại đúng bốn thành phần lõi OVN (NB DB, ovn-northd, SB DB, ovn-controller) nhưng theo một topology triển khai khác hẳn Bài 17 — mỗi node là một "zone" tự có bộ database riêng, nối nhau qua transit switch thay vì một cụm RAFT tập trung; phân biệt rạch ròi Antrea Agent (bắt buộc, tự sinh OpenFlow) với Antrea Controller (tùy chọn, chỉ tính NetworkPolicy) — tránh nhầm Controller với vai trò ovn-northd; và đọc được một chuỗi flow OpenFlow thật của Antrea cho traffic Pod-to-Pod cùng node.
Ba câu hỏi mà bài này trả lời:
- OVN-Kubernetes có phải là "OVN Bài 17 áp thẳng cho Pod" hay không — nếu không, khác ở điểm nào trong cách NB DB/SB DB được triển khai?
- Antrea có dùng OVN không, và vì sao cái tên "Antrea Controller" dễ khiến người mới nhầm nó với
ovn-northd? - Traffic giữa hai Pod trên cùng một node có đi qua tunnel không, và Antrea tự cài đặt những OpenFlow flow nào để traffic đó đi tắt?
Mục lục
- 1. Vì sao mỗi node Kubernetes cần một con switch mềm
- 2. OVN-Kubernetes: đúng core OVN Bài 17 — nhưng nhân bản theo "interconnect"
- 3. Topology trong một zone, và transit switch nối các zone lại với nhau
- 4. Service thay kube-proxy: OVN Load_Balancer
- 5. Antrea: OVS trực tiếp — không có OVN nào cả
- 6. Bẫy dễ nhầm: "Antrea Controller" không phải là ovn-northd
- 7. Điểm giống bất ngờ: cả hai CNI đều mặc định Geneve
- 8. So sánh trực diện hai kiến trúc
- 9. CLI lab: đọc pipeline OpenFlow thật của Antrea cho Pod-to-Pod cùng node
- Bài tập cuối bài
1. Vì sao mỗi node Kubernetes cần một con switch mềm
Bài 7 đã trả lời câu hỏi tương tự cho một VM: QEMU tạo một tap device (vnetX), libvirt gắn nó vào một OVS bridge, và từ đó VM "có mạng" theo đúng nghĩa cắm dây vào switch. Một Pod Kubernetes cần đúng thứ tương tự, nhưng nhẹ hơn hẳn: không có QEMU, không có hypervisor giả lập phần cứng đầy đủ. Mỗi Pod chỉ là một network namespace — một bản sao lập trình được của ngăn xếp mạng (routing table, interface list, iptables/nftables riêng) — cách ly khỏi namespace mặc định của node. Để namespace đó "nói chuyện" được với phần còn lại của node, CNI plugin tạo một cặp veth: một đầu nằm trong network namespace của Pod (thường đặt tên eth0 bên trong Pod), đầu còn lại nằm ở namespace gốc của node và được gắn vào con switch mềm trên node đó.
💡 Hình dung như thế này: một VM ở Bài 7 giống một căn hộ riêng biệt hoàn toàn — có đồng hồ điện riêng, đường ống nước riêng (QEMU giả lập phần cứng đầy đủ), chỉ nối vào tòa nhà qua đúng một sợi cáp (tap). Một Pod giống một phòng trong ký túc xá cùng tòa nhà — không cần đồng hồ điện riêng, dùng chung hạ tầng vật lý của tòa nhà (kernel của node), nhưng vẫn có khóa cửa riêng và địa chỉ phòng riêng (network namespace) — và vẫn cần đúng một sợi dây (veth pair) nối ra hành lang chung (switch mềm trên node) để liên lạc với phòng khác. Khác nhau về "độ nặng" của căn phòng, nhưng nguyên lý "phải có một điểm cắm vào switch" thì giống hệt nhau.
Vì mọi Pod trên cùng một node đều cần điểm cắm đó, node cần một con switch mềm đứng ra làm việc học-MAC, VLAN/tunnel isolation, và (nếu cần) lọc traffic theo NetworkPolicy — đúng vai trò một OVS bridge đã đảm nhiệm cho VM ở Bài 7. Sự khác biệt giữa các CNI nằm ở ai quyết định flow chạy trên con switch đó, và bằng cơ chế nào — đây chính xác là câu hỏi Mục 2-6 dưới đây trả lời cho hai CNI phổ biến nhất dùng OVS: OVN-Kubernetes và Antrea.
2. OVN-Kubernetes: đúng core OVN Bài 17 — nhưng nhân bản theo "interconnect"
Tài liệu kiến trúc chính thức của OVN-Kubernetes mô tả một pod hệ thống tên ovnkube-node, chạy trên mọi node (không riêng control-plane), bên trong có các container sau — đối chiếu trực tiếp với bốn thành phần OVN Bài 17 đã học:
| Container | Vai trò (trích dẫn chính thức) | Đối chiếu Bài 17 |
|---|---|---|
nbdb | "Runs the OVN NBDB database", "Stores the logical elements created by ovnkube-controller" | NB DB |
northd | "Converts the OVN logical elements from NBDB to OVN logical flows in SBDB" | ovn-northd |
sbdb | "Stores the logical flows created by northd" | SB DB |
ovn-controller | "Connects to the local SBDB over a Unix socket", "Converts SBDB logical flows into openflows", ghi vào OVS | ovn-controller |
ovnkube-controller | "Allocates podIP from the podSubnet to each pod in its zone (IPAM)", "Translates K8s objects into OVN logical entities" | không có tương đương — đây là phần OVN/CMS Plugin, đóng đúng vai trò Neutron đã đóng ở Bài 18, chỉ khác CMS là Kubernetes |
Bốn cái tên đầu — NB DB, ovn-northd, SB DB, ovn-controller — khớp đúng luồng dữ liệu Bài 17 đã dạy: NB DB → ovn-northd → SB DB → ovn-controller → OpenFlow. Không có biến thể thuật toán nào ở tầng lõi. ovnkube-controller chính là "CMS Plugin" — thứ ghi vào NB DB thay cho việc bạn tự gõ ovn-nbctl tay như lab Bài 17 Mục 6.
Nhưng cách triển khai bốn thành phần đó đã đổi khác hẳn. Bài 17 mô tả đúng mô hình OVN "vanilla": một cụm NB DB và một cụm SB DB tập trung (thường dùng RAFT 3-node để HA — một thuật toán đồng thuận phân tán, cả 3 bản sao database phải bầu ra đúng 1 leader và thống nhất cùng một dữ liệu trước khi coi là ghi thành công), mọi ovn-controller trên mọi chassis cùng kết nối vào đúng một SB DB đó. OVN-Kubernetes không làm vậy. Tài liệu định nghĩa rõ:
"By default, each node in the cluster is a
zone, so eachzonecontains 1 node." — OVN-Kubernetes Architecture
Nói cách khác: mỗi node tự có một bộ NB DB + ovn-northd + SB DB + ovn-controller của riêng nó, không chia sẻ với node khác — sbdb container ghi chú thêm "runs only 1 replica, contains information local to this node". Đây gọi là kiến trúc interconnect, và nó không phải một tính năng phụ — từ bản 1.1, đây là kiến trúc mặc định:
"Support for this mode of deployment was added as part of 1.0.0 release, however it was not the default. Now, from 1.1 release, we are making this the default deployment mode of OVN-Kubernetes." — OVN-Kubernetes v1.1.0 release discussion, github.com/orgs/ovn-kubernetes/discussions/5476
Bốn lý do chính thức cho lựa chọn này, đối chiếu trực tiếp với mô hình RAFT tập trung Bài 17 đã dạy:
- Stability — database chạy standalone cục bộ từng node, loại bỏ hoàn toàn RAFT consensus và nguy cơ split-brain (tình huống cụm RAFT mất kết nối nội bộ, chia thành nhiều nhóm nhỏ và mỗi nhóm tự bầu một leader riêng — hai leader cùng tồn tại song song có thể ghi dữ liệu mâu thuẫn nhau); một node lỗi chỉ ảnh hưởng đúng node đó, không lan ra cụm.
- Scale — mỗi SB DB chỉ phục vụ đúng một kết nối
ovn-controllercục bộ, không phải hàng trăm kết nối đồng thời như mô hình tập trung. - Performance — mỗi node chỉ xử lý dữ liệu logic liên quan tới chính node đó, giảm khối lượng dữ liệu và độ trễ xử lý.
- Security — traffic điều khiển giữa
ovn-controllervà SB DB nằm gọn trong nội bộ một node, không đi qua mạng.
Đừng viết (và đừng hiểu) OVN-Kubernetes như "OVN Bài 17 y hệt, chỉ đổi VM thành Pod". Chính xác hơn: OVN-Kubernetes = đúng 4 thành phần OVN core, nhưng nhân bản thành một "mini-OVN" độc lập trên từng node, cộng thêm một tầng router mới (transit switch, Mục 3) để nối các mini-OVN đó lại với nhau.
3. Topology trong một zone, và transit switch nối các zone lại với nhau
Hệ quả trực tiếp của việc mỗi node chỉ có SB DB cục bộ: khi hai Pod trên hai node khác nhau cần nói chuyện, ovn-controller của node A không hề biết logic network của node B (vì SB DB của A không chứa dữ liệu của B). Tài liệu topology chính thức liệt kê các thực thể logic tồn tại trên mỗi zone/node để giải quyết đúng vấn đề đó:
| Thực thể | Vai trò (trích dẫn) |
|---|---|
| node-local-switch | "all the logical switch ports for the pods created on a node are bound to this switch and it also hosts load balancers that take care of DNAT-ing the service traffic" — đây chính là logical switch, mỗi Pod là một LSP, đúng khái niệm Bài 17 Mục 3 |
| distributed-ovn-cluster-router | "it's responsible for tunnelling overlay traffic between the nodes and also routing traffic between the node switches and gateway router's" |
| distributed-join-switch | "connects the ovn-cluster-router to the gateway routers" |
| node-local-gateway-router | "it's responsible for north-south traffic routing and connects the join switch to the external switch and it also hosts load balancers that take care of DNAT-ing the service traffic" |
| node-local-external-switch | "connects the gateway router to the external bridge" |
| transit-switch | "distributed across the nodes in the cluster and responsible for routing traffic between the different zones" |
Bốn thực thể đầu lặp lại đúng khái niệm logical switch/logical router/logical patch port Bài 17 Mục 3-4 đã dạy, chỉ khác là mỗi thực thể giờ tồn tại cục bộ trong một zone, thay vì trải đều toàn cụm như OVN "vanilla". Thực thể cuối — transit-switch — mới là phần hoàn toàn mới so với Bài 17: nó chính là cơ chế thay thế cho việc chia sẻ một SB DB tập trung. Traffic liên-node đi qua transit switch (qua Geneve, xem Mục 7), còn traffic trong cùng một node vẫn được mô phỏng cục bộ qua OpenFlow đúng nguyên lý "chỉ encap khi cần ra khỏi hypervisor" Bài 17 Mục 3 đã dạy — chỉ khác đơn vị "hypervisor" giờ chính là "zone", và với cấu hình mặc định một node = một zone, hai khái niệm này trùng nhau.
4. Service thay kube-proxy: OVN Load_Balancer
Một khác biệt lớn khác với vận hành Kubernetes "thường": OVN-Kubernetes thay thế hoàn toàn kube-proxy, không chạy song song. Hướng dẫn cài đặt chính thức bằng kubeadm xác nhận:
"skip the kube-proxy addon (OVN-Kubernetes provides its own service implementation)" — Launching OVN-Kubernetes with kubeadm, ovn-kubernetes.io
Cơ chế: ovnkube-controller tạo một object Load_Balancer trong NB DB mỗi khi có Service — đúng bảng NB DB Bài 17 đã dạy cách thao tác bằng ovn-nbctl. Cú pháp tạo tay (không bắt buộc trong vận hành thực tế vì OVN-Kubernetes tự động hóa toàn bộ, nhưng hữu ích để hiểu bản chất), theo đúng ovn-nbctl(8):
# vip = địa chỉ ảo (Cluster IP:port), ips = danh sách endpoint thật, cách nhau dấu phẩy
ovn-nbctl lb-add my-lb 10.96.0.10:80 "10.244.1.5:8080,10.244.2.7:8080" tcp
DNAT của Service traffic được thực hiện ngay tại node-local-gateway-router (Mục 3) — nằm trong chính logical pipeline OVN, không phải một tầng iptables/IPVS tách biệt như kube-proxy truyền thống.
5. Antrea: OVS trực tiếp — không có OVN nào cả
Rẽ sang nhánh CNI thứ hai. Tài liệu kiến trúc chính thức của Antrea mô tả gọn cấu trúc triển khai:
"In a Kubernetes cluster, Antrea creates a Deployment that runs Antrea Controller, and a DaemonSet that includes two containers to run Antrea Agent and OVS daemons respectively, on every Node." — Antrea Architecture, antrea.io/docs/main/docs/design/architecture/
Không hề có ovn-northd, không NB DB, không SB DB ở bất kỳ đâu trong tài liệu này — đây không phải khoảng trống tài liệu, mà phản ánh đúng thực tế kiến trúc: Antrea không có tầng logical-network-database trung gian nào giữa "ý định cấu hình" và OpenFlow flow thật. Ba thành phần tồn tại:
| Thành phần | Chạy ở đâu | Vai trò |
|---|---|---|
| Antrea Controller | 1 Deployment, mặc định 1 replica | Watch NetworkPolicy/Pod/Namespace, tính toán NetworkPolicy, phân phối cho Agent — chỉ liên quan NetworkPolicy |
| Antrea Agent | DaemonSet, mọi node | Quản lý OVS bridge + Pod interface, tự tính và tự cài OpenFlow flow trực tiếp |
OVS daemon (ovsdb-server + ovs-vswitchd) | Container riêng, cùng pod với Agent | Dataplane thật — đúng vai trò đã học từ Bài 1-16, không có gì đặc biệt cho Kubernetes |
Ba thứ Antrea Agent tự dựng trên mỗi node: OVS bridge br-int (tên mặc định, nơi mọi Pod veth cắm vào), antrea-gw0 — internal port đóng vai trò gateway IP cho Pod subnet cục bộ của node đó, và antrea-tun0 — tunnel port cho overlay liên-node. Agent tự tính địa chỉ tunnel đích thẳng từ việc watch Node object qua Kubernetes API, không có database logic trung gian nào lưu "topology" cả — khác hẳn cách OVN-Kubernetes phải đi qua NB DB → ovn-northd → SB DB.
6. Bẫy dễ nhầm: "Antrea Controller" không phải là ovn-northd
Đây là điểm dễ gây hiểu lầm nhất khi so sánh hai CNI, và đáng một mục riêng để tránh viết sai. Cái tên "Antrea Controller" rất dễ khiến người đọc quen với Bài 17-18 liên tưởng nó đóng vai trò tương đương ovn-northd/SB DB — một tầng biên dịch logic-network-config thành flow, mọi packet phải "đi qua" mới tồn tại được. Điều đó sai.
Bằng chứng rõ nhất nằm ngay trong tài liệu kiến trúc chính thức:
"If you only care about connectivity between Pods but not NetworkPolicy support, you may choose not to deploy Antrea Controller at all." — Antrea Architecture, antrea.io/docs/main/docs/design/architecture/
So sánh trực tiếp với OVN-Kubernetes: ở đó, cả 4 thành phần NB DB/ovn-northd/SB DB/ovn-controller đều bắt buộc cho connectivity cơ bản — thiếu bất kỳ mắt xích nào, Pod không có flow nào cả vì flow chỉ tồn tại sau khi đi qua đủ chuỗi biên dịch đó. Ở Antrea, Controller chỉ cộng thêm khả năng tính selector NetworkPolicy (podSelector/namespaceSelector) thành danh sách IP cụ thể rồi phát cho Agent — Agent mới là nơi duy nhất sinh ra OpenFlow flow, và Agent tự đủ khả năng dựng OVS bridge, tạo tunnel, forward Pod-to-Pod mà hoàn toàn không cần Controller sống.
Một điểm phụ nên biết nếu đọc mã nguồn Antrea: gói nội bộ pkg/agent/openflow có một struct tên Controller (viết hoa) — đóng vai trò OpenFlow controller cục bộ cho ovs-vswitchd trên chính node đó. Đây là chi tiết cài đặt (implementation detail) nội bộ của Agent, hoàn toàn khác với "Antrea Controller" (K8s Deployment) đang nói ở trên — hai chữ "Controller" trùng tên nhưng không cùng một khái niệm, dễ gây nhầm thêm một lớp nữa nếu đọc code mà không phân biệt rõ.
7. Điểm giống bất ngờ: cả hai CNI đều mặc định Geneve
Sau một loạt khác biệt, có một điểm hai kiến trúc lại giống nhau: cả OVN-Kubernetes lẫn Antrea đều dùng Geneve làm tunnel encapsulation mặc định — không phải VXLAN, dù VXLAN mới là dạng phổ biến ở tầng fabric vật lý (Bài 9).
Với OVN-Kubernetes, lý do giống hệt Bài 17 Mục 5 đã giải thích cho OVN nói chung: cần mang 55-bit metadata (24-bit logical datapath + 15-bit logical ingress port + 16-bit logical egress port) qua tunnel, vượt quá khả năng VXLAN (24-bit) hay GRE (32-bit) — chỉ Geneve có TLV mở rộng đủ chỗ chứa.
Với Antrea, lý do xuất phát từ nhu cầu khác — mang thêm context cho tính năng Traceflow (dò vết đường đi 1 packet), việc đổi mặc định từ VXLAN sang Geneve được ghi lại trực tiếp trong lịch sử phát triển dự án:
"Geneve supports extensible encapsulation headers which allow Antrea to add extra contexts to the encapsulated packets across Nodes. This is required by the Antrea Traceflow feature." — PR #858 "Change default tunnel type from VXLAN to Geneve", github.com/antrea-io/antrea
Cấu hình mặc định của Antrea Agent liệt kê rõ 4 loại tunnel hỗ trợ, geneve đứng đầu danh sách và là giá trị mặc định: geneve (default), vxlan, gre, stt — thuộc trường TunnelType trong TrafficEncapMode. Vậy: dù đi hai con đường khác hẳn nhau để tới cùng kết luận, cả OVN-Kubernetes và Antrea đều "chọn Geneve vì cần mang thêm metadata mà VXLAN 24-bit VNI không đủ chỗ" — chỉ khác loại metadata cần mang.
8. So sánh trực diện hai kiến trúc
| Tiêu chí | OVN-Kubernetes | Antrea |
|---|---|---|
| Dataplane | OVS (OpenFlow) | OVS (OpenFlow) — giống nhau |
| Tầng logic trung gian kiểu OVN | Có — đúng 4 thành phần OVN gốc, nhưng nhân bản theo node/zone (interconnect), không phải 1 cụm tập trung | Không có — Agent tính OpenFlow trực tiếp từ object Kubernetes nó watch được |
| "Trình biên dịch" logic → flow | ovn-northd (cục bộ từng node) dịch NB DB → SB DB, rồi ovn-controller dịch tiếp → OpenFlow (2 bước, đúng mô hình Bài 17) | Antrea Agent tự tính OpenFlow thẳng từ Pod/Node/policy đã tính sẵn (1 bước, không qua DB trung gian) |
| Vai trò "Controller" cấp cụm | ovnkube-controller/ovnkube-cluster-manager — cấp Pod subnet, dịch K8s object sang NB DB, không tính flow | Antrea Controller — chỉ tính selector NetworkPolicy → danh sách IP, không tính flow, không bắt buộc cho connectivity cơ bản |
| Nơi sinh OpenFlow flow thật | ovn-controller, chạy cục bộ mỗi node, đọc SB DB cục bộ | Antrea Agent, chạy cục bộ mỗi node |
| Service / kube-proxy | Thay thế hoàn toàn bằng Load_Balancer (NB DB construct), DNAT tại node-local-gateway-router | AntreaProxy — tùy chọn thay thế/song song kube-proxy tùy proxyAll, load balancing ngay trong pipeline OVS |
| Tunnel mặc định | Geneve (mang 55-bit metadata logic: datapath/ingress-port/egress-port) | Geneve (mang thêm context cho Traceflow) — giống nhau về lựa chọn, khác lý do |
| Node lỗi ảnh hưởng gì | Chỉ ảnh hưởng đúng zone/node đó — đúng lợi ích "Stability" Mục 2, không lan cụm | Agent chết → node đó ngừng nhận flow mới (flow cũ vẫn còn trong OVS); Controller chết → NetworkPolicy mới không được tính nhưng connectivity cơ bản không ảnh hưởng |
9. CLI lab: đọc pipeline OpenFlow thật của Antrea cho Pod-to-Pod cùng node
Tài liệu thiết kế pipeline chính thức của Antrea (docs/design/ovs-pipeline.md, cùng ví dụ minh họa được giữ nhất quán qua nhiều bản phát hành) trình bày một pipeline nhiều bảng đặt tên — bản chất vẫn là OpenFlow multi-table với goto_table/resubmit đúng nguyên lý Bài 12 đã học, chỉ khác Antrea đặt tên bảng thay vì dùng số trần trụi. Rút gọn đúng các bảng traffic Pod-to-Pod cùng node đi qua (bỏ qua các bảng chỉ liên quan Service/NetworkPolicy/Egress không cần cho ping đơn giản):
| Bảng | Vai trò trên đường đi Pod-to-Pod cùng node |
|---|---|
Classifier | Nhận diện packet đến từ port Pod cục bộ, gán FromPodRegMark |
SpoofGuard | Xác nhận cặp MAC-IP nguồn khớp đúng Pod đã đăng ký, chống giả mạo |
ConntrackZone / ConntrackState | Đưa packet vào connection tracking bằng action ct() — đúng cơ chế đã học ở Bài 13, không phải cơ chế riêng của Antrea |
L3Forwarding | Tính MAC đích thật của Pod đích; với traffic trong cùng node, không rewrite MAC (khác traffic liên-node hoặc qua Service) |
L2ForwardingCalc | Từ dl_dst tính ra port OVS egress, nạp vào register nội bộ |
Output | Xuất packet ra đúng port của Pod đích |
Ví dụ dòng flow thật, trích trực tiếp từ tài liệu chính thức (antrea.io/docs/main/docs/design/ovs-pipeline/, ba Pod minh họa client, web, db trên cùng một node, web có IP 10.10.0.24):
table=Classifier, priority=190,in_port="web-7975-274540" \
actions=set_field:0x3/0xf->reg0,set_field:0x10000000/0x10000000->reg4,goto_table:SpoofGuard
table=SpoofGuard, priority=200,ip,in_port="web-7975-274540",dl_src=fa:b7:53:74:21:a6,nw_src=10.10.0.24 \
actions=goto_table:UnSNAT
table=L3Forwarding, priority=200,ip,reg0=0/0x200,nw_dst=10.10.0.0/24 \
actions=goto_table:L2ForwardingCalc
table=L2ForwardingCalc, priority=200,dl_dst=fa:b7:53:74:21:a6 \
actions=set_field:0x25->reg1,set_field:0x200000/0x600000->reg0,goto_table:TrafficControl
(Các dòng flow trên trích nguyên văn từ ví dụ minh họa chính thức trong tài liệu thiết kế Antrea — không phải output tự dump từ một cluster trong bài này; nếu bạn có cluster Kind/Antrea thật, tự chạy ovs-ofctl dump-flows br-int để đối chiếu số liệu thật trên máy bạn, xem Bài tập 1.)
Đọc chuỗi flow trên: Classifier nhận packet vào từ port web-7975-274540, đóng dấu "đây là traffic từ Pod cục bộ" (FromPodRegMark qua reg4). SpoofGuard xác nhận đúng cặp MAC/IP đã đăng ký cho Pod này. Tới L3Forwarding, flow ưu tiên khớp nw_dst nằm trong cùng subnet cục bộ (10.10.0.0/24) không rewrite MAC nào cả — nhảy thẳng sang L2ForwardingCalc, bỏ qua các bảng tính MAC đích/TTL dành cho traffic liên-node. L2ForwardingCalc cuối cùng tra dl_dst để tìm đúng port OVS của Pod đích.
Điểm quan trọng nhất cần nhớ: antrea-tun0 (tunnel port) không xuất hiện ở đâu trong chuỗi flow trên — traffic Pod-to-Pod cùng node hoàn toàn không đi qua tunnel, không cần Geneve, không cần Global Virtual MAC. Đây là một địa chỉ MAC giả, dùng chung và giống hệt nhau trên mọi node trong cụm — khi traffic phải đi liên-node, L3Forwarding không đặt MAC đích là MAC thật của Pod đích (vì MAC đó vô nghĩa với underlay, packet còn phải đi qua tunnel), mà đặt tạm MAC đích thành Global Virtual MAC này; node nhận gói sau khi decap tunnel sẽ tự nhận ra MAC giả đó và tra lại MAC Pod thật để forward tiếp. Cơ chế này chỉ cần thiết cho traffic liên-node — traffic Pod-to-Pod cùng node đi thẳng nên không đụng tới khái niệm này. Đây khớp đúng nguyên lý cơ bản OVS đã học từ Bài 1: chỉ tunnel khi bắt buộc phải ra khỏi host, switch/route cục bộ khi có thể — nguyên lý này đúng cho cả OVN (Bài 17: "chỉ encap khi cần ra khỏi hypervisor") lẫn Antrea, dù cơ chế tính flow khác hẳn nhau.
Bài tập cuối bài
- Nếu có quyền dựng một cluster Kind (Kubernetes-in-Docker) với Antrea CNI thật: cài Antrea theo hướng dẫn chính thức, tạo 2 Pod trên cùng một node, rồi chạy
sudo ovs-ofctl dump-flows br-inttrên node đó. Tìm đúng các dòng flow ở bảngClassifier/SpoofGuard/L3Forwarding/L2ForwardingCalckhớp với hai Pod của bạn, đối chiếu với bảng và ví dụ ở Mục 9 — số liệu (MAC, IP, số port) sẽ khác, nhưng cấu trúc match/action phải cùng dạng. - Không có cluster thật cũng làm được: đọc lại bảng Mục 2 (container
ovnkube-node) và Mục 5 (Antrea Controller/Agent/OVS daemon), tự vẽ (trên giấy hoặc text) sơ đồ "một request tạo Pod mới đi qua bao nhiêu thành phần trước khi có flow OpenFlow thật" cho từng CNI — đếm số bước dịch (NB DB → SB DB → OpenFlow là 2 bước với OVN-Kubernetes) và so sánh với Antrea (1 bước). Giải thích bằng lời tại sao số bước khác nhau lại kéo theo khác biệt "Stability" đã nêu ở Mục 2. - Nếu có cả hai loại cluster (hoặc chỉ 1 loại, kết hợp đọc lại Bài 6/17 Mục 6): chạy
ovs-vsctl showtrên một node K8s, xác định đây là node OVN-Kubernetes hay Antrea dựa đúng vào tiêu chí đã học — OVN-Kubernetes:br-intdoovn-controllertự tạo, port tên theo Pod UUID/iface-idgiống hệt Bài 17 Mục 6; Antrea:br-intcó thêm hai port cố địnhantrea-gw0/antrea-tun0không xuất hiện ở OVN-Kubernetes.
Nguồn tham khảo
- Thành phần
ovnkube-nodepod (nbdb,northd,sbdb,ovn-controller,ovnkube-controller), định nghĩa "zone" ("By default, each node in the cluster is a zone, so each zone contains 1 node"), 4 lợi ích kiến trúc interconnect (stability/scale/performance/security) — OVN-Kubernetes Architecture, ovn-kubernetes.io/master/design/architecture/ - Interconnect mode hỗ trợ từ bản 1.0.0 (chưa mặc định), mặc định từ bản 1.1 ("Support for this mode of deployment was added as part of 1.0.0 release, however it was not the default. Now, from 1.1 release, we are making this the default deployment mode of OVN-Kubernetes.") — OVN-Kubernetes v1.1.0 release discussion, github.com/orgs/ovn-kubernetes/discussions/5476
- Topology chi tiết: node-local-switch, distributed-ovn-cluster-router, distributed-join-switch, node-local-gateway-router, node-local-external-switch, transit-switch ("distributed across the nodes in the cluster and responsible for routing traffic between the different zones") — OVN-Kubernetes Network Topology, ovn-kubernetes.io/master/design/topology/
- kube-proxy bị skip khi cài OVN-Kubernetes qua kubeadm ("skip the kube-proxy addon (OVN-Kubernetes provides its own service implementation)") — Launching OVN-Kubernetes with kubeadm, ovn-kubernetes.io
- Cú pháp
lb-add(tạo Load_Balancer) — ovn-nbctl(8), ovn.org - Kiến trúc tổng thể Antrea Controller/Agent/OVS daemon ("Antrea creates a Deployment that runs Antrea Controller, and a DaemonSet that includes two containers to run Antrea Agent and OVS daemons respectively, on every Node"), câu trích Controller không bắt buộc cho Pod connectivity ("you may choose not to deploy Antrea Controller at all") — Antrea Architecture, antrea.io/docs/main/docs/design/architecture/
- AntreaProxy: cơ chế Service load-balancing trong OVS pipeline, tùy chọn thay thế kube-proxy qua
proxyAll— AntreaProxy, antrea.io/docs/main/docs/antrea-proxy/ - Bảng OpenFlow pipeline Antrea (
Classifier/SpoofGuard/ConntrackZone/ConntrackState/L3Forwarding/L2ForwardingCalc/Output) và ví dụ flow thật cho traffic same-node (web-7975-274540, IP10.10.0.24, MACfa:b7:53:74:21:a6), xác nhận traffic cùng node không qua tunnel — Antrea OVS Pipeline, antrea.io/docs/main/docs/design/ovs-pipeline/ (nguồn markdown: github.com/antrea-io/antrea/blob/main/docs/design/ovs-pipeline.md) - Lý do đổi tunnel mặc định từ VXLAN sang Geneve, phục vụ tính năng Traceflow ("Geneve supports extensible encapsulation headers which allow Antrea to add extra contexts to the encapsulated packets across Nodes. This is required by the Antrea Traceflow feature.") — PR #858, github.com/antrea-io/antrea
- 55-bit metadata và lý do OVN chọn Geneve đã học ở Bài 17 Mục 5; kiến trúc OVN core NB DB/SB DB/
ovn-northd/ovn-controllervà cách CMS/OVN Plugin cắm vào NB DB đã học ở Bài 17 Mục 1-2; ML2/OVS vs ML2/OVN như một tiền lệ "2 kiến trúc dưới cùng 1 CMS" đã học ở Bài 18; VM tap interface/vòng đờivnetXgắn vào OVS để liên hệ với Pod veth pair đã học ở Bài 7 Mục 5; multi-table OpenFlow,goto_table/resubmitđã học ở Bài 12; connection trackingct()đã học ở Bài 13; VXLAN/Geneve/VNI cơ bản đã học ở Bài 9.
Tiếp theo: Module 4, Bài 20 — Troubleshooting nâng cao: debug flow, datapath, performance tuning thực chiến.