Skip to content

Gateway API Architecture — GatewayClass, Gateway, HTTPRoute và GKE Implementation

Tại sao Gateway API ra đời

Ingress API trong Kubernetes có một vấn đề thiết kế cơ bản: nó cố gắng phục vụ tất cả trong một resource. Platform operator, application developer, và infrastructure provider đều thao tác trên cùng một Ingress object. Điều này dẫn đến:

  • Conflict permissions: developer phải có quyền edit Ingress để thêm routing rule, nhưng cùng Ingress đó cũng chứa TLS config và IP assignment mà chỉ operator mới nên touch
  • Thiếu expressiveness: không thể làm header matching hay traffic weighting chỉ với Ingress annotations
  • Fragmentation: mỗi Ingress controller (nginx, HAProxy, Traefik) implement annotations khác nhau, không portable

Gateway API (Kubernetes SIG Network standard) giải quyết bằng cách tách biệt theo roletăng expressiveness thông qua resources riêng biệt.

Ba-layer resource model

Gateway API chia control thành ba lớp resource, mỗi lớp thuộc về một role khác nhau:

Infrastructure Provider
        │ định nghĩa

   GatewayClass          ← "Loại LB nào tồn tại trong cluster này?"

        │ tham chiếu

   Cluster Operator
        │ tạo

     Gateway              ← "Frontend: IP, port, TLS, namespace policy"

        │ route attachment

   Application Developer
        │ tạo

    HTTPRoute             ← "Routing rules: path, header, weight"

Điểm quan trọng: Gateway và HTTPRoute không nhất thiết phải cùng namespace. Một Gateway ở namespace infra có thể nhận HTTPRoutes từ nhiều namespaces khác nhau — đây là enabler cho self-service routing trong platform model.

GatewayClass — Infrastructure definition

GatewayClass là cluster-scoped resource (không thuộc namespace nào). Mỗi GatewayClass định nghĩa một loại load balancer infrastructure cụ thể mà controller biết cách provision.

GKE tự động cài sẵn các GatewayClasses khi enable Gateway API:

yaml
# Ví dụ: xem GatewayClasses có sẵn
kubectl get gatewayclass
# NAME                                  CONTROLLER
# gke-l7-global-external-managed        networking.gke.io/gateway
# gke-l7-regional-external-managed      networking.gke.io/gateway
# gke-l7-rilb                           networking.gke.io/gateway
# gke-l7-gxlb                           networking.gke.io/gateway

Mapping GatewayClass → GCP Load Balancer

GatewayClassGCP LB typeScopeGhi chú
gke-l7-global-external-managedGlobal External Application LBGlobal (Premium tier)Recommended cho internet-facing
gke-l7-regional-external-managedRegional External Application LBRegionalInternet-facing, regional scope
gke-l7-rilbInternal Application LBRegional (trong VPC)Private services
gke-l7-gxlbClassic Global External ALBGlobalLegacy, không support advanced features

Cơ chế: GatewayClass chứa spec.controllerName chỉ định controller nào xử lý. Tất cả GKE GatewayClasses đều có controllerName: networking.gke.io/gateway — đây là GKE Gateway controller được Google quản lý.

Khi bạn tạo một Gateway tham chiếu một GatewayClass, GKE Gateway controller nhận event và bắt đầu provision GCP LB resources phù hợp với loại LB được định nghĩa bởi GatewayClass đó.

Gateway — Frontend definition

Gateway là cluster-scoped (có thể thuộc bất kỳ namespace nào). Nó định nghĩa "frontend" của load balancer: IP address, ports, protocols, TLS termination, và ai được phép attach routes.

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: external-gateway
  namespace: infra
spec:
  gatewayClassName: gke-l7-global-external-managed
  listeners:
    - name: https
      port: 443
      protocol: HTTPS
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: my-tls-cert
            namespace: infra
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: "allowed"
    - name: http
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: Same  # Chỉ namespace "infra"

Listeners — Cổng vào

Mỗi listener trong Gateway tương ứng với một forwarding rule trong GCP. Một Gateway có thể có nhiều listeners với ports khác nhau.

allowedRoutes kiểm soát namespace nào được phép attach HTTPRoutes vào listener này:

  • from: Same — chỉ cùng namespace với Gateway
  • from: All — tất cả namespaces
  • from: Selector — namespaces matching label selector

Đây là cơ chế namespace isolation quan trọng: cluster operator quyết định team nào được routing traffic qua Gateway của mình.

Static IP Address

Mặc định, controller tự assign IP. Để pin một static IP:

yaml
metadata:
  annotations:
    networking.gke.io/static-ip: "my-reserved-ip-name"
    # Hoặc cho ephemeral premium tier:
    # networking.gke.io/premium-ephemeral-ipv4-address: "true"

Static IP tồn tại độc lập với Gateway lifecycle — xóa Gateway không xóa reserved IP.

HTTPRoute — Routing definition

HTTPRoute là namespaced resource, thường được tạo bởi application developer. Nó định nghĩa routing rules: request nào đi đến backend nào.

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-route
  namespace: team-a
spec:
  parentRefs:
    - name: external-gateway
      namespace: infra
      sectionName: https  # Attach vào listener "https"
  hostnames:
    - "api.example.com"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /v2
          headers:
            - name: X-API-Version
              value: "2"
      backendRefs:
        - name: api-v2-service
          port: 8080
          weight: 100
    - matches:
        - path:
            type: PathPrefix
            value: /v2
      backendRefs:
        - name: api-v2-service
          port: 8080
          weight: 90
        - name: api-v2-canary
          port: 8080
          weight: 10
    - backendRefs:
        - name: api-v1-service
          port: 8080

Matching precedence

HTTPRoute rules được evaluate theo thứ tự trong spec — rule đầu tiên match sẽ được dùng. Nhưng khi nhiều HTTPRoutes từ các namespaces khác nhau đều attach vào cùng một Gateway và có rules conflicting, GKE Gateway controller dùng precedence ordering theo:

  1. Specificity của hostname match (exact > wildcard)
  2. Specificity của path match (exact > prefix > regex)
  3. Specificity của header match (nhiều headers > ít headers)

Nếu vẫn tie, route được tạo trước (theo creation timestamp) sẽ thắng.

Traffic splitting (Canary deployment)

Traffic splitting trong HTTPRoute là một cơ chế native, không cần annotation:

yaml
rules:
  - backendRefs:
      - name: stable-service
        port: 8080
        weight: 95
      - name: canary-service
        port: 8080
        weight: 5

Cơ chế: Controller dịch weight thành tỷ lệ phần trăm traffic cho mỗi backend service trong URL Map. GFE phân phối traffic theo tỷ lệ này dựa trên consistent hashing — không phải per-request round-robin thuần túy.

Điểm quan trọng: weight: 0 không nghĩa là "gửi 0% traffic" theo cách bạn nghĩ. Nó nghĩa backend vẫn tồn tại trong URL Map nhưng không nhận traffic thông thường. Để loại bỏ hoàn toàn, phải xóa backend khỏi backendRefs.

Header matching

yaml
matches:
  - headers:
      - name: "X-Experiment"
        value: "new-ui"
        type: Exact

Header matching cho phép route specific requests đến specific backends — enabler cho A/B testing theo user segment.

GKE Gateway Controller — Cơ chế hoạt động

Controller là gì

GKE Gateway controller là Google-hosted controller (không chạy trong cluster của bạn, tương tự như GKE Ingress controller). Controller watch Kubernetes API của cluster và provision GCP LB resources tương ứng.

Theo tài liệu GKE: "Google-hosted controllers that watch the Kubernetes API for GKE clusters". Controller không phải networking data plane — nó quản lý load balancers out-of-band.

Có hai loại controller:

  • Single-cluster controller: Được enable mặc định khi enable Gateway API feature. Xử lý single-cluster Gateways.
  • Multi-cluster controller: Yêu cầu fleet registration. Xử lý Gateways với -mc suffix GatewayClasses, provision global LB với backends từ nhiều clusters.

Reconciliation flow

Khi bạn kubectl apply một Gateway:

  1. Controller nhận Watch event từ Kubernetes API
  2. Validate spec (GatewayClass tồn tại, listeners hợp lệ, etc.)
  3. Provision GCP resources theo dependency order:
    • Reserve IP address (nếu chưa có)
    • Tạo Target HTTPS Proxy (hoặc HTTP)
    • Tạo Forwarding Rule
    • (Đợi HTTPRoutes được attach)
  4. Update Gateway .status.conditions với provisioning progress

Khi HTTPRoute được tạo và attach vào Gateway:

  1. Controller compile tất cả HTTPRoutes attach vào Gateway thành một URL Map
  2. URL Map được áp vào Target Proxy
  3. Backend Services được tạo cho mỗi Service reference trong HTTPRoutes
  4. NEGs được tạo/attach vào Backend Services

Điểm quan trọng: Mỗi khi có HTTPRoute mới attach hoặc thay đổi, controller phải update URL Map — đây là operation trên GCP API, không phải chỉ trên Kubernetes objects.

Policy attachment model

Gateway API sử dụng Policy attachment thay vì CRDs riêng lẻ như BackendConfig/FrontendConfig:

yaml
# Tương đương BackendConfig trong Gateway API
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
  name: api-backend-policy
  namespace: team-a
spec:
  targetRef:
    group: ""
    kind: Service
    name: api-service
  default:
    securityPolicy: "my-cloud-armor-policy"
    timeoutSec: 30
    connectionDraining:
      drainingTimeoutSec: 60
    healthCheck:
      checkIntervalSec: 15
      timeoutSec: 5
      healthyThreshold: 1
      unhealthyThreshold: 3
      type: HTTP
      requestPath: /healthz
      port: 8080
yaml
# Tương đương FrontendConfig
apiVersion: networking.gke.io/v1
kind: GCPGatewayPolicy
metadata:
  name: gateway-frontend-policy
  namespace: infra
spec:
  targetRef:
    kind: Gateway
    name: external-gateway
  default:
    sslPolicy: "my-ssl-policy"

TLS Termination — Ba cách tiếp cận

Cách 1: Kubernetes Secrets

Đơn giản nhất, phù hợp cho một hoặc vài certs:

yaml
# Tạo Secret từ cert/key
kubectl create secret tls my-tls-cert \
  --cert=tls.crt \
  --key=tls.key \
  -n infra

# Tham chiếu trong Gateway
spec:
  listeners:
    - tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: my-tls-cert

Limitation: Kubernetes Secrets không tự-renew. Cần external tool (cert-manager) để tự động hóa renewal.

Cách 2: Certificate Manager

Certificate Manager là GCP-native service quản lý certificate lifecycle. Đây là cách khuyến nghị cho production:

yaml
# Tạo Certificate Manager Certificate
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: my-managed-cert
spec:
  domains:
    - app.example.com

# Trong Gateway — dùng annotation để reference Certificate Map
metadata:
  annotations:
    networking.gke.io/certmap: "my-cert-map"

Certificate Manager hỗ trợ đến 15+ certificates per Gateway — quan trọng cho multi-tenant Gateways phục vụ nhiều domains. Kubernetes Secret approach bị giới hạn hơn.

Certificate tự động được provision qua Google Trust Services (certs do Google quản lý, renew tự động) hoặc qua CA được import.

Cách 3: Google-managed SSL Certificates (legacy)

Cách cũ hơn, vẫn được hỗ trợ nhưng Certificate Manager là recommended:

yaml
metadata:
  annotations:
    networking.gke.io/managed-certificates: "my-cert"

Proxy-only subnet cho regional và internal Gateways

Giống như Internal Ingress, các Gateway sử dụng gke-l7-rilb (Internal) hoặc gke-l7-regional-external-managed (Regional External) đều yêu cầu proxy-only subnet trong VPC:

bash
gcloud compute networks subnets create proxy-only-subnet \
  --purpose=REGIONAL_MANAGED_PROXY \
  --role=ACTIVE \
  --region=us-central1 \
  --range=10.129.0.0/23 \
  --network=my-vpc

Gateway controller sẽ fail provision nếu proxy-only subnet không tồn tại. Error sẽ appear trong Gateway .status.conditions.

Giới hạn và constraints của GKE Gateway API

Chỉ hỗ trợ HTTPRoute

Theo tài liệu GKE hiện tại, GKE Gateway chỉ hỗ trợ HTTPRoute. Các route types khác trong Gateway API spec (TCPRoute, UDPRoute, TLSRoute, GRPCRoute) chưa được GKE implement. Nếu cần expose TCP services, vẫn phải dùng Service type: LoadBalancer.

Giới hạn số Gateways

GKE recommend giới hạn số Gateways tối đa là 100 per cluster để tránh controller overload. Mỗi Gateway là một forwarding rule + target proxy trong GCP — GCP quotas cũng áp dụng.

URL Map quota từ nhiều HTTPRoutes

Nhiều HTTPRoutes compile thành một URL Map. GCP URL Maps có quota về số lượng rules. Nếu cluster có nhiều teams, nhiều HTTPRoutes, URL Map rule count có thể hit quota — cần monitor và request quota increase.

Không hỗ trợ path redirect cùng lúc với URL rewrite

HTTPRoute filter hỗ trợ hoặc RequestRedirect (redirect đến URL khác) hoặc URLRewrite (rewrite path trước khi forward), nhưng không thể dùng cả hai trong cùng một rule. Đây là limitation từ GCP URL Map design.

Tính năng advanced cần GKE 1.27+

Custom request/response headers, path manipulation trong HTTPRoute filters chỉ được hỗ trợ từ GKE 1.27+. Cluster cũ hơn sẽ ignore các fields này mà không báo error.

Tại sao Gateway API thay thế Ingress

Nhìn lại, sự chuyển dịch từ Ingress sang Gateway API không chỉ là "API mới". Đây là sự chuyển dịch về operating model:

Khía cạnhIngressGateway API
Ai quản lý routing?Một người/team quản lý toàn bộ IngressPlatform team quản lý Gateway, app team quản lý HTTPRoute
Feature extensibilityQua annotations (hacky, implementation-specific)Qua Policy CRDs (structured, typed)
Traffic splittingKhông native (cần annotations của specific controller)Native (weight trong backendRefs)
Header routingKhông nativeNative (matches.headers)
Multi-namespace isolationKhông (một Ingress cross-namespace qua ExternalName)Có (allowedRoutes, ReferenceGrant)
PortabilityKhông (annotations thay đổi theo controller)Có (HTTPRoute spec là Kubernetes standard)
Certificate managementManual hoặc cert-managerCertificate Manager native integration

Với các hệ thống mới trên GKE, Gateway API là lựa chọn mặc định. Ingress nên được giữ lại chỉ khi đang vận hành hệ thống legacy có chi phí migration cao.

References