Skip to content

Multi-Cluster Services (MCS) — Service Discovery Xuyên Cluster

Tại Sao Quan Trọng Trong Production

Khi workload trên cluster-A cần call service trên cluster-B, bạn có các lựa chọn:

  1. External LoadBalancer: Expose cluster-B service bằng LoadBalancer type, hardcode external IP vào cluster-A config
  2. VPC peering + shared VPC: Routes định tuyến traffic xuyên clusters, dùng internal IPs
  3. Service mesh: Istio/Linkerd maintain endpoint registry xuyên clusters
  4. Multi-Cluster Services: Native Kubernetes abstraction để discover và call services xuyên clusters

MCS là giải pháp "most Kubernetes-native" — không cần external LB, không cần peering cấu hình phức tạp, không cần service mesh overhead. Chỉ cần ServiceExport trên cluster B và ServiceImport consume xuyên clusters. Nó leverage Cloud DNS và GKE native networking để achieve cross-cluster connectivity.

ServiceExport — "I Export This Service"

Để service có thể được accessed từ clusters khác, tạo ServiceExport resource cùng namespace và name với service:

yaml
# Cluster B (service provider)
apiVersion: net.gke.io/v1
kind: ServiceExport
metadata:
  name: payment-api
  namespace: payments
---
# Cũng phải tồn tại underlying Service
apiVersion: v1
kind: Service
metadata:
  name: payment-api
  namespace: payments
spec:
  ports:
  - name: http
    port: 8080
    targetPort: 8080
  selector:
    app: payment-api
  type: ClusterIP  # Luôn ClusterIP, không LoadBalancer

Khi ServiceExport được tạo:

  1. Fleet controller (chạy ở GCP control plane) phát hiện ServiceExport
  2. Retrieve Service object — endpoint list, port definitions
  3. Tạo Cloud DNS public zone record trong fleet project
  4. Record name: {service}.{namespace}.svc.clusterset.local
  5. Record type: A record (cho headless service) hoặc CNAME (cho ClusterIP service)

Ví dụ: payment-api.payments.svc.clusterset.local trỏ đến virtual IP của service.

Cluster B không cần public IP — MCS handle mọi thứ internal với Cloud DNS. Service vẫn là ClusterIP, chỉ được exported, không expose ra internet.

ServiceImport — "I Want to Use This Service"

Khi service được exported từ provider cluster, consumer clusters tự động có ServiceImport object được tạo:

yaml
# Cluster A (service consumer) — tự động generated
apiVersion: net.gke.io/v1
kind: ServiceImport
metadata:
  name: payment-api
  namespace: payments
status:
  type: ClusterSetIP  # Có thể là ClusterSetIP hoặc Headless
  clusterSetIPs:
  - 10.100.0.10  # Virtual IP, routable từ bất kỳ cluster nào trong fleet
  clusters:
  - name: cluster-b
    lbBalancePolicy: Random  # Hoặc Round Robin
  conditions:
  - type: Clusterset
    status: "True"

ServiceImport object này cấp phép workloads trong cluster A để discover service từ cluster B.

Cơ Chế DNS Resolution Xuyên Cluster

Cloud DNS Integration

MCS tương tác với Cloud DNS ở fleet level:

  1. RootSync/Policy Controller distribute Config Sync tạo Private Cloud DNS Zone cho fleet trong fleet host project
  2. Khi ServiceExport tạo: Fleet controller tạo DNS record trong zone này
  3. DNS queries từ pods: Pod trong bất kỳ cluster nào query payment-api.payments.svc.clusterset.local
  4. Routing: CloudDNS resolve tới virtual IP, traffic routed dựa trên locality

DNS Name Format

Kubernetes định nghĩa MCS DNS naming:

  • ClusterIP service: {service}.{namespace}.svc.clusterset.local
  • Headless service: {service}.{namespace}.svc.clusterset.local (A records cho mỗi pod)

clusterset.local là TLD dành riêng cho MCS, không phải cluster.local của single-cluster DNS.

Query Resolution Path

Pod → CoreDNS trong cluster
    → Query `payment-api.payments.svc.clusterset.local`
    → CoreDNS không biết, forward tới upstream (Cloud DNS)
    → Cloud DNS lookup record trong MCS zone
    → Return virtual IP
    → kube-proxy trong cluster route VIP đến endpoints
    → Traffic flow đến backing pods ở cluster B

Latency được thêm vào là một DNS lookup + potential cross-cluster latency. Mặc định MCS không dùng local caching ở CoreDNS level (để đảm bảo endpoint freshness), nhưng NodeLocal DNSCache có thể cache MCS records để reduce latency.

Endpoint Discovery Và Consistency Model

Endpoint Controller

Fleet maintain một endpoint controller (không visible trực tiếp) monitor Endpoints objects xuyên clusters:

  1. Khi pod được created/deleted ở cluster B đã export service, local kube-proxy update Endpoints object
  2. Fleet controller watch cluster B's Endpoints object
  3. Update internal endpoint registry trong fleet control plane
  4. Propagate changes đến consumer clusters' Endpoints objects
  5. kube-proxy ở consumer clusters update local iptables/routes để route traffic đến new/removed endpoints

Delay giữa pod creation/deletion và endpoint availability xuyên clusters phụ thuộc vào:

  • Kube-proxy sync period (mặc định 30s, có thể tune xuống nhưng không nên quá thấp)
  • Fleet controller update latency (thường < 5s)
  • DNS cache TTL (mặc định 30s)

Tổng latency thường là 30–60 giây cho endpoint propagation xuyên clusters.

Consistency Model

MCS eventually consistent, không strong consistent. Nếu pod ở cluster B bị terminate:

  • Local kube-proxy remove endpoint ngay
  • Cluster A kube-proxy vẫn có endpoint trong cache
  • Requests từ cluster A tới endpoint cũ sẽ fail
  • Kube-proxy retry logic hoặc connection reset (TCP) trigger fallback

Ứng dụng phải handle transient failures — đó là lý do tại sao circuit breakers và retry logic là critical cho cross-cluster calls.

Locality-Aware Load Balancing

MCS có thể choose endpoints dựa trên locality (prefer endpoints trong cùng region/zone):

yaml
apiVersion: v1
kind: Service
metadata:
  name: payment-api
  namespace: payments
spec:
  topologyKeys:
  - topology.kubernetes.io/zone
  - topology.kubernetes.io/region
  - "*"  # Fallback tới any endpoint

Với topology keys, kube-proxy prefer endpoints có topology label giống với requesting pod. Ví dụ: pod trong us-east1 zone sẽ prefer payment-api endpoints ở us-east1 trước, fallback đến other regions nếu cần.

Constraints Và Failure Modes

Constraint 1: Namespace Sameness Required ServiceExport cần exact namespace name match trên provider cluster. Nếu service ở namespace payment-api-prod ở cluster B, consumer cluster A phải có cùng namespace với cùng name payment-api — không thể rename hoặc namespace-map.

Constraint 2: All Fleet Members Are Consumers Khi ServiceExport tạo, mọi cluster trong fleet tự động có ServiceImport được created. Không thể "selective export" (export đến 3 clusters nhưng không đến 4 clusters khác). Nếu cần selective, phải dùng NetworkPolicy để block traffic từ non-authorized clusters.

Constraint 3: No Cross-Service Dependencies ServiceImport là consumer view. Nếu Consumer A dùng ServiceImport của Provider B, và Provider B lại dùng ServiceImport của Provider C (cross-cluster dependency chain), behavior có thể trở nên unpredictable. Tốt nhất flat service topology — consumers don't depend trên MCS-imported services của nhau.

Failure Mode: Endpoint Propagation Delay Khi pod scale up/down ở provider cluster, endpoint change không propagate instantly. Requests tới old endpoints sẽ fail. Để mitigate: dùng connection-level retries, circuit breakers, và monitor MCS endpoint propagation latency.

Failure Mode: CloudDNS Zone Outage Nếu Cloud DNS zone cho fleet không accessible (rare, but possible), DNS queries sẽ fail. Fallback mechanisms không automatic — applications mất connection. Luôn có fallback path (không exclusively rely trên MCS).

Failure Mode: Port Mismatch Service export tới port 8080, nhưng ứng dụng expect port 8081. MCS không do mapping port — chỉ reexport same ports. Port mismatch là application-level issue, không MCS issue.

Khi Nào Dùng MCS vs Alternatives

Dùng MCS:

  • Workloads cùng namespace xuyên clusters
  • Service discovery là primary need (không cần complex traffic management)
  • Locality-aware routing là useful
  • Simple, native Kubernetes model là priority

Dùng Service Mesh (Istio/ASM):

  • Cần advanced traffic management (weighted routing, circuit breaking, retry logic)
  • Cross-namespace service dependencies
  • mTLS giữa services
  • Detailed observability (latencies, error rates per service pair)

Dùng External LoadBalancer:

  • Legacy applications không biết sao cluster boundaries
  • Cần deterministic routing (không accept eventually consistent)
  • Cluster hybrid (GKE + non-GKE)

Dùng VPC Peering/NCC:

  • Cần communicate tới resources ngoài Kubernetes (databases, VMs)
  • Fleet topology very complex (hub-and-spoke across regions)

Example: Payment Service Topology

cluster-prod-us-east1:
├── ServiceExport payment-api (ports 8080)
└── Pod payment-api-xyz

cluster-prod-eu-west1:
├── Deployment order-processor
│   ├── Calls payment-api.payments.svc.clusterset.local:8080
│   └── MCS resolve → cluster-prod-us-east1 payment-api endpoints
└── Pod order-processor-abc

Architecture:
order-processor (eu-west1) → MCS DNS → cloud-dns.payments.svc.clusterset.local → 
  kube-proxy route → VIP → payment-api endpoints (us-east1)

Latency: Intra-region DNS lookup + cross-region network latency (50–100ms).

Circuit breaker pattern critical: order-processor timeout quá thấp sẽ cause cascading failures khi EU cluster call US service.

References