Pod network, Services, DNS và Gateway
Pod IP là identity mạng có vòng đời theo Pod; Service tạo một điểm truy cập ổn định tới tập backend thay đổi theo thời gian. Hiểu đúng lớp Pod network, Service/EndpointSlice, DNS, north-south routing và NetworkPolicy giúp debug theo từng hop thay vì đoán.
1. Network model
CNI plugin (hoặc dataplane tương đương của distribution) tạo network interface, cấp IP, route và có thể enforce NetworkPolicy cho Pod. Các container trong cùng một Pod chia sẻ network namespace nên giao tiếp qua localhost; giữa các Pod, ứng dụng nên coi Pod IP là địa chỉ có thể thay đổi khi Pod bị recreate.
Service có selector thường được control plane ánh xạ sang EndpointSlice chứa các backend phù hợp. Service proxy/dataplane quan sát Service và EndpointSlice rồi lập trình đường đi tới backend. Kubernetes có kube-proxy làm implementation mặc định, nhưng một số network implementation dùng dataplane riêng.
Đừng nhầm Service với process proxy
Service là API abstraction và virtual endpoint. Việc packet được NAT, load-balance hoặc chuyển tiếp cụ thể phụ thuộc dataplane/implementation. Vì vậy khi debug cần kiểm tra cả object Kubernetes lẫn implementation đang thực thi nó.
Failure window và signals
- Pod vừa restart: Pod IP cũ có thể biến mất; readiness phải loại backend chưa sẵn sàng khỏi traffic.
- Service tồn tại nhưng không có backend usable: DNS/ClusterIP vẫn có thể tồn tại trong khi kết nối timeout/refused tùy đường đi và dataplane.
- Control-plane/dataplane lag: EndpointSlice đã đổi nhưng node chưa kịp lập trình rule; quan sát EndpointSlice, readiness, kube-proxy/CNI health và connection errors.
2. Service types và EndpointSlice
| Type | Dùng khi | Điểm cần nhớ |
|---|---|---|
ClusterIP | Traffic nội bộ cluster | Mặc định. Cấp virtual IP nội bộ và route tới backend. |
NodePort | Cần mở cùng một port trên các node | Xây trên ClusterIP; client truy cập NodeIP:NodePort. Cần firewall/security review. |
LoadBalancer | Expose ra ngoài qua LB integration | Kubernetes cần cloud/provider hoặc implementation cung cấp load balancer; không tự tạo external LB thuần túy. |
ExternalName | Alias một DNS name bên ngoài | Trả DNS alias/CNAME; không proxy traffic và không tạo backend Pod. |
Headless (clusterIP: None) | Client cần thấy trực tiếp endpoint, thường stateful/discovery | Không có virtual ClusterIP; DNS có thể trả tập IP endpoint để client tự lựa chọn. |
EndpointSlice là representation chuẩn của tập endpoint phía sau Service. Khi một selector match nhiều Pod, controller cập nhật EndpointSlice thay vì buộc client quan tâm Pod lifecycle trực tiếp.
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api
ports:
- name: http
port: 80
targetPort: 8080
type: ClusterIP
Debug Service theo chuỗi
kubectl get svc api -o wide— type, ClusterIP, ports có đúng không?kubectl get endpointslice -l kubernetes.io/service-name=api— có endpoint không?kubectl get pods -l app=api -o wide— selector có match đúng Pod và Pod có Ready không?- Test trực tiếp Pod IP/port từ debug Pod để tách lỗi application khỏi lỗi Service dataplane.
- Test qua Service DNS/ClusterIP; nếu direct Pod chạy nhưng Service fail, tập trung vào Service/EndpointSlice/dataplane.
3. DNS và service discovery
Cluster DNS (thường là CoreDNS trong nhiều cluster) cung cấp DNS records cho Service/Pod theo cấu hình cluster. Pod mặc định có search domain liên quan namespace, vì vậy tên ngắn như api thường chỉ resolve Service cùng namespace; cross-namespace nên dùng api.backend hoặc FQDN đầy đủ như api.backend.svc.cluster.local nếu cluster domain là cluster.local.
| Truy vấn | Ý nghĩa điển hình |
|---|---|
api | Tìm Service api trong namespace hiện tại qua search domain. |
api.backend | Tìm Service api trong namespace backend. |
api.backend.svc.cluster.local | FQDN, tránh ambiguity do search path. |
| Headless Service name | Có thể resolve thành tập IP endpoint thay vì một ClusterIP. |
DNS failure modes
ndots+ search list: tên chưa đủ FQDN có thể tạo nhiều query hơn dự kiến, đặc biệt với external hostname.- DNS cache: cache giảm query load nhưng TTL và stale answer phải được hiểu khi backend thay đổi.
- DNS đúng nhưng endpoint sai: resolve thành ClusterIP không chứng minh Service có ready backend.
- Long-lived connection: application có thể giữ connection tới backend cũ dù DNS đã thay đổi; cần xem pool TTL/reconnect behavior.
# Trong debug pod
cat /etc/resolv.conf
nslookup api.backend.svc.cluster.local
# hoặc dùng dig nếu image có sẵn
dig api.backend.svc.cluster.local
4. Ingress và Gateway API
Ingress và Gateway chỉ là API/configuration object; muốn traffic thực sự đi qua cần controller/implementation tương ứng. Ingress tập trung vào HTTP/HTTPS routing và API của Ingress hiện đã frozen. Kubernetes khuyến nghị Gateway API cho hướng phát triển mới.
Gateway API tách trách nhiệm rõ hơn: GatewayClass mô tả loại implementation, Gateway yêu cầu một điểm nhận traffic/listener, còn Route như HTTPRoute mô tả routing tới backend Service. Mô hình này phù hợp cluster dùng chung vì infrastructure provider, cluster operator và application developer có thể có quyền khác nhau.
Những behavior phải đọc theo implementation
- TLS termination/passthrough và certificate lifecycle.
- Proxy headers và client IP preservation.
- Connect/request/idle timeout.
- Retry, circuit breaking, body/header limits, buffering.
- Controller-specific status/conditions và conformance level.
Security và rollout
Không để application team mặc định có toàn quyền sửa shared GatewayClass/Gateway nếu cluster multi-tenant. Dùng RBAC theo ownership, giới hạn listener/namespace attachment theo policy của implementation, rotate TLS secret/certificate có kiểm soát và quan sát status conditions trước khi chuyển traffic.
Khi migrate Ingress → Gateway API, chạy canary route/hostname nếu có thể, xác minh TLS, headers, redirects, timeout, websocket/gRPC behavior và log/metrics. Rollback nên giữ manifest/implementation cũ đủ lâu để quay lại mà không tạo hai đường ingress cạnh tranh cho cùng hostname.
5. NetworkPolicy
NetworkPolicy là Kubernetes API để kiểm soát traffic ở lớp IP/port. Policy chỉ có hiệu lực nếu network plugin/dataplane của cluster hỗ trợ enforcement. Việc object tạo thành công không chứng minh traffic đã bị chặn.
Policy là additive: nhiều policy chọn cùng Pod thì tập allow là union của các rule liên quan, không có thứ tự “policy sau override policy trước”. Ingress và egress isolation được xét độc lập; để một kết nối Pod-to-Pod thành công, phía source phải được phép egress và phía destination phải được phép ingress khi các phía đó đang bị isolate.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: backend
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Sau default-deny, thêm allow rule tối thiểu cho dependencies thật sự cần thiết. Đặc biệt, default-deny egress cũng có thể chặn DNS; phải allow DNS tới resolver của cluster theo cách phù hợp với distribution/CNI của bạn.
Selector semantics dễ sai
podSelectortrong policy chọn target Pod trong namespace của policy.namespaceSelectormatch label trên Namespace, không match tên namespace trừ khi bạn dùng label phù hợp.- Khi phối hợp
namespaceSelectorvàpodSelector, cấu trúc YAML quyết định là AND trong cùng peer hay các peer độc lập. - Policy L3/L4 không phải WAF/application authorization; cho phép TCP/443 không đồng nghĩa request HTTP được phép về mặt business.
Debug và rollback
- Xác nhận CNI có support NetworkPolicy và policy engine đang healthy.
- Xem label thực tế của source Pod, destination Pod và Namespace.
- Kiểm tra cả ingress lẫn egress policy đang chọn hai phía.
- Test DNS riêng, sau đó test IP/port dependency bằng debug Pod có cùng labels/service account/context cần thiết.
- Nếu rollout policy làm gián đoạn production, rollback bằng cách gỡ policy mới hoặc áp dụng temporary explicit allow có scope hẹp; sau đó thu evidence trước khi chỉnh lại rule.
6. Runbook: phân lớp sự cố networking
| Triệu chứng | Khoanh vùng đầu tiên | Evidence nên lấy |
|---|---|---|
| Name không resolve | DNS policy/search path/CoreDNS/upstream | /etc/resolv.conf, DNS query, CoreDNS logs/metrics |
| DNS resolve nhưng connect fail | Service endpoints, targetPort, NetworkPolicy, app listener | Service YAML, EndpointSlice, Pod readiness, direct Pod test |
| Chỉ external traffic fail | LB/Gateway/Ingress/controller/firewall/TLS | Gateway/Ingress status, LB health, controller logs, certificate state |
| Một số Pod fail ngẫu nhiên | Bad endpoint, readiness gap, zone/node path, stale connection | Per-endpoint error, Pod/node mapping, connection age |
| Sau NetworkPolicy rollout bị timeout | Selector/egress DNS/dependency port | Matched policy, labels, CNI policy verdict/log nếu có |
7. Production checklist
- Readiness phản ánh đúng khả năng phục vụ traffic; không chỉ kiểm tra process còn sống.
- Service selector và named ports nhất quán; EndpointSlice có expected ready endpoints.
- DNS dependency có latency/error SLI và đủ capacity/headroom.
- Gateway/Ingress controller có metrics, access/error logs và status monitoring.
- Timeout/retry được cấu hình phối hợp giữa client, gateway và backend để tránh retry storm.
- NetworkPolicy rollout theo default-deny + explicit allow có canary/verification và rollback path.
- LB/Gateway certificate, DNS record, firewall/security group và external dependency đều có owner.
- Runbook cho “DNS → Service → EndpointSlice → Pod → policy → gateway/LB” được test bằng failure injection phù hợp môi trường.