Service Mesh Networking: Envoy Data Plane and mTLS
Tại sao Service Mesh Troubleshooting Khác biệt
Service Mesh (Anthos Service Mesh hoặc Istio) bổ sung thêm một tầng phức tạp mới (additional layer of complexity):
- Luồng traffic đi qua các Envoy sidecar proxy, không truyền trực tiếp (direct).
- Bắt buộc áp dụng mTLS (mutual TLS) giữa các service.
- Các chính sách traffic policy kiểm soát định tuyến (routing), thử lại (retries), và ngắt mạch (circuit breaking).
- Khả năng quan sát (Observability) thông qua access logs, traces, và metrics.
Sự cố mạng có thể xuất phát từ hạ tầng bên dưới (firewall, routes) hoặc cấu hình của service mesh. Để phân tách nguyên nhân, bạn cần hiểu rõ kiến trúc của service mesh.
Cơ chế bên trong: Luồng đi của Traffic trong Service Mesh
Luồng tổng quát (High-Level Flow)
Pod A (có Envoy sidecar)
↓
Envoy bắt traffic (qua các rules iptables)
↓
Envoy áp dụng các chính sách (retry, timeout, v.v.)
↓
Envoy thiết lập kết nối mTLS tới Envoy của Pod B
↓
Envoy của Pod B giải mã và forward tới ứng dụngChi tiết các bước
Bước 1: Đánh chặn Traffic (iptables)
Service Mesh đưa các iptables rules vào để đánh chặn traffic:
# Xem các rules iptables (yêu cầu quyền admin)
sudo iptables -t mangle -L -n
# Kết quả hiển thị các rule chuyển traffic tới Envoy (localhost:15000)Cơ chế hoạt động:
Pod khởi tạo kết nối: pod-a.ns.svc.cluster.local:8080
↓
iptables redirect: 127.0.0.1:15001 (Envoy listener)
↓
Envoy xử lý trafficBước 2: Cấu hình Envoy
Service Mesh control plane (istiod) đẩy cấu hình (push configuration) tới các Envoy sidecar:
istiod (control plane)
↓
Cấu hình Envoy sidecar
├─ Listeners (các port Envoy lắng nghe)
├─ Routes (cách thức định tuyến traffic)
├─ Clusters (các destination ở backend)
└─ Endpoints (các instance backend thực tế)Cấu hình được cập nhật theo thời gian thực qua giao thức xDS (gRPC). Envoy sẽ áp dụng cấu hình này ngay lập tức.
Bước 3: Đưa ra Quyết định Định tuyến (Traffic Decision)
Khi packet truyền đến Envoy listener, Envoy sẽ thực hiện:
1. Khớp listener (port, protocol)
2. Áp dụng route khớp (host, path, headers)
3. Áp dụng các chính sách (retry, timeout, circuit breaker)
4. Chọn cluster (backend service)
5. Chọn endpoint (instance pod cụ thể)
6. Mở kết nối upstream tới endpoint
7. Forward traffic của ứng dụngBước 4: Thiết lập Kết nối mTLS
Envoy thiết lập kết nối mutual TLS tới Envoy của endpoint:
Envoy A: Bắt tay TLS tới port 15003 của Envoy B (mutual)
├─ Xuất trình client certificate (Workload Identity)
├─ Xác thực server certificate (Workload Identity)
└─ Thiết lập encrypted tunnel (đường truyền mã hóa)
Traffic ứng dụng được mã hóa qua tunnelQuản lý Certificate:
- Istio Certificate Authority (CA) cấp phát các certificate.
- Certificate được tự động xoay vòng (mặc định sau mỗi 24 giờ).
- mTLS được bắt buộc áp dụng dựa trên các chính sách
PeerAuthentication.
Bước 5: Đường truyền Phản hồi (Response Path)
Traffic phản hồi được truyền ngược lại:
Backend Pod → Backend Envoy
↓
Giải mã mTLS
↓
Forward phản hồi tới upstream Envoy
↓
Upstream Envoy giải mã, forward tới ứng dụngCác lỗi Service Mesh thường gặp khi Debug
Trường hợp 1: Lỗi từ chối kết nối (Connection Refused)
Triệu chứng:
Pod A curl pod-b:8080
curl: (7) Failed to connect to pod-b port 8080: Connection refusedNguyên nhân gốc rễ:
Chưa inject các rule iptables của service mesh
bash# Kiểm tra status sidecar injection kubectl get pods pod-a -o yaml | grep sidecar # Phải có annotation: sidecar.istio.io/inject=true # Nếu chưa được inject, hãy kích hoạt cho namespace kubectl label namespace default istio-injection=enabled --overwrite # Tạo lại pod kubectl delete pods pod-a kubectl apply -f pod-a.yamlBackend service chưa được đăng ký trong mesh
bash# Kiểm tra Service definition kubectl get svc pod-b -o yaml # Kiểm tra xem port có được định nghĩa rõ ràng không # Kiểm tra VirtualService / DestinationRule (nếu có) kubectl get vs,drChính sách traffic policy chặn kết nối
bash# Kiểm tra DestinationRule traffic policies kubectl get dr pod-b -o yaml # Xem kỹ: trafficPolicy (load balancer, connection pool) # Kiểm tra chính sách PeerAuthentication kubectl get peerauth -o yaml # Nếu ở chế độ STRICT, kết nối bắt buộc phải dùng mTLS
Trường hợp 2: Lỗi bắt tay mTLS (mTLS Handshake Failures)
Triệu chứng:
Envoy logs hiển thị:
TLS error: certificate verify failed
TLS error: bad certificate
upstream connect error or disconnect/reset before headersNguyên nhân gốc rễ:
Certificate chưa được cấp phát
bash# Kiểm tra log của deployment/istiod kubectl logs -n istio-system deployment/istiod | grep certificate # Pod mới có thể phải chờ cấp certificate # Chờ khoảng 30s rồi thử lạiWorkload Identity bị sai lệch (mismatch)
bash# Kiểm tra service account kubectl get sa pod-b # Certificate được cấp phát cho service account # Xác minh pod đang chạy đúng service account kubectl get pods pod-b -o yaml | grep serviceAccountNameSai lệch chính sách PeerAuthentication
bash# Nếu PeerAuthentication bắt buộc STRICT mTLS, # cả hai pod đều phải hỗ trợ mTLS kubectl get peerauth -o yaml # Nếu một pod không có sidecar proxy, kết nối sẽ lỗi # Hãy inject sidecar proxy cho pod
Trường hợp 3: Traffic không đến được Backend (Cấu hình sai Routing)
Triệu chứng:
Lúc đầu gọi curl thành công, sau đó bắt đầu gặp lỗi
hoặc traffic đi sai backend mong muốnNguyên nhân gốc rễ:
Cấu hình sai rule trong VirtualService
bash# Kiểm tra VirtualService kubectl get vs -o yaml # Xem kỹ: hosts, http routes, match conditions # Ví dụ mẫu: apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: pod-b spec: hosts: - pod-b.default.svc.cluster.local http: - route: - destination: host: pod-b.default.svc.cluster.local port: number: 8080Thiếu Destination Rule
bash# VirtualService có thể tham chiếu tới destination không tồn tại kubectl describe vs pod-b # Kiểm tra xem host có phân giải được không # Tạo DestinationRule nếu cần thiết kubectl apply -f - << EOF apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: pod-b spec: host: pod-b.default.svc.cluster.local trafficPolicy: connectionPool: tcp: maxConnections: 100 http: http1MaxPendingRequests: 100 EOF
Trường hợp 4: Latency qua Mesh tăng cao
Triệu chứng:
Kết nối trực tiếp giữa hai pod (qua IP): latency 1ms
Kết nối qua mesh (qua service): latency 50msNguyên nhân gốc rễ:
Phát sinh thêm hop qua Envoy
Envoy làm tăng thêm độ trễ xử lý (thường khoảng ~10-20ms). Đây là hiện tượng bình thường.
Circuit breaker giới hạn số lượng request đồng thời
bash# Kiểm tra DestinationRule traffic policy kubectl get dr -o yaml | grep -A 10 trafficPolicy # Nếu http1MaxPendingRequests quá thấp, các request sẽ bị xếp hàng # Hãy tăng giới hạn này lênRetry policy làm phát sinh thêm latency
bash# Kiểm tra retry policy kubectl get vs -o yaml | grep -A 5 retries # Nếu cấu hình 3 lần retry với timeout 1s mỗi lần, độ trễ tối đa sẽ là 3s # Hãy điều chỉnh lại nếu quá khắt khe
Kiểm tra Logs của Envoy
Access Logs
Bật Envoy access logs để theo dõi traffic:
# Qua CLI
kubectl set env -n default deployment/pod-a \
PROXY_LOG_LEVEL=debug
# Hoặc cấu hình qua Telemetry resource
kubectl apply -f - << EOF
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: default
spec:
accessLogging:
- providers:
- name: envoy
state: ON
EOFXem logs:
# Log của container proxy
kubectl logs pod-a -c istio-proxy
# Định dạng output mẫu:
[2026-06-26T15:30:45.123Z] "[2026-06-26T15:30:45.123Z] ...
SOURCE_IP - - [26/Jun/2026:15:30:45 +0000] "GET /api HTTP/1.1" 200 1234 "-" "-" 0 42 "-" "-" "10.0.1.2" "10.1.1.3:8080" "pod-b.default.svc.cluster.local" outbound|8080||pod-b.default.svc.cluster.local 10.0.1.2:54321 10.1.1.3:8080 10.0.1.2:54321 -Đọc hiểu log:
- Method: GET
- Path: /api
- Status: 200
- Thời gian phản hồi (Response time): 42ms
- Upstream: pod-b.default.svc.cluster.localCấu hình Debug Log Level
Tăng độ chi tiết của log:
# Kiểm tra tên container proxy của pod
kubectl get pods pod-a -o jsonpath='{.spec.containers[].name}'
# Bật debug logging qua API
kubectl exec pod-a -c istio-proxy -- \
curl -X POST http://localhost:15000/logging?level=debug
# Theo dõi logs trực tiếp
kubectl logs pod-a -c istio-proxy -fXuất thông tin Cấu hình (Configuration Dump)
Kiểm tra cấu hình thực tế của Envoy:
# Xuất toàn bộ config
kubectl exec pod-a -c istio-proxy -- \
curl localhost:15000/config_dump > config_dump.json
# Kiểm tra các cluster
kubectl exec pod-a -c istio-proxy -- \
curl localhost:15000/clusters
# Kiểm tra các listener
kubectl exec pod-a -c istio-proxy -- \
curl localhost:15000/listenersSử dụng Distributed Tracing
Tracing hiển thị luồng đi của request đầu-cuối qua mesh:
# Xác thực Tracing đã được bật chưa
kubectl get telemetry -o yaml | grep tracingProviders
# Triển khai tracing backend (như Jaeger/Zipkin)
# Thường được tích hợp sẵn kèm theo Anthos Service Mesh
# Gửi request để tạo trace
kubectl exec pod-a -- curl pod-b:8080
# Xem thông tin trace trên Jaeger UISơ đồ luồng đi (Trace):
Request A → Envoy A (10ms)
↓
Bắt tay mTLS (5ms)
↓
Request B → Envoy B (8ms)
↓
Xử lý ở App B (20ms)
↓
Phản hồi B ← Envoy B (3ms)
↓
Phản hồi A ← Envoy A (2ms)
Tổng cộng: ~48msMỗi phân đoạn (span) hiển thị latency chi tiết ở từng layer, giúp xác định điểm nghẽn.
Best Practices cho Service Mesh Debugging
1. Đảm bảo Kích hoạt Sidecar Injection đồng nhất
# Label namespace
kubectl label namespace default istio-injection=enabled
# Kiểm tra pod đã được auto-inject sidecar chưa
kubectl get pods pod-a -o yaml | grep "- name: istio-proxy"
# Phải xuất hiện container istio-proxy2. Giám sát thời gian hết hạn Certificate
# Kiểm tra các secret cert
kubectl get secret -n default | grep cert
# Xem thông tin chi tiết certificate
kubectl get secret pod-a-certs -o jsonpath='{.data.cert}' | \
base64 --decode | openssl x509 -text -noout3. Áp dụng mTLS theo lộ trình
# Bắt đầu với chế độ PERMISSIVE (cho phép cả traffic không dùng mTLS)
kubectl apply -f - << EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
spec:
mtls:
mode: PERMISSIVE # Ban đầu cho phép cả kết nối thường
EOF
# Sau khi xác thực hoạt động ổn định, chuyển sang STRICT
kubectl patch peerauth default -p '{"spec":{"mtls":{"mode":"STRICT"}}}'4. Thiết lập rõ các Traffic Policies
# Áp dụng DestinationRule đi kèm giới hạn và cấu hình log
kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: pod-b
spec:
host: pod-b
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1000
http:
http1MaxPendingRequests: 1000
maxRequestsPerConnection: 2
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
EOF5. Xác thực cấu hình trước khi deploy
# Sử dụng công cụ analyze của istioctl để xác thực
istioctl analyze
# Đảm bảo không hiển thị lỗi hoặc cảnh báo nào trước khi deployQuy trình xử lý sự cố trên Production
Khi xảy ra lỗi kết nối giữa các service (service-to-service communication failing):
1. Xác thực sidecar đã được inject vào pod chưa
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}' | grep istio-proxy
2. Kiểm tra cấu hình mTLS
kubectl get peerauth -o yaml
→ Nếu là STRICT, bắt buộc cả hai service kết nối đều phải có sidecar proxy.
3. Kiểm tra các chính sách traffic policy
kubectl get vs,dr -o yaml
→ Xem kỹ các routing rules và traffic policies.
4. Bật access logs để theo dõi traffic
kubectl apply -f telemetry.yaml
5. Tạo traffic giả lập để kiểm tra trace
kubectl exec pod-a -- curl pod-b:8080
6. Kiểm tra logs của proxy
kubectl logs pod-a -c istio-proxy | grep "pod-b"
7. Kiểm tra certificate của workload
kubectl get secret -n default | grep cert
8. Xác thực phân giải tên miền nội bộ
kubectl exec pod-a -- nslookup pod-b.default.svc.cluster.local
9. Nếu vẫn gặp lỗi:
kubectl describe vs pod-b
kubectl describe dr pod-b
kubectl describe peerauth