Triển khai Linkerd Service Mesh trên Kubernetes: mTLS Zero-Trust siêu nhẹ và tối ưu hiệu năng mạng

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Các hướng tiếp cận Service Mesh: Lựa chọn tầng kiến trúc phù hợp cho Microservices

Việc bảo mật traffic east-west giữa các microservices trong cụm Kubernetes thường buộc các đội ngũ kỹ thuật phải đánh đổi giữa độ phức tạp và hiệu năng. Khi các yêu cầu kiểm toán tuân thủ đòi hỏi Zero-Trust mutual TLS (mTLS), khả năng thu thập telemetry toàn diện và các chính sách traffic nghiêm ngặt, ba mô hình kiến trúc phổ biến thường được cân nhắc:

  • Mã hóa ở tầng ứng dụng (SDK / Code): Các lập trình viên trực tiếp xử lý các bước bắt tay TLS ngay trong runtime của ứng dụng, chẳng hạn như cấu hình Java KeyStore trong Spring Boot hoặc nạp cặp khóa X.509 vào gRPC dial options trong Go. Cách tiếp cận này loại bỏ hoàn toàn độ trễ do proxy tạo ra. Tuy nhiên, nó phân tán logic xoay vòng chứng chỉ ra hàng chục codebase khác nhau, dễ phát sinh lỗi đặc thù theo từng ngôn ngữ và tạo gánh nặng bảo trì mã hóa liên tục cho đội ngũ phát triển.
  • Service Mesh dạng nặng dựa trên Envoy (ví dụ: Istio): Các sidecar Envoy chạy song song với từng pod, cung cấp khả năng định tuyến Layer 7 chuyên sâu và phân tích cú pháp giao thức chi tiết. Nhược điểm lớn nhất là mức tiêu hao tài nguyên. Một sidecar Envoy tiêu chuẩn thường chiếm từ 50MB đến 150MB RAM cho mỗi pod và có thể làm tăng tail latency từ 2ms đến 6ms khi chịu tải lớn. Ngoài ra, control plane phức tạp cũng đòi hỏi chi phí vận hành đáng kể.
  • Service Mesh sử dụng Micro-Proxy chuyên dụng (Linkerd): Linkerd sử dụng linkerd2-proxy, một proxy chuyên biệt được viết hoàn toàn bằng Rust. Thay vì tích hợp mọi bộ lọc định tuyến phức tạp vào data plane, nó tập trung tối đa vào luồng traffic cốt lõi của microservices. Giải pháp này cung cấp mTLS sẵn sàng sử dụng ngay, chỉ tiêu tốn 15MB đến 30MB RAM cho mỗi sidecar và duy trì độ trễ p99 tăng thêm ở mức dưới 1.5ms.

Đối với các cụm chạy hàng trăm microservices, giải pháp micro-proxy mang lại khả năng mã hóa và giám sát toàn diện mà không làm tăng vọt chi phí hạ tầng đám mây của bạn.

Ưu và nhược điểm: Đánh giá Linkerd cho môi trường Production

Ưu điểm

  • Mức tiêu thụ CPU và Memory cực thấp: Được xây dựng với các bảo đảm an toàn bộ nhớ của Rust, proxy hoạt động mà không bị gián đoạn do thu gom rác (garbage collection). Ở trạng thái chờ, proxy thường chỉ chiếm dưới 20MB RAM và 10m CPU trên mỗi pod.
  • Mutual TLS tự động hoàn toàn (Zero-Touch): Linkerd tự động thiết lập các đường hầm TLS 1.3 đã được xác thực giữa các pod trong mesh ngay khi phát hiện dịch vụ. Hệ thống tự động xoay vòng các chứng chỉ tạm thời (ephemeral workload certificates) mỗi 24 giờ mà không làm ngắt các kết nối TCP đang hoạt động.
  • Độ trễ p99 dưới mili-giây: Proxy lược bỏ việc thực thi runtime Lua nặng nề và các chuỗi bộ lọc chung chung, giúp giữ độ trôi p99 dưới 1.5ms ngay cả khi xử lý 35.000 requests mỗi giây.
  • Mô hình chính sách tinh gọn: Thay vì bắt buộc bạn phải làm quen với hàng chục CRD phức tạp, Linkerd chỉ sử dụng các tài nguyên chính sách cốt lõi, tập trung như Server, AuthorizationPolicy và MeshTLSAuthentication.

Hạn chế cần cân nhắc

  • Hỗ trợ giao thức có chọn lọc: Linkerd xử lý tốt HTTP/1.x, HTTP/2, gRPC và raw TCP. Nếu kiến trúc của bạn phụ thuộc vào các giao thức doanh nghiệp cũ như Dubbo hoặc yêu cầu phân tích payload tùy biến ngay tại tầng proxy, Envoy sẽ là lựa chọn linh hoạt hơn.
  • Không hỗ trợ khả năng mở rộng nhúng: Linkerd không hỗ trợ WebAssembly (Wasm) hoặc chuỗi bộ lọc Lua tùy chỉnh bên trong data plane. Bạn cần thực hiện các biến đổi payload tùy biến tại ingress gateway hoặc ở tầng middleware của ứng dụng.

Kiến trúc Production và các yêu cầu tiên quyết

Tuyệt đối không sử dụng chứng chỉ tự ký mặc định của CLI Linkerd trên môi trường production. Các chứng chỉ này sẽ hết hạn sau 365 ngày và không có cơ chế tự động gia hạn. Thay vào đó, hãy tích hợp hạ tầng khóa công khai (PKI) bên ngoài với cert-manager để tự động hóa việc xoay vòng chứng chỉ.

Mô hình kiến trúc

  • Trust Anchor: Chứng chỉ root CA dài hạn (có hiệu lực từ 5 đến 10 năm) được lưu trữ trong kho bí mật an toàn như HashiCorp Vault hoặc AWS KMS.
  • Identity Issuer: Chứng chỉ CA trung gian do cert-manager quản lý trực tiếp trong Kubernetes, được xoay vòng định kỳ từ 30 đến 60 ngày một lần.
  • Control Plane độ sẵn sàng cao (High-Availability): Triển khai 3 replica cho mỗi thành phần linkerd-destination và linkerd-identity kèm theo cấu hình pod anti-affinity để đảm bảo khả năng chịu lỗi khi có sự cố node.
  • Tự động inject ở cấp độ Namespace: Gắn nhãn (annotate) trực tiếp cho các namespace của Kubernetes để mọi pod mới được tạo đều tự động nhận sidecar proxy.

Mô hình kiến trúc này xử lý ổn định các workload production vượt mức 50.000 requests mỗi giây trong khi tổng mức sử dụng bộ nhớ của control plane vẫn duy trì dưới 1.5GB.

Hướng dẫn triển khai từng bước

Bước 1: Cài đặt Linkerd CLI và kiểm tra độ tương thích của cụm

Tải Linkerd CLI về máy trạm và kiểm tra cụm của bạn có đáp ứng các yêu cầu về kernel, CNI và iptables hay không:

# Tải xuống và cài đặt Linkerd CLI
curl -fsL https://run.linkerd.io/install | sh
export PATH=$PATH:$HOME/.linkerd2/bin

# Kiểm tra tính sẵn sàng của cụm trước khi cài đặt
linkerd check --pre

Đảm bảo toàn bộ các bước kiểm tra tiền khả thi (pre-flight checks) đều đạt trạng thái màu xanh trước khi chuyển sang bước kế tiếp.

Bước 2: Thiết lập hạ tầng PKI với Step-CLI và Cert-Manager

Tạo root trust anchor và chứng chỉ intermediate issuer bằng công cụ step CLI:

# Tạo root Trust Anchor (thời hạn 10 năm)
step certificate create root.linkerd.cluster.local root.crt root.key \
  --profile root-ca \
  --no-password --insecure \
  --not-after=87600h

# Tạo chứng chỉ Issuer trung gian (thời hạn 1 năm)
step certificate create identity.linkerd.cluster.local issuer.crt issuer.key \
  --profile intermediate-ca \
  --ca root.crt --ca-key root.key \
  --no-password --insecure \
  --not-after=8760h

Lưu cặp chứng chỉ issuer trung gian vào một secret của Kubernetes để controller identity của Linkerd có thể ký các chứng chỉ pod tạm thời có hiệu lực 24 giờ:

# Tạo namespace linkerd
kubectl create namespace linkerd

# Lưu trữ chứng chỉ issuer vào secret
kubectl create secret tls linkerd-identity-issuer \
  --cert=issuer.crt \
  --key=issuer.key \
  --namespace=linkerd

Bước 3: Triển khai Linkerd Control Plane ở chế độ High-Availability

Cài đặt các Custom Resource Definitions (CRDs) trước, sau đó tiến hành triển khai các thành phần control plane cốt lõi:

# 1. Cài đặt Linkerd CRD
linkerd install --crds | kubectl apply -f -

# 2. Cài đặt Control Plane với cờ HA và giới hạn tài nguyên
linkerd install \
  --ha \
  --identity-trust-anchors-file=root.crt \
  --identity-issuer-certificate-file=issuer.crt \
  --identity-issuer-key-file=issuer.key \
  --proxy-cpu-request="50m" \
  --proxy-memory-request="32Mi" \
  --proxy-cpu-limit="500m" \
  --proxy-memory-limit="128Mi" \
  | kubectl apply -f -

# 3. Kiểm tra trạng thái hoạt động của control plane
linkerd check

Bước 4: Bật tính năng tự động Inject Proxy trên Namespace ứng dụng

Tránh chỉnh sửa spec của từng pod thủ công. Hãy kích hoạt mutating admission webhook trên toàn bộ namespace ứng dụng mục tiêu của bạn:

# Tạo namespace cho ứng dụng
kubectl create namespace payments-service

# Kích hoạt tự động inject proxy
kubectl annotate namespace payments-service linkerd.io/inject=enabled

Triển khai các workload của bạn hoặc thực hiện rolling restart để Linkerd tự động inject sidecar container linkerd2-proxy:

# Thực hiện rolling restart trên các deployment hiện có
kubectl rollout restart deployment -n payments-service

Bước 5: Kiểm tra xác thực Zero-Trust mTLS và Telemetry mạng theo thời gian thực

Linkerd tích hợp sẵn một engine giám sát chỉ số ngay trên cụm để kiểm toán trạng thái mã hóa và theo dõi phân bổ độ trễ.

Cài đặt tiện ích mở rộng trực quan hóa (Linkerd Viz):

# Cài đặt Linkerd Viz
linkerd viz install | kubectl apply -f -
linkerd check

Kiểm tra trạng thái mTLS thời gian thực giữa các workload đang chạy trực tiếp từ terminal:

# Kiểm tra các kết nối mTLS trực tiếp trong payments-service
linkerd viz edges deployment -n payments-service

Kết quả đầu ra xác nhận việc xác thực mutual TLS đã hoàn tất và hiển thị chính xác danh tính workload chuẩn SPIFFE:

SRC          DST             SRC_EU_ID                                                                   DST_EU_ID                                                                   SECURED
api-gateway  payment-worker  api-gateway.payments-service.serviceaccount.identity.linkerd.cluster.local  payment-worker.payments-service.serviceaccount.identity.linkerd.cluster.local  yes (TLS 1.3)

Để xem các phân vị độ trễ (latency percentiles), throughput và tỷ lệ lỗi theo thời gian thực mà không cần viết thêm mã đo lường vào ứng dụng:

# Kiểm tra golden metrics (Success Rate, RPS, Độ trễ p50/p95/p99)
linkerd viz stat deployment -n payments-service

Bước 6: Áp dụng các chính sách phân quyền Zero-Trust nghiêm ngặt

Mặc định, Linkerd chạy ở chế độ permissive (cho phép), tức là vừa mã hóa traffic vừa cho phép các kết nối chưa được xác thực đi qua. Để thiết lập ranh giới cách ly Zero-Trust nghiêm ngặt, hãy định nghĩa các tài nguyên Server và AuthorizationPolicy nhằm từ chối các caller không hợp lệ ngay tại ranh giới của proxy:

apiVersion: policy.linkerd.io/v1beta1
kind: Server
metadata:
  name: payment-server-port
  namespace: payments-service
spec:
  port: 8080
  proxyProtocol: HTTP/2
  podSelector:
    matchLabels:
      app: payment-worker
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
  name: allow-api-gateway-only
  namespace: payments-service
spec:
  targetRef:
    group: policy.linkerd.io
    kind: Server
    name: payment-server-port
  requiredAuthenticationRefs:
    - group: policy.linkerd.io
      kind: MeshTLSAuthentication
      name: api-gateway-identity
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
  name: api-gateway-identity
  namespace: payments-service
spec:
  identities:
    - "api-gateway.payments-service.serviceaccount.identity.linkerd.cluster.local"

Khi chính sách này được kích hoạt, bất kỳ pod nào không có danh tính api-gateway đều sẽ bị ngắt kết nối ngay lập tức với mã lỗi HTTP 403 hoặc tín hiệu TCP reset trước khi traffic có thể chạm tới mã nguồn ứng dụng của bạn.

Share: