本文章已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kong Ingress Controller 和服務網格:在 Kubernetes 上設定 Ingress 到 Istio

Kubernetes 已成為協調容器和服務中服務的事實標準方式。但是,我們如何讓叢集外部的服務存取叢集內部的服務呢?Kubernetes 提供了 Ingress API 物件,用於管理對叢集內服務的外部存取。

Ingress 是一組規則,用於將入站連線代理到後端定義的端點。然而,如果沒有 Ingress 控制器,Kubernetes 就不知道如何處理 Ingress 資源,而這正是開放原始碼控制器可以發揮作用的地方。在這篇文章中,我們將使用其中一個選項:Kong Ingress Controller。Kong Ingress Controller 在一年前開源,最近下載量達到一百萬次。在最近的 0.7 版本中,也加入了服務網格支援。此版本的其他功能包括

  • 內建 Kubernetes 准入控制器,用於驗證自訂資源定義 (CRD) 在建立或更新時的有效性,並拒絕任何無效的配置。
  • 記憶體內模式 - 每個 Pod 的控制器都會主動配置其 Pod 中的 Kong 容器,這將單個 Kong 容器或控制器容器故障的影響範圍限制在該 Pod 內。
  • 原生 gRPC 路由 - 現在可以使用 Kong Ingress Controller 原生地路由 gRPC 流量,並支援基於方法的路由。

K4K-gRPC

如果您想深入了解 Kong Ingress Controller 0.7,請查看 GitHub 儲存庫

但讓我們回到服務網格支援,因為這將是這篇部落格文章的主要重點。服務網格允許組織通過將服務間通信抽象到網格層來解決與安全性、可靠性和可觀察性相關的微服務挑戰。但是,如果我們的網格層位於 Kubernetes 內部,並且我們仍然需要將某些服務暴露在叢集之外呢?那麼您需要一個 Ingress 控制器,例如 Kong Ingress Controller。在這篇部落格文章中,我們將介紹如何將 Kong Ingress Controller 部署為 Istio 網格的 Ingress 層。讓我們深入了解

Kong Kubernetes Ingress Controller

第 0 部分:在 Kubernetes 上設定 Istio

本部落格文章將假設您已在 Kubernetes 上設定 Istio。如果您需要趕上進度,請查看 Istio 文件。它將引導您在 Kubernetes 上設定 Istio。

1. 安裝 Bookinfo 應用程式

首先,我們需要標記將託管我們的應用程式和 Kong 代理的命名空間。要標記 bookinfo 應用程式所在的預設命名空間,請運行此命令

$ kubectl label namespace default istio-injection=enabled
namespace/default labeled

然後建立一個新的命名空間,用於託管我們的 Kong 閘道和 Ingress 控制器

$ kubectl create namespace kong
namespace/kong created

因為 Kong 將位於預設命名空間之外,請確保您也標記 Kong 命名空間並啟用 istio-injection

$ kubectl label namespace kong istio-injection=enabled
namespace/kong labeled

必須將兩個命名空間都標記為 istio-injection=enabled。否則,預設配置不會將 sidecar 容器注入到您的命名空間的 Pod 中。

現在使用以下命令部署您的 BookInfo 應用程式

$ kubectl apply -f http://bit.ly/bookinfoapp
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created

讓我們仔細檢查我們的服務和 Pod,以確保我們已正確設定所有內容

$ kubectl get services
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.97.125.254    <none>        9080/TCP   29s
kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP    29h
productpage   ClusterIP   10.97.62.68      <none>        9080/TCP   28s
ratings       ClusterIP   10.96.15.180     <none>        9080/TCP   28s
reviews       ClusterIP   10.104.207.136   <none>        9080/TCP   28s

您應該會看到四個新服務:details、productpage、ratings 和 reviews。它們都沒有外部 IP,因此我們將使用 Kong 閘道 來公開必要的服務。要檢查 Pod,請運行以下命令

$ kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-c5b5f496d-9wm29        2/2     Running   0          101s
productpage-v1-7d6cfb7dfd-5mc96   2/2     Running   0          100s
ratings-v1-f745cf57b-hmkwf        2/2     Running   0          101s
reviews-v1-85c474d9b8-kqcpt       2/2     Running   0          101s
reviews-v2-ccffdd984-9jnsj        2/2     Running   0          101s
reviews-v3-98dc67b68-nzw97        2/2     Running   0          101s

此命令輸出有用的資料,因此讓我們花一點時間來理解它。如果您查看 READY 欄,每個 Pod 都有兩個容器在運行:服務和一個與之一起注入的 Envoy sidecar。另一個需要強調的是,有三個 review Pod,但只有 1 個 review 服務。Envoy sidecar 將負載平衡到包含不同版本的三個不同的 review Pod 的流量,讓我們能夠對我們的更改進行 A/B 測試。在我們可以存取已部署的應用程式之前,我們還需要執行一個步驟。我們需要向 productpage 服務新增一個額外的註釋。要做到這一點,請運行

$ kubectl annotate service productpage ingress.kubernetes.io/service-upstream=true
service/productpage annotated

API 閘道 (Kong) 和服務網格 (Istio) 都可以處理負載平衡。如果沒有額外的 ingress.kubernetes.io/service-upstream: "true" 註釋,Kong 將嘗試透過從 productpage 服務中選擇自己的端點/目標來進行負載平衡。這會導致 Envoy 接收該 Pod 的 IP 作為上游本機位址,而不是服務的叢集 IP。但我們希望使用服務的叢集 IP,以便 Envoy 可以正確地進行負載平衡。

新增完成後,您現在應該可以存取您的產品頁面了!

$ kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>

2. 無資料庫的 Kong Kubernetes Ingress Controller

為了將您的服務公開給全世界,我們將部署 Kong 作為南北向流量閘道。Kong 1.1 發布了宣告式配置和無資料庫模式。宣告式配置允許您透過 YAML 或 JSON 檔案而不是一系列 API 呼叫來指定所需的系統狀態。使用宣告式配置提供了幾個主要優勢,可以降低複雜性、提高自動化程度並增強系統效能。透過 Kong Ingress Controller,您應用於叢集的任何 Ingress 規則都將自動在 Kong 代理上配置。讓我們首先像這樣設定 Kong Ingress Controller 和實際的 Kong 代理

$ kubectl apply -f https://bit.ly/k4k8s
namespace/kong configured
customresourcedefinition.apiextensions.k8s.io/kongconsumers.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongcredentials.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongingresses.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongplugins.configuration.konghq.com created
serviceaccount/kong-serviceaccount created
clusterrole.rbac.authorization.k8s.io/kong-ingress-clusterrole created
clusterrolebinding.rbac.authorization.k8s.io/kong-ingress-clusterrole-nisa-binding created
configmap/kong-server-blocks created
service/kong-proxy created
service/kong-validation-webhook created
deployment.apps/ingress-kong created

要檢查 Kong Pod 是否已啟動並運行,請運行

$ kubectl get pods -n kong
NAME                               READY   STATUS    RESTARTS   AGE
pod/ingress-kong-8b44c9856-9s42v   3/3     Running   0          2m26s

這個 Pod 中將有三個容器。第一個容器是 Kong 閘道,它將成為您叢集的 Ingress 點。第二個容器是 Ingress 控制器。它使用 Ingress 資源並更新代理以遵循資源中定義的規則。最後,第三個容器是 Istio 注入的 Envoy 代理。Kong 將透過 Envoy sidecar 代理將流量路由到適當的服務。要透過我們新部署的 Kong 閘道將請求發送到叢集中,請設定一個環境變數,其 URL 基於 Kong 可存取的 IP 位址。

$ export PROXY_URL="$(minikube service -n kong kong-proxy --url | head -1)"
$ echo $PROXY_URL
http://192.168.99.100:32728

接下來,我們需要更改一些配置,以便 sidecar Envoy 進程可以根據請求的 host/authority 標頭正確路由請求。運行以下命令以停止路由保留主機

$ echo "
apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:
    name: do-not-preserve-host
route:
  preserve_host: false
upstream:
  host_header: productpage.default.svc
" | kubectl apply -f -
kongingress.configuration.konghq.com/do-not-preserve-host created

並註釋現有的 productpage 服務,以將 service-upstream 設定為 true

$ kubectl annotate svc productpage Ingress.kubernetes.io/service-upstream="true"
service/productpage annotated

現在我們已經設定好一切,我們可以看看如何使用 Ingress 資源來幫助將外部流量路由到 Istio 網格中的服務。我們將建立一個 Ingress 規則,將路徑為 / 的所有流量路由到我們的 productpage 服務

$ echo "
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: productpage
  annotations:
    configuration.konghq.com: do-not-preserve-host
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: productpage
          servicePort: 9080
" | kubectl apply -f -
ingress.extensions/productpage created

就這樣,Kong Ingress Controller 能夠理解您在 Ingress 資源中定義的規則,並將其路由到 productpage 服務!要查看產品頁面服務的 GUI,請在瀏覽器中前往 $PROXY_URL/productpage。或者要在命令列中測試它,請嘗試

$ curl $PROXY_URL/productpage

這就是我這次逐步說明的全部內容。如果您喜歡這篇文章中使用的技術,請查看它們的儲存庫,因為它們都是開放原始碼,並且很樂意有更多貢獻者!為了您的方便,這裡提供它們的連結

感謝您的關注!