Sau bài này bạn làm được: giải thích service mesh giải quyết vấn đề gì mà K8s Service + NetworkPolicy không làm được; biết khi nào mesh là overkill; đọc được diagram Istio/Linkerd mà không bị mất phương hướng.
Vấn đề mesh giải quyết
Sau khi có Kubernetes Service và Ingress (bài 10), traffic bắc-nam (north-south: vào/ra cluster) đã có LB và TLS. Nhưng traffic đông-tây (east-west: giữa service trong cluster) vẫn thiếu:
| Nhu cầu | K8s thuần | Service Mesh |
|---|---|---|
| Retry / timeout giữa service | Phải code trong app | Proxy tự xử lý |
| mTLS service-to-service | Phải tự cấu hình cert | Mesh cấp cert tự động |
| Circuit breaker | Phải dùng lib (Hystrix, Resilience4j) | Proxy tự xử lý |
| Traffic split (canary) | Ingress routing đơn giản | Fine-grained policy |
| Observability east-west | Tự instrument | Tự động từ proxy |
Kiến trúc: sidecar + control plane
[Pod: service A]
├── container app
└── container proxy (Envoy / Linkerd-proxy) ← sidecar
│ intercept mọi traffic in/out
▼
[Control Plane (istiod / Linkerd control plane)]
└── phát cert, cấu hình route, auth policy tới sidecar
Data plane: sidecar proxy trên từng Pod — xử lý gói tin thực sự.
Control plane: phát policy và chứng chỉ — nếu down, traffic vẫn chạy theo config hiện tại, nhưng policy mới không được đẩy xuống.
mTLS — xác thực lẫn nhau
Mặc định HTTP giữa Pod không mã hóa. Mesh phát SVID (SPIFFE identity — thường là cert ngắn hạn) cho mỗi workload và enforce mTLS:
Service A (cert: spiffe://cluster/ns/default/sa/api)
│ TLS mutual authentication
▼
Service B (cert: spiffe://cluster/ns/default/sa/db)
Kết quả: chỉ workload được chứng nhận mới nói chuyện được — giảm blast radius nếu Pod bị compromise.
Ví dụ policy Istio
# Bắt buộc mTLS trong namespace
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: production
spec:
mtls:
mode: STRICT
---
# Cho phép service A gọi service B
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-api-to-db
namespace: production
spec:
selector:
matchLabels:
app: db
rules:
- from:
- source:
principals: ["cluster.local/ns/production/sa/api"]
Retry, timeout và circuit breaker (không cần code trong app)
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-api
spec:
http:
- retries:
attempts: 3
perTryTimeout: 2s
retryOn: "5xx,reset,connect-failure"
timeout: 10s
route:
- destination:
host: my-api
Cảnh báo: retry + timeout không đúng có thể gây retry storm — khi downstream đã quá tải, upstream retry tiếp thêm áp lực.
Thế hệ mesh 2025 — không chỉ còn sidecar
Trước đây sidecar (Istio, Linkerd) là mô hình mặc định, nhưng chi phí RAM/CPU và phức tạp vận hành khiến cộng đồng tìm phương án nhẹ hơn. Ba trường phái chính hiện nay:
Istio ambient mesh (GA 2024)
Istio giới thiệu ambient mode — bỏ sidecar, dùng hai lớp:
- ztunnel (DaemonSet trên mỗi node): xử lý mTLS L4 cho mọi Pod.
- Waypoint proxy (Deployment per-namespace): xử lý L7 (retry, AuthorizationPolicy trên header) khi cần.
[Pod A: không sidecar]
│ plain TCP
▼
[ztunnel node A] ── HBONE (HTTP CONNECT qua mTLS) ──▶ [ztunnel node B]
│
▼
[Pod B: không sidecar]
Ưu: app không cần inject, RAM tiết kiệm đáng kể, upgrade data plane không restart Pod. Nhược: L7 policy phải triển khai waypoint riêng, còn mới với nhiều use case edge.
Linkerd — nhẹ, đơn giản
Linkerd giữ mô hình sidecar nhưng viết proxy bằng Rust (không dùng Envoy) → RAM ~10–20MB/sidecar thay vì ~50–100MB của Envoy. Triết lý “less is more”: không có custom CRD phức tạp, ít tính năng hơn Istio nhưng dễ vận hành; phù hợp team nhỏ.
Cilium Service Mesh (sidecar-less bằng eBPF)
Cilium dùng eBPF làm data plane mesh ngay trong kernel — không sidecar, không DaemonSet proxy cho L4 mTLS (WireGuard hoặc IPsec); tuỳ chọn Envoy DaemonSet per-node khi cần L7. Ưu: hiệu năng cao, tận dụng CNI đã có; nhược: tính năng L7 còn giới hạn so với Istio full-feature.
Chọn mesh nào (2025):
| Tình huống | Gợi ý |
|---|---|
| Team nhỏ, cần mTLS + observability cơ bản | Linkerd |
| Đã dùng Cilium CNI | Cilium Service Mesh |
| Cần nhiều policy L7 phức tạp, multi-cluster | Istio ambient |
| Chỉ cần mTLS giữa một vài service | SPIFFE/SPIRE + cert-manager (không mesh) |
Khi nào KHÔNG cần service mesh
Mesh thêm độ phức tạp vận hành đáng kể:
- Mỗi Pod thêm ~50–100MB RAM cho sidecar (Istio sidecar classic, Envoy); Linkerd ~10–20MB; ambient/Cilium gần như không có overhead per-Pod.
- Debug khó hơn: thêm proxy hop, trace phức tạp hơn.
- Upgrade mesh = rủi ro outage (đặc biệt upgrade CRD và data plane cùng lúc).
- Control plane là điểm tập trung quan trọng — cần HA, monitor riêng.
Không nên dùng mesh khi:
- Số service < 10–20 và team nhỏ.
- Không có yêu cầu zero-trust security (mTLS).
- Đã đủ resilience bằng library trong app (retry, timeout).
Nên cân nhắc mesh khi:
- Nhiều service, nhiều team, cần policy east-west thống nhất.
- Compliance yêu cầu encryption in-transit giữa service.
- Canary/traffic split phức tạp (A/B test bằng header, weight).
Tóm tắt
- Mesh giải quyết east-west traffic: mTLS, retry, circuit breaker, observability — không cần code trong app.
- Sidecar model: mọi traffic in/out của Pod đi qua proxy.
- mTLS chứng thực workload identity — khác với TLS user-facing.
- Cân nhắc kỹ trade-off trước khi adopt: mesh tốt cho hệ thống lớn, overkill cho team nhỏ.
Câu hỏi hay gặp
Istio control plane (istiod) down — traffic đang chạy có chết không?
Trả lời: Data plane (Envoy) thường vẫn forward với config đã nhận; mất cập nhật policy/cert mới. Ngắt hoàn toàn tùy cấu hình và phiên bản — không coi CP down là “an toàn để deploy”.
STRICT mTLS, Pod C không có sidecar gọi Pod B — được không?
Trả lời: Thường không — B mong đợi TLS/mTLS từ mesh, C không đáp ứng. Cần inject sidecar, exception policy, hoặc plaintext port riêng (ít khuyến khích).
Retry 3×2s khi downstream đang quá tải — rủi ro gì?
Trả lời: Retry storm: nhân đôi số request lên service đang gục, làm sập nhanh hơn. Cần retry budget, circuit breaker, jitter.
Quay lại Giai đoạn IV: VPC và mạng trên cloud — từ trong cluster nhìn ra cloud provider.