Kubernetes Gateway API 攻略:解鎖叢集流量服務新維度!

2023-11-20 12:05:17

Kubernetes Gateway API 剛剛 GA,旨在改進將叢集服務暴露給外部的過程。這其中包括一套更標準、更強大的 API資源,用於管理已暴露的服務。在這篇文章中,我將介紹 Gateway API 資源,並以 Istio 為例來展示這些資源是如何關聯的。通過這個範例,你將瞭解 Gateway API 的各個組成部分如何配合以將流量傳遞到後端服務。
 

背 景

允許外部與 Kubernetes 叢集內的服務通訊是 administrator 需要執行的最基本任務之一。Service 在 IP 層面上提供的功能十分有限,且缺乏根據應用層資料(如 DNS 主機名或 HTTP 路徑)路由流量的能力。因此 Kubernetes 提供了 Ingress API 來實現應用層路由。
 

然而,Ingress API 有一些限制。Ingress2gateway 的公告[1]清楚地列出了這些限制:

  • Ingress 側重於 HTTP 流量,因此使用者需要找到其他解決方案來處理 UDP、TCP 或其他協定。

  • Ingress 資源混合了基礎架構和應用程式設定,讓細粒度的基於角色的存取控制(RBAC)的實施變得較為困難。
     

第二點對於已經熟悉 Ingress 的使用者來說是最明顯的。在平臺工程中提供強大的 RBAC 是叢集管理的關鍵步驟。將基礎設施元件(負載均衡器、設定等)的許可權與流量路由規則的許可權分開,能夠讓許可權的邊界更加清晰。
 

接下來我將介紹 Gateway API 如何劃分這些資源,以及它們如何最終結合在一起來路由流量。
 

設定測試環境

本文使用執行 Istio 和一個範例工作負載的測試環境來檢查和理解各種 Gateway API 資源。如果你也想上手嘗試,可以複製這個環境。
 

我用的是 K3s,使用 Kubernetes 叢集也是類似的操作。如果選擇使用 K3s,則在安裝時不要啟用 Traefik:

$ curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --disable=traefik" sh -

 

首先,部署 Gateway API CRD(Custom Resource Definitions),並按照官方檔案安裝 Istio(https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/):

# Install the CRDs
$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
  { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.8.0" | kubectl apply -f -; }
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created

# Install Istio
$ istioctl install --set profile=minimal -y
✔ Istio core installed
✔ Istiod installed
✔ Installation complete
Made this installation the default for injection and validation.

 

接下來建立一個簡單的工作負載,比如一個 Nginx deployment ,並通過 deservice 將其暴露:

# Deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
# Service.yaml
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: ClusterIP
$ kubectl apply -f Deployment.yaml
deployment.apps/nginx created
$ kubectl apply -f Service.yaml
service/nginx created

 

以上就是你用來理解 Gateway API 所需的全部基礎設施。
 

瞭解 Gateway API 資源

想要使用 Gateway API,有三種資源型別你需要明確瞭解:

  • GatewayClass

  • Gateway

  • 路由資源,比如 HTTPRouteGRPCRoute。GA 版本僅包含在 v1 通道中到 HTTPRoute
     

這些資源在標準 Ingress API 或自定義提供商負載均衡器和路由工具提供的 CRD 中以各種方式組合在一起。通過將這些資源拆分為單獨的元件,Gateway API 實現了關注點分離和強大的、細粒度的存取控制。
 

讓我們逐個瞭解這些資源,以瞭解它們之間的關係。
 

瞭解 GatewayClass 資源

GatewayClass資源的作用與現有 Ingress API 中的 IngressClass相同,類似於 Storage API 中的 StorageClass。它定義了可以建立的 Gateway類別。通常,此資源由你的基礎架構平臺(如 EKS 或 GKE)提供。也可以由第三方的 Ingress Controller 提供,例如 Istio 或 Nginx。Istio 包含兩個 GatewayClasses

$ kubectl get gatewayclass
NAME           CONTROLLER                    ACCEPTED   AGE
istio-remote   istio.io/unmanaged-gateway    True       19h
istio          istio.io/gateway-controller   True       19h

 

spec欄位提供了有關實現 GatewayClass功能的 controller 的資訊,它定義了整個叢集使用的控制器,而 GatewayClasses 是叢集範圍的資源,適用於所有名稱空間。
 

$ kubectl get gatewayclass istio -o yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
  creationTimestamp: "2023-10-30T02:15:11Z"
  generation: 1
  name: istio
  resourceVersion: "636"
  uid: dea0bb44-5f1b-4d23-8f7f-c34f70b4603c
spec:
  controllerName: istio.io/gateway-controller
  description: The default Istio GatewayClass
status:
  conditions:
  - lastTransitionTime: "2023-10-30T02:15:11Z"
    message: Handled by Istio controller
    observedGeneration: 1
    reason: Accepted
    status: "True"
    type: Accepted

 

GatewayClass還可以指定傳遞給控制器的引數。這樣上游專案能夠進一步客製化向叢集管理員公開的設定。也就是說, GatewayClass允許叢集管理員專注於將其流量暴露給外部,而不必擔心例如在底層基礎設施上如何建立負載均衡器等實現細節。
 

建立 Gateway

Gateway 代表在基礎設施提供商中範例化的負載均衡器服務。它可以是一個實際的雲負載均衡器,用於處理流量。也可以代表現有負載均衡器中的虛擬設定。然後通過 GatewayClass 進行抽象。Cluster operator 專注於定義必要的 Gateway 資源,無需擔心由 GatewayClass 處理的實現細節。
 

Gateway 在其規範中參照了一個 GatewayClass。下面的範例使用 istio 類,並定義了一個響應埠 8080 上 *.example.com 的 HTTP 請求的單個偵聽器:

# Gateway.yaml
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: tutorial-gw
  namespace: default
spec:
  gatewayClassName: istio
  listeners:
  - name: default
    hostname: "*.example.com"
    port: 8080
    protocol: HTTP
    allowedRoutes:
      namespaces:
        from: All

 

使用 Istio 在建立 Gateway 時還會相應設定DeploymentService 來處理流量。GatewayClass 的控制器負責為 Gateway 處理所需的基礎設施或設定的設定:

$ kubectl get pods
NAME                                READY   STATUS    RESTARTS        AGE
tutorial-gw-istio-65bfccf7c-45c4w   1/1     Running   2 (6m31s ago)   18h

$ kubectl get service
NAME                TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                          AGE
tutorial-gw-istio   LoadBalancer   10.43.126.90   192.168.122.10   15021:31348/TCP,8080:31728/TCP   18h

 

這裡需要注意的是 Gateway 中沒有定義路由規則。Gateways 代表基礎設施的設定,這種分離對於實現 RBAC 至關重要。存取控制模型允許 cluster operator 設定可用的Gateways ,讓使用者在其路由資源中參照,而無需暴露對基礎設施設定本身的存取。
 

建立路由

現有的 Ingress API 僅支援 HTTP 和 HTTPS 服務,這是一個比較大的限制。
 

而新的 Gateway API 為各種入站流量型別提供通用支援。 HTTPRouteTCPRouteTLSRouteGRPCRoute 等資源在特定 Gateway 上指定了實際的流量路由。Gateway API 的 GA 版本只在標準的 v1 通道中包含了 HTTPRoute資源,在未來的版本中將會有更多的協定支援。
 

HTTPRoute資源指定與用於暴露服務的 Gateway 的連線,以及一系列規則來將流量路由到適當的後端。下面的範例將 HTTPRoute附加到 tutorial-gw Gateway,並指定規則將所有流量路由到 nginx Service:

---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: tutorial-route
  namespace: default
spec:
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: tutorial-gw
  rules:
  - backendRefs:
    - group: ""
      kind: Service
      name: nginx
      port: 80
      weight: 1
    matches:
    - path:
        type: PathPrefix
        value: /
$ kubectl apply -f HTTPRoute.yaml
httproute.gateway.networking.k8s.io/tutorial-route created
$ kubectl get httproute
NAME             HOSTNAMES   AGE
tutorial-route               6s

 

綜合以上

Gateway API 將許多傳統上包含在單個資源定義中的資源拆分開來。要跟蹤所有這些資源之間的連線可能有點困難,這裡我將資源之間的關係圖展示如下:

Gateway API 資源之間的關係
 

快速回顧

  • GatewayClass 定義了可以部署的 Gateway 型別。通常由基礎設施提供商提供。在本範例中,Istio 定義了GatewayClass

  • Gateway 是負載均衡基礎設施的範例化。這可以是在雲環境中部署的實際負載均衡器,也可以是針對現有負載均衡器執行的一些設定。無論哪種方式,通過簡單地參照所需的GatewayClass ,就能從 cluster administrator 中抽象出來。

  • HTTPRoute(或任何其他支援的 Route 資源)定義了處理流量的實際規則。這些路由附加到特定的 Gateway,最終決定了流量的轉發。

 

有了所有這些設定,就可以對服務進行測試請求。本範例Gateway 設定為偵聽埠 8080 上 *.example.com 的 HTTP 請求,因此你的請求需要設定適當的 Host header 和埠:

$ curl -H "Host: www.example.com" 192.168.122.10:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

 

這樣,你就使用新的閘道器 API 成功設定了第一組資源咯!
 

連結:
https://itnext.io/what-you-should-know-about-the-kubernetes-gateway-api-801d46b68ae2