成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Istio 使用 Gateway API 實現流量管理

開源
Gateway API 最初設計用于管理從集群外部客戶端到集群內部服務的流量(入口或北/南情況)。隨著時間的推移,服務網格用戶的興趣促使 GAMMA(Gateway API for Service Mesh)計劃的創建,以定義 Gateway API 如何用于同一集群內的服務間或東/西流量。

Gateway API 是由 SIG-NETWORK 社區管理的開源項目,項目地址:https://gateway-api.sigs.k8s.io/。主要原因是 Ingress 資源對象不能很好的滿足網絡需求,很多場景下 Ingress 控制器都需要通過定義 annotations 或者 crd 來進行功能擴展,這對于使用標準和支持是非常不利的,新推出的 Gateway API 旨在通過可擴展的面向角色的接口來增強服務網絡。

Gateway API 是 Kubernetes 中的一個 API 資源集合,包括 GatewayClass、Gateway、HTTPRoute、TCPRoute、Service 等,這些資源共同為各種網絡用例構建模型。

Gateway API

Gateway API 最初設計用于管理從集群外部客戶端到集群內部服務的流量(入口或北/南情況)。隨著時間的推移,服務網格用戶的興趣促使 GAMMA(Gateway API for Service Mesh)計劃的創建,以定義 Gateway API 如何用于同一集群內的服務間或東/西流量。

Gateway API 的改進比當前的 Ingress 資源對象有很多更好的設計:

  • 面向角色 - Gateway 由各種 API 資源組成,這些資源根據使用和配置 Kubernetes 服務網絡的角色進行建模。
  • 通用性 - 和 Ingress 一樣是一個具有眾多實現的通用規范,Gateway API 是一個被設計成由許多實現支持的規范標準。
  • 更具表現力 - Gateway API 資源支持基于 Header 頭的匹配、流量權重等核心功能,這些功能在 Ingress 中只能通過自定義注解才能實現。
  • 可擴展性 - Gateway API 允許自定義資源鏈接到 API 的各個層,這就允許在 API 結構的適當位置進行更精細的定制。

還有一些其他值得關注的功能:

  • GatewayClasses - GatewayClasses 將負載均衡實現的類型形式化,這些類使用戶可以很容易了解到通過 Kubernetes 資源可以獲得什么樣的能力。
  • 共享網關和跨命名空間支持 - 它們允許共享負載均衡器和 VIP,允許獨立的路由資源綁定到同一個網關,這使得團隊可以安全地共享(包括跨命名空間)基礎設施,而不需要直接協調。
  • 規范化路由和后端 - Gateway API 支持類型化的路由資源和不同類型的后端,這使得 API 可以靈活地支持各種協議(如 HTTP 和 gRPC)和各種后端服務(如 Kubernetes Service、存儲桶或函數)。
  • 服務網格支持 - Gateway API 支持將路由資源與服務資源關聯,以配置服務網格以及入口控制器。

面向角色設計

無論是道路、電力、數據中心還是 Kubernetes 集群,基礎設施都是為了共享而建的,然而共享基礎設施提供了一個共同的挑戰,那就是如何為基礎設施用戶提供靈活性的同時還能被所有者控制。

Gateway API 通過對 Kubernetes 服務網絡進行面向角色的設計來實現這一目標,平衡了靈活性和集中控制。它允許共享的網絡基礎設施(硬件負載均衡器、云網絡、集群托管的代理等)被許多不同的團隊使用,所有這些都受到集群運維設置的各種策略和約束。

gateway api demo

一個集群運維人員創建了一個基于 GatewayClass 的 Gateway 資源,這個 Gateway 配置了它所代表的基礎網絡資源,集群運維和特定的團隊必須溝通什么可以附加到這個 Gateway 上來暴露他們的應用。 集中的策略,如 TLS,可以由集群運維在 Gateway 上強制執行,同時,Store 和 Site 應用在他們自己的命名空間中運行,但將他們的路由附加到相同的共享網關上,允許他們獨立控制他們的路由邏輯。

這種關注點分離的設計可以使不同的團隊能夠管理他們自己的流量,同時將集中的策略和控制留給集群運維。

概念

在整個 Gateway API 中涉及到 3 個角色:基礎設施提供商、集群管理員、應用開發人員,在某些場景下可能還會涉及到應用管理員等角色。Gateway API 中定義了 3 種主要的資源模型:GatewayClass、Gateway、Route。

GatewayClass

GatewayClass 定義了一組共享相同配置和動作的網關。每個 GatewayClass 由一個控制器處理,是一個集群范圍的資源,必須至少有一個 GatewayClass 被定義。

這與 Ingress 的 IngressClass 類似,在 Ingress v1beta1 版本中,與 GatewayClass 類似的是 ingress-class 注解,而在 Ingress V1 版本中,最接近的就是 IngressClass 資源對象。

Gateway

Gateway 網關描述了如何將流量轉化為集群內的服務,也就是說,它定義了一個請求,要求將流量從不了解 Kubernetes 的地方轉換到集群內的服務。例如,由云端負載均衡器、集群內代理或外部硬件負載均衡器發送到 Kubernetes 服務的流量。

它定義了對特定負載均衡器配置的請求,該配置實現了 GatewayClass 的配置和行為規范,該資源可以由管理員直接創建,也可以由處理 GatewayClass 的控制器創建。

Gateway 可以附加到一個或多個路由引用上,這些路由引用的作用是將流量的一個子集導向特定的服務。

Route 資源

路由資源定義了特定的規則,用于將請求從網關映射到 Kubernetes 服務。從 v1alpha2 版本開始,API 中包含四種 Route 路由資源類型。

HTTPRoute

HTTPRoute 是用于 HTTP 或 HTTPS 連接,適用于我們想要檢查 HTTP 請求并使用 HTTP 請求進行路由或修改的場景,比如使用 HTTP Headers 頭進行路由,或在請求過程中對它們進行修改。

TLSRoute

TLSRoute 用于 TLS 連接,通過 SNI 進行區分,它適用于希望使用 SNI 作為主要路由方法的地方,并且對 HTTP 等更高級別協議的屬性不感興趣,連接的字節流不經任何檢查就被代理到后端。

TCPRoute 和 UDPRoute

TCPRoute(和 UDPRoute)旨在用于將一個或多個端口映射到單個后端。在這種情況下,沒有可以用來選擇同一端口的不同后端的判別器,所以每個 TCPRoute 在監聽器上需要一個不同的端口。你可以使用 TLS,在這種情況下,未加密的字節流會被傳遞到后端,當然也可以不使用 TLS,這樣加密的字節流將傳遞到后端。

GRPCRoute

GRPCRoute 用于路由 gRPC 流量,支持 GRPCRoute 的網關必須支持 HTTP/2,無需從 HTTP/1 進行初始升級,因此可以確保 gRPC 流量正常進行。

組合

GatewayClass、Gateway、xRoute 和 Service 的組合定義了一個可實施的負載均衡器,下圖說明了不同資源之間的關系:

組合關系

使用反向代理實現的網關的典型客戶端/網關 API 請求流程如下所示:

  • 客戶端向 http://foo.example.com 發出請求。
  • DNS 將域名解析為 Gateway 網關地址。
  • 反向代理在監聽器上接收請求,并使用 Host Header 來匹配 HTTPRoute。
  • (可選)反向代理可以根據 HTTPRoute 的匹配規則進行路由。
  • (可選)反向代理可以根據 HTTPRoute 的過濾規則修改請求,即添加或刪除 headers。
  • 最后,反向代理根據 HTTPRoute 的 forwardTo 規則,將請求轉發給集群中的一個或多個對象,即服務。

與 Istio API 的區別

我們這里主要是講解 Gateway API 在服務網格中的使用,首先我們先了解下 Gateway API 與 Istio API 的區別。

Gateway API 與 Istio API(如 Gateway 和 VirtualService)有很多相似之處。主資源使用相同的 Gateway 名稱,并且這些資源服務于相類似的目標。

新的 Gateway API 致力于從 Kubernetes 的各種 Ingress 實現(包括 Istio)中吸取經驗,以構建標準化的,獨立于供應商的 API。這些 API 通常與 Istio Gateway 和 VirtualService 具有相同的用途,但依然有一些不同的地方:

  • Istio API 中的 Gateway 僅配置已部署的現有網關 Deployment/Service,而在 Gateway API 中的 Gateway 資源不僅配置也會部署網關。
  • 在 Istio VirtualService 中,所有協議都在單一的資源中配置,而在 Gateway API 中,每種協議類型都有自己的資源,例如 HTTPRoute 和 TCPRoute。
  • 雖然 Gateway API 提供了大量豐富的路由功能,但它還沒有全部涵蓋 Istio 的全部特性。

實現

接下來我們就來了解下如何在 Istio z 中使用 Gateway API。默認情況下 Kubernetes 集群中不會安裝 Gateway API,首先我們需要安裝 Gateway API CRD:

$ kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml
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

standard-install.yaml 包括所有已升級為 GA 或 Beta 的資源,包括 GatewayClass、Gateway、HTTPRoute 和 ReferenceGrant,由于 Istio 已經對 Gateway API 提供了支持,所以現在我們就可以直接使用了。比如現在就會自動創建一個 istio 的 GatewayClass 資源對象,如下所示(另外還有一個名為 istio-remote):

$ kubectl get gatewayclass
NAME           CONTROLLER                    ACCEPTED   AGE
istio          istio.io/gateway-controller   True       106s
istio-remote   istio.io/unmanaged-gateway    True       106s
$ kubectl get gatewayclass istio -oyaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: istio
spec:
  controllerName: istio.io/gateway-controller
  description: The default Istio GatewayClass

因為大部分場景下在一個 Kubernetes 集群中只會有一個 Istio 集群,所以我們可以直接使用默認的 istio 這個 GatewayClass,如果你有多個 Istio 集群,那么你可以創建多個 GatewayClass 來區分不同的集群。

比如接下來我們來嘗試將 httpbin 應用使用 Gateway API 暴露到外部,首先我們需要部署一個 httpbin 應用:

kubectl apply -f samples/httpbin/httpbin.yaml

然后接下來同樣我們需要部署一個 Gateway 資源對象,用于將流量從外部負載均衡器轉發到集群內的服務,如下所示:

# default-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway
  namespace: istio-ingress # 網關資源對象所在的命名空間
spec:
  gatewayClassName: istio # 使用默認的 istio GatewayClass
  listeners: # 監聽器
    - name: default
      hostname: "*.example.com"
      port: 80
      protocol: HTTP
      allowedRoutes: # 允許的路由
        namespaces:
          from: All # 允許所有命名空間

Gateway 代表了邏輯負載均衡器的實例化,它是根據一個 istio 這個 GatewayClass 進行模板化的,網關在 80 端口上監聽 HTTP 流量,這個特定的 GatewayClass 在部署后會自動分配一個 IP 地址,該地址會顯示在 Gateway.status 中。

需要注意的是這里我們聲明使用的命名空間為 istio-ingress, 這是因為 Istio Gateway 可以直接使用 istio ingressgateway 的 Deployment,而這個 Deployment 默認是部署在 istio-system 命名空間中的,我們這里單獨將 Gateway 資源對象創建在 istio-ingress 命名空間中,那么就會自動在這個命名空間中部署一個網關控制器,用于區分默認的 istio ingressgateway。

所以我們需要在 istio-ingress 命名空間中創建這個 Gateway 資源對象,這樣才能讓 istio ingressgateway 通過 Gateway 資源對象來獲取配置。

kubectl create namespace istio-ingress

然后直接應用這個資源對象即可:

$ kubectl apply -f default-gateway.yaml
$ kubectl get gateway -n istio-ingress
NAME      CLASS   ADDRESS   PROGRAMMED   AGE
gateway   istio             False        8m23s
$ kubectl get deploy -n istio-ingress
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
gateway-istio   1/1     1            1           8m35s
$ kubectl get svc -n istio-ingress
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                        AGE
gateway-istio   LoadBalancer   10.100.103.86   <pending>     15021:31509/TCP,80:32530/TCP   9m38s

我們也可以去對比下上面生成的 gateway-istio 和 Istio 默認的 istio-ingressgateway 的 Deployment,他們的配置幾乎是一樣的。

接下來我們就需要去創建一個路由規則了,也就是想要如何訪問我們的 httpbin 應用,類似于 VirtualService,我們可以使用 HTTPRoute 資源對象來定義這個路由規則,如下所示:

# httpbin-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
  namespace: default
spec:
  parentRefs: # 引用定義的 Gateway 對象
    - name: gateway
      namespace: istio-ingress
  hostnames: ["httpbin.example.com"] # 域名
  rules: # 具體的路由規則
    - matches:
        - path:
            type: PathPrefix
            value: /get # 匹配 /get 的請求
      backendRefs: # 引用的后端服務
        - name: httpbin
          port: 8000

在上面的 HTTPRoute 對象中我們通過 parentRefs 字段指定要連接到的網關,只要網關允許這種連接,這將允許路由接收來自父網關的流量,在 backendRefs 中定義將要發送流量的后端。但是需要注意我們這里只定義了匹配 /get 這個路徑的請求,然后將要訪問的域名通過 hostnames 來定義。

同樣直接應用該資源對象即可:

$ kubectl apply -f httpbin-route.yaml
$ kubectl get httproute
NAME      HOSTNAMES                 AGE
httpbin   ["httpbin.example.com"]   5s

然后我們就可以通過 httpbin.example.com 來訪問 httpbin 應用了:

# $ export INGRESS_HOST=$(kubectl get gateways.gateway.networking.k8s.io gateway -n istio-ingress -ojsnotallow='{.status.addresses[0].value}')
export GATEWAY_URL=$(kubectl get po -l istio.io/gateway-name=gateway -n istio-ingress -o 'jsnotallow={.items[0].status.hostIP}'):$(kubectl get svc gateway-istio -n istio-ingress -o 'jsnotallow={.spec.ports[?(@.name=="default")].nodePort}')

如果你的集群可以正常使用 LoadBalancer,那么 Gateway 控制器在部署后會自動分配一個 IP 地址,該地址會顯示在 Gateway.status 中。我們這里暫不支持,所以還是可以通過 NodePort 方式來進行訪問。然后可以使用 curl 訪問 httpbin 服務:

$ curl -s -HHost:httpbin.example.com "http://$GATEWAY_URL/get"
HTTP/1.1 200 OK
server: istio-envoy
date: Mon, 18 Dec 2023 07:29:11 GMT
content-type: application/json
content-length: 494
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 2

請注意,使用 -H 標志可以將 Host HTTP 標頭設置為 httpbin.example.com。這一步是必需的,因為 HTTPRoute 已配置為處理 httpbin.example.com 的請求,但是在測試環境中,該主機沒有 DNS 綁定,只是將請求發送到入口 IP。

訪問其他沒有被顯式暴露的 URL 時,正常就會看到 HTTP 404 錯誤:

$ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/headers"
HTTP/1.1 404 Not Found
date: Mon, 18 Dec 2023 07:31:51 GMT
server: istio-envoy
transfer-encoding: chunked

同樣我們也可以查看下 gateway-istio 的日志,可以看到類似于下面的日志:

$ kubectl -n istio-ingress logs -f gateway-istio-7474cd4d9b-8dw2k
# ......
2023-12-18T07:04:33.164968Z     info    cache   returned workload trust anchor from cache       ttl=23h59m59.835033638s
2023-12-18T07:04:33.621616Z     info    Readiness succeeded in 813.201909ms
2023-12-18T07:04:33.621946Z     info    Envoy proxy is ready
[2023-12-18T07:29:11.177Z] "HEAD /get HTTP/1.1" 200 - via_upstream - "-" 0 0 2 2 "10.244.1.1" "curl/7.29.0" "68f51e89-8125-4d9e-be36-e0cdc6e6ead8" "httpbin.example.com" "10.244.1.131:80" outbound|8000||httpbin.default.svc.cluster.local 10.244.1.132:46066 10.244.1.132:80 10.244.1.1:55626 - default.httpbin.0
[2023-12-18T07:31:52.051Z] "HEAD /headers HTTP/1.1" 404 NR route_not_found - "-" 0 0 0 - "10.244.1.1" "curl/7.29.0" "a9a1002f-d65c-40d8-861d-ec99d4a4a442" "httpbin.example.com" "-" - - 10.244.1.132:80 10.244.1.1:53583 - -

證明我們的路由規則已經生效了。

同樣如果我們想要能夠正常訪問刀 /headers 路由,那么我們可以更新下 HTTPRoute 對象:

# httpbin-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
  namespace: default
spec:
  parentRefs: # 引用定義的 Gateway 對象
    - name: gateway
      namespace: istio-ingress
  hostnames: ["httpbin.example.com"] # 域名
  rules: # 具體的路由規則
    - matches:
        - path:
            type: PathPrefix
            value: /get # 匹配 /get 的請求
        - path:
            type: PathPrefix
            value: /headers # 匹配 /headers 的請求
      filters:
        - type: RequestHeaderModifier # 添加一個修改請求頭的過濾器
          requestHeaderModifier:
            add: # 添加一個標頭
              - name: my-added-header
                value: added-value
      backendRefs: # 引用的后端服務
        - name: httpbin
          port: 8000

我們除了在 rules 中添加了一個匹配 /headers 的規則外,還添加了一個 RequestHeaderModifier 過濾器,用于添加一個 Header 頭信息,更新這個資源對象后再次訪問 /headers,注意到 My-Added-Header 標頭已被添加到請求中了:

$ curl -s -HHost:httpbin.example.com "http://$GATEWAY_URL/headers"
{
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin.example.com",
    "My-Added-Header": "added-value",  # 添加了一個Header頭
    "User-Agent": "curl/7.29.0",
    "X-Envoy-Attempt-Count": "1",
    "X-Envoy-Internal": "true",
    "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=11fc66a1c6c9fc44e65ec67f7f8b16d06fbaa73d9729e141e0bd91134dc59db3;Subject=\"\";URI=spiffe://cluster.local/ns/istio-ingress/sa/gateway-istio"
  }
}

在上面的示例中,在配置網關之前,我們并沒有去安裝 Ingress 網關的 Deployment,因為在默認配置中會根據 Gateway 配置自動分發網關 Deployment 和 Service。但是對于高級別的場景可能還是需要去手動部署。

自動部署

默認情況下,每個 Gateway 將自動提供相同名稱的 Service 和 Deployment。如果 Gateway 發生變化(例如添加了一個新端口),這些配置將會自動更新。這些資源可以通過以下幾種方式進行定義:

  • 將 Gateway 上的注解和標簽復制到 Service 和 Deployment。這就允許配置從上述字段中讀取到的內容,如配置內部負載均衡器等。Istio 提供了一個額外的注解來配置生成的資源:
  • networking.istio.io/service-type:控制 Service.spec.type 字段。例如設置 ClusterIP 為不對外暴露服務,將會默認為 LoadBalancer。
  • 通過配置addresses字段可以顯式設置Service.spec.loadBalancerIP字段:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: gateway
spec:
addresses:
    - value: 192.0.2.0 # 僅能指定一個地址
    type: IPAddress

手動部署

如果您不希望使用自動部署,可以進行手動配置 Deployment 和 Service。完成此選項后,您將需要手動將 Gateway 鏈接到 Service,并保持它們的端口配置同步。

要將 Gateway 鏈接到 Service,需要將 addresses 字段配置為指向單個 Hostname。

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: gateway
spec:
  addresses:
    - value: ingress.istio-gateways.svc.cluster.local
      type: Hostname

當然我們這里只是一個最簡單的示例,我們將在后面的課程中繼續介紹 Gateway API 的更多功能。

配置請求路由

接下來我們來了解下如果通過 Gateway API 將請求動態路由到微服務的多個版本。

同樣我們這里以 Bookinfo 示例為例(首先要部署 Bookinfo 應用),我們首先將所有流量路由到微服務的 v1 (版本 1),然后將應用規則根據 HTTP 請求 header 的值路由流量。

首先專門為 Bookinfo 應用創建一個 Gateway 資源對象,如下所示:

# bookinfo-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  gatewayClassName: istio
  listeners:
    - name: http
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: Same

上面的 Gateway 資源對象與之前的示例類似,只是這里我們將 allowedRoutes 設置為 Same,表示允許同一命名空間中的所有路由資源對象都可以連接到這個網關。

然后為 Productpage 應用創建一個 HTTPRoute 資源對象,如下所示:

# productpage-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: bookinfo
spec:
  parentRefs:
    - name: bookinfo-gateway # 引用上面定義的 Gateway 對象
  rules:
    - matches:
        - path:
            type: Exact
            value: /productpage
        - path:
            type: PathPrefix
            value: /static
        - path:
            type: Exact
            value: /login
        - path:
            type: Exact
            value: /logout
        - path:
            type: PathPrefix
            value: /api/v1/products
      backendRefs:
        - name: productpage # 引用的后端服務
          port: 9080

和以前 VirtualService 的類似,我們為 Productpage 應用配置了幾個路由規則,這樣我們就可以在頁面上正常訪問應用了。直接應用上面的兩個資源清單文件即可:

kubectl apply -f bookinfo-gateway.yaml
kubectl apply -f productpage-route.yaml

同樣當我們創建了 Gateway 對象后,會自動在 default 命名空間中部署一個 gateway-istio 的 Deployment 和 對應的 Service:

$ kubectl get pods -l istio.io/gateway-name=bookinfo-gateway
NAME                                      READY   STATUS    RESTARTS   AGE
bookinfo-gateway-istio-548556df95-kggs2   1/1     Running   0          112s
$ kubectl get svc bookinfo-gateway-istio
NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                        AGE
bookinfo-gateway-istio   LoadBalancer   10.111.86.147   <pending>     15021:30357/TCP,80:30749/TCP   2m19s

正常我們就可以通過上面的 30749 這個 NodePort 端口來訪問 Productpage 應用了:

bookinfo

路由到版本 1

同樣的頁面上的評論區域會出現 3 種不同的狀態,因為我們背后有 3 個不同的版本的評論服務,我們可以創建一個如下所示的 HTTPRoute 資源對象,首先將流量路由到 v1 版本:

# route-reviews-v1.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs: # 這里我們引用的是 reviews 這個 Service 對象
    - group: ""
      kind: Service
      name: reviews
      port: 9080
  rules:
    - backendRefs:
        - name: reviews-v1
          port: 9080

注意上面的資源對象中我們是通過 parentRefs 字段引用的是 reviews 這個 Service 對象,而不是 Gateway 對象了,因為我們流量并不是從 Gateway 直接過來的,而是通過 Productpage 訪問 reviews 服務,也就是 Service 對象。然后背后的我們會將流量全部路由到 v1 版本的 reviews 服務 reviews-v1。

現在我們再應用上面的這個資源對象:

kubectl apply -f route-reviews-v1.yaml

不過這里需要注意不同于 Istio API 使用 DestinationRule 子集來定義服務的版本, Kubernetes Gateway API 將為此使用后端 Service 服務來進行定義。所以我們還需要運行以下命令為三個版本的 reviews 服務創建后端服務定義:

kubectl apply -f samples/bookinfo/platform/kube/bookinfo-versions.yaml

然后我們可以通過再次刷新 Bookinfo 應用程序,現在我們無論刷新多少次,頁面的評論部分都不會顯示評級星標,這是因為我們將 Istio 配置為將評論服務的所有流量路由到版本 reviews:v1,而此版本的服務不訪問星級評分服務。

reviews v1

基于用戶身份路由

接下來我們來更改路由配置,將來自特定用戶的所有流量路由到特定服務版本,比如將來自名為 Jason 的用戶的所有流量被路由到服務 reviews:v2(包含星級評分功能的版本)。

創建一個如下所示的 HTTPRoute 資源對象:

# route-reviews-jason-v2.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs:
    - group: ""
      kind: Service
      name: reviews
      port: 9080
  rules:
    - matches:
        - headers: # 匹配請求頭 end-user: jason
            - name: end-user
              value: jason
      backendRefs:
        - name: reviews-v2
          port: 9080
    - backendRefs:
        - name: reviews-v1
          port: 9080

在上面的 HTTPRoute 資源對象中,我們將訪問 reviews 的流量分為兩個規則,第一個規則匹配請求頭 end-user: jason,然后將流量路由到 reviews-v2 服務,第二個則是如果不匹配將流量路由到 reviews-v1 服務。

然后我們再次應用這個資源對象:

kubectl apply -f route-reviews-jason-v2.yaml

然后我們在 Bookinfo 頁面上面,可以以用戶 jason 身份進行登錄,登錄后無論如何刷新瀏覽器,我們將始終在頁面上看到黑色的星級評分,也就是 reviews 的 v2 版本。

jason 用于

我們也可以切換成其他用戶,或者不登錄,刷新瀏覽器,那么就不會顯示星級評分了。

基于權重的路由

接下來我們再來測試下基于權重的路由,常常我們有將流量從微服務的一個版本逐步遷移到另一個版本的需求,同樣使用 Gateway API 來實現也非常簡單。

下面我們將會把 50% 的流量發送到 reviews:v1,另外,50% 的流量發送到 reviews:v3。接著,再把 100% 的流量發送到 reviews:v3 來完成遷移。

首先重新運行下面的命令將所有流量路由到 review 服務的 v1 版本。

kubectl apply -f route-reviews-v1.yaml

接下來創建如下所示的資源對象,把 50% 的流量從 reviews:v1 轉移到 reviews:v3:

# route-reviews-50-v3.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs:
    - group: ""
      kind: Service
      name: reviews
      port: 9080
  rules:
    - backendRefs:
        - name: reviews-v1
          port: 9080
          weight: 50
        - name: reviews-v3
          port: 9080
          weight: 50

上面的對象中在 backendRefs 中我們使用了一個 weight 字段,用于設置權重,這里我們將 reviews-v1 和 reviews-v3 的權重都設置為 50,也就是說將流量平均分配到這兩個版本的服務上。

然后我們應用這個資源對象即可:

kubectl apply -f route-reviews-50-v3.yaml

等待幾秒鐘,等待新的規則傳播到代理中生效,然后我們再次刷新瀏覽器中的 productpage 頁面,大約有 50% 的幾率會看到頁面中帶紅色星級的評價內容。 這是因為 reviews 的 v3 版本可以訪問帶星級評價,但 v1 版本不能。

如果你認為 reviews:v3 微服務已經穩定,那么接下來我們就可以將 100% 的流量路由 reviews:v3:

# route-reviews-v3.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs:
    - group: ""
      kind: Service
      name: reviews
      port: 9080
  rules:
    - backendRefs:
        - name: reviews-v3
          port: 9080

然后我們再次應用這個資源對象:

kubectl apply -f route-reviews-v3.yaml

現在,當我們訪問 Bookinfo 應用時,將始終看到帶有紅色星級評分的書評。

使用 TLS 暴露服務

接下來我們來看下如何通過 TLS 來暴露服務,這里我們以 httpbin 示例進行說明。

首先要部署 httpbin 示例:

kubectl apply -f samples/httpbin/httpbin.yaml

然后接下來生成客戶端和服務器證書和密鑰,這里我們使用 openssl 工具來生成。

首先創建用于服務簽名的根證書和私鑰:

$ mkdir example_certs1
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs1/example.com.key -out example_certs1/example.com.crt

為 httpbin.example.com 創建證書和私鑰:

$ openssl req -out example_certs1/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
$ openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 0 -in example_certs1/httpbin.example.com.csr -out example_certs1/httpbin.example.com.crt

然后接下來需要為入口網關創建 Secret:

kubectl create -n istio-system secret tls httpbin-credential \
  --key=example_certs1/httpbin.example.com.key \
  --cert=example_certs1/httpbin.example.com.crt

這里我們創建一個獨立的 Kubernetes Gateway:

# httpbin-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: mygateway
  namespace: istio-system
spec:
  gatewayClassName: istio
  listeners:
    - name: https
      hostname: "httpbin.example.com"
      port: 443
      protocol: HTTPS
      tls:
        mode: Terminate
        certificateRefs:
          - name: httpbin-credential
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              kubernetes.io/metadata.name: default

在上面的對象中我們配置了 HTTPS 協議,并在 tls 中配置使用 Terminate 模式,也就是說我們將在網關上終止 TLS 連接,然后在 certificateRefs 中引用了之前創建的 Secret 對象,用于配置網關的憑據。最后通過 allowedRoutes 字段配置了允許的路由,這里我們配置的是將流量路由到 default 命名空間中的所有路由資源對象。

接下來,通過定義相應的 HTTPRoute 配置網關的入口流量路由:

# httpbin-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
spec:
  parentRefs:
    - name: mygateway
      namespace: istio-system
  hostnames: ["httpbin.example.com"]
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /status
        - path:
            type: PathPrefix
            value: /delay
      backendRefs:
        - name: httpbin
          port: 8000

這里最重要的就是在 parentRefs 字段中引用了之前創建的 Gateway 對象。

然后我們直接應用上面的兩個資源對象即可:

kubectl apply -f httpbin-gateway.yaml
kubectl apply -f httpbin-route.yaml

同樣應用后會自動在 istio-system 命名空間中部署一個 gateway-istio 的 Deployment 和對應的 Service:

$ kubectl get pods -n istio-system
NAME                                       READY   STATUS    RESTARTS         AGE
mygateway-istio-64676bfc88-q8nft           1/1     Running   0                32s
$ kubectl get svc -n istio-system
NAME                      TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                                      AGE
mygateway-istio           LoadBalancer   10.111.175.36    <pending>     15021:31206/TCP,443:32597/TCP                                                74s

然后我們可以通過 32597 這個 NodePort 端口向 httpbin 服務發送 HTTPS 請求:

$ curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:32597:192.168.0.100" --cacert example_certs1/example.com.crt "https://httpbin.example.com:32597/status/418"

* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: example_certs1/example.com.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*       subject: O=httpbin organization,CN=httpbin.example.com
*       start date: Dec 22 07:13:47 2023 GMT
*       expire date: Dec 21 07:13:47 2024 GMT
*       common name: httpbin.example.com
*       issuer: CN=example.com,O=example Inc.
# ......

    -=[ teapot ]=-

       _...._
     .'  _ _ `.
    | ."` ^ `". _,
    \_;`"---"`|//
      |       ;/
      \_     _/
        `"""`
* Connection #0 to host httpbin.example.com left intact

正常我們就可以看到輸出一個茶壺,這樣我們完成了通過 TLS 來暴露服務。

TCP 路由

除了 HTTP 路由外,Gateway API 還支持 TCP 和 UDP 路由,配置 TCP 的路由規則,需要使用單獨的資源對象 TCPRoute,如下所示:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: tcp-echo-gateway
spec:
  gatewayClassName: istio
  listeners:
    - name: tcp-31400
      protocol: TCP
      port: 31400
      allowedRoutes: # 只允許 TCPRoute 資源對象連接到這個網關
        kinds:
          - kind: TCPRoute
---
apiVersion: v1
kind: Service
metadata:
  name: tcp-echo-v1
spec:
  ports:
    - port: 9000
      name: tcp
  selector:
    app: tcp-echo
    version: v1
---
apiVersion: v1
kind: Service
metadata:
  name: tcp-echo-v2
spec:
  ports:
    - port: 9000
      name: tcp
  selector:
    app: tcp-echo
    version: v2
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute # TCPRoute 資源對象
metadata:
  name: tcp-echo
spec:
  parentRefs: # 引用定義的 Gateway 對象
    - name: tcp-echo-gateway
      sectionName: tcp-31400
  rules:
    - backendRefs:
        - name: tcp-echo-v1
          port: 9000
          weight: 80
        - name: tcp-echo-v2
          port: 9000
          weight: 20

其他使用

其他的流量管理比如故障注入、熔斷這些,Gateway API 尚不支持。

但是支持請求超時,比如對 reviews 服務的調用增加一個半秒的請求超時,可以使用下面的資源對象:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs:
    - group: ""
      kind: Service
      name: reviews
      port: 9080
  rules:
    - backendRefs:
        - name: reviews-v2
          port: 9080
      timeouts:
        request: 500ms

上面的對象中我們添加了一個 timeouts 字段,用于設置請求超時時間。

同樣還支持流量鏡像,如下的資源對象:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
spec:
  parentRefs:
    - group: ""
      kind: Service
      name: httpbin
      port: 8000
  rules:
    - filters:
        - type: RequestMirror
          requestMirror:
            backendRef:
              name: httpbin-v2
              port: 80
      backendRefs:
        - name: httpbin-v1
          port: 80

在上面的資源對象中我們添加了一個 RequestMirror 過濾器,該過濾器用于將流量鏡像到另外的服務上去。

責任編輯:姜華 來源: k8s技術圈
相關推薦

2021-07-27 06:51:53

Istio 微服務Service Mes

2025-04-17 09:09:29

2023-11-09 07:23:57

Istio路由分析

2021-07-28 06:26:33

Istio 流量管理微服務

2022-05-10 07:46:08

Envoy網絡通訊

2023-11-07 17:32:31

Istiok8s

2022-01-06 07:46:01

Traefik 開源Gateway API

2024-07-05 11:13:05

2023-11-08 00:23:08

網關API

2021-11-01 08:16:26

模型Istio服務

2024-09-23 08:03:59

2023-06-05 08:00:00

mTLSIstio安全

2022-11-24 08:35:28

KitexProxyless

2024-05-09 08:24:01

2023-04-18 15:18:10

2023-11-07 07:46:02

GatewayKubernetes

2023-11-07 07:08:57

2024-01-30 07:58:41

KubernetesGAMMA網關

2019-08-22 09:55:17

RedisAPI數據

2023-06-26 18:13:56

開源API
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产日韩欧美精品一区二区 | 九九爱这里只有精品 | 羞羞视频网页 | 成人精品一区 | 欧美淫片| 中文字幕一区二区三区四区 | 国产99精品 | 亚洲大片在线观看 | 中文在线a在线 | 亚洲一区视频在线 | 精品1区2区3区4区 | 国精产品一区一区三区免费完 | h网站在线观看 | 日韩欧美在线观看 | 国产精品久久毛片av大全日韩 | 色频| 国产视频一区在线 | 高清久久久 | 国产精品久久久久久久久久 | 一级做a爰片性色毛片视频停止 | 欧美精品第三页 | 色片在线观看 | 一区二区三区久久久 | 国产又色又爽又黄又免费 | 欧美日韩国产中文 | 欧美精品一区二区三区四区 在线 | 日本高清中文字幕 | 国产精品视频网站 | 91精品观看 | 成人毛片视频免费 | 久久久九九 | 视频在线h | av男人的天堂在线 | 国产h视频 | 久久中文字幕一区 | 成人毛片视频免费 | 欧美日韩精品一区二区三区四区 | 亚洲久久久 | 久久久久久国产精品 | 91精品国产一区二区三区香蕉 | 精品9999|