在 Istio 服務網格中使用 Traefik Ingress Controller

作者:Petr McAllister,Petr 是一名 IT 專業人士,擁有 20 多年的國際經驗和計算機科學碩士學位。他是 Tetrate 的技術專家。

Istio 服務網格自帶 ingress,但我們經常看到有要求使用非 Istio ingress 的客戶。此前,我們已經介紹過將 NGINX 與 Istio 集成的情況。最近,我們一直在與使用 Traefik ingress 的客戶合作。通過對我們之前建議的方法進行一些輕微調整,我將向你介紹如何實現 Traefik 作爲 Istio 服務網格的入口網關。

流量的流向如下圖所示。一旦請求從 Traefik Ingress 到達服務網格,Istio 就能夠對請求應用安全性、可觀察性和流量引導規則。

傳入的流量繞過 Istio sidecar,直接到達 Traefik,所以請求終止在 Traefik ingress。

Traefik 使用 IngressRoute 配置重寫 Host 頭以匹配目的地,並將請求轉發到目標服務,這是一個多步驟的過程。

• 從 Traefik Ingress 出來的請求被重定向到 Istio sidecar(由 iptables)。•Sidecar 接收請求,對其進行加密(因爲我們的 Istio PeerAuthentication 策略要求使用 STRICT mTLS),然後將請求轉發到目標服務的 pod。

下面是一個端到端的部署示例,使用 Istio 的 bookinfo 演示應用,但用 Traefik ingress 來支撐整個部署。簡而言之,要想在自己的環境中實現這個功能。

• 用 Istio sidecar 部署 Traefik 控制器,註釋部署,使入站流量繞過 Istio Sidecar:

# Exclude the ports that Traefik receives traffic on
traffic.sidecar.istio.io/excludeInboundPorts: “80” 
# Make sure Traefik controller can talk to the Kubernetes API server 
traffic.sidecar.istio.io/excludeOutboundIPRanges: X.X.X.X/32

• 在應用程序命名空間中啓用 Istio sidecar 注入,並部署任何你需要的 Istio 特定配置。• 用 Traefik Middleware 對象創建 IngressRoute,將主機名改寫爲網格識別的主機名(即集羣中的服務;下文將通過一個例子詳細討論)。

使用 Traefik Ingress 的 Bookinfo

這篇文章的其餘部分涵蓋了部署 Istio 的 Bookinfo 示例應用程序,使用 Traefik 作爲部署的 Ingress 代理。

設置環境

參考以下步驟。

部署一個至少 1.17 版本的 Kuberentes 集羣(最小支持 Istio 1.8 版本)。我們使用 Google Kubernetes Engine 創建的集羣。

gcloud container clusters create istio-traefik \
  --cluster-version=1.17 \
  --region <GCP region> \
  --machine-type=e2-standard-4 \
  --project <GCP Project> \
  --num-nodes 1 \
  --node-locations <GCP Zone> # i.e us-west2-b (otherwise 1 node per zone)

下載 Istio 1.8

curl -sL https://git.io/getLatestIstio |\
ISTIO_VERSION=1.8.1 sh -

在啓用 HTTP 訪問日誌的情況下進行安裝。

./istio-1.8.1/bin/istioctl install \
  --set meshConfig.accessLogFile=/dev/stdout \
  --skip-confirmation

部署 Bookinfo 應用

安裝好 Istio 後,我們就可以開始部署我們的應用程序了。我們將使用 Istio 的 Bookinfo 應用程序進行演示。這個示例應用程序是 Istio 發行版的一部分(在./istio-1.8.1/samples/ 文件夾中)。

創建 bookinfo namespace。

kubectl create ns bookinfo

設置 label,讓 sidecar 自動注入。

kubectl label namespace bookinfo istio-injection=enabled

在該 namespace 中部署 bookinfo 應用程序。

kubectl apply -f istio-1.8.1/samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo

確認所有的吊艙都已啓動,並部署了側車。

啓用 Istio mTLS 爲應用程序命名空間的服務到服務通信。

cat <<EOF | kubectl apply -f - 
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: bookinfo
spec:
  mtls:
    mode: STRICT
EOF

部署 Traefik 入口

現在是時候按照 v2.3 文檔來部署 Traefik 了(本篇文章中 Traefik 的最新版本是 2.3,但如果你根據你的版本調整了 IngressRoute 和 Middleware 資源,它將適用於任何版本的 Traefik)。

部署 Traefik。請注意,Traefik 網站上的文檔部署有一些修改(代替 Traefik 文檔中的默認命名空間,將指定 bookinfo 命名空間)。該文件可以在這裏訪問並應用如下。

$ kubectl apply -f http://bit.ly/Traefik-CRDs-and-Roles
customresourcedefinition.apiextensions.k8s.io/ingressroutes.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/middlewares.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/ingressroutetcps.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/ingressrouteudps.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/tlsoptions.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/tlsstores.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/traefikservices.traefik.containo.us created
clusterrole.rbac.authorization.k8s.io/traefik-ingress-lb created
clusterrolebinding.rbac.authorization.k8s.io/traefik-ingress-lb created

爲傳入的請求創建一個服務。該服務將接收外部 IP 地址。(Traefik 網站上的例子有一些變化)。

• 需要指定 Namespace。• 只發布兩個端口:80 用於 Bookinfo 應用,8080 用於 Traefik 管理。• 服務需要使用的標籤(traefik-ingress-lb)指向 Traefik。•Type: Loadbalancer 是爲了告訴 GCP 給服務分配一個外部 IP。

cat <<EOF | kubectl apply -f - 
apiVersion: v1
kind: Service
metadata:
  name: traefik
  namespace: bookinfo
spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
    - protocol: TCP
      name: admin
      port: 8080
  selector:
    app: traefik-ingress-lb
  type: LoadBalancer
EOF

確認服務的創建符合預期。

$ kubectl get svc traefik -n bookinfo
NAME      TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                       AGE
traefik   LoadBalancer   10.35.244.227   35.236.XXX.XXX   80:31718/TCP,8080:31334/TCP   2m6s

正如 Traefik 網站中介紹的,需要應用 ServiceAccount 的 Kubernetes 部署。除了名稱和命名空間,網站示例還引入了以下變化。

• 爲了簡單起見,刪除了安全端點。•Accesslog:增加了 =true,因爲沒有這個值就不行。•Log.level 設置爲 DEBUG 將幫助我們看到發生了什麼。• 增加了 traffic.sidecar.istio.io 註釋(更多細節請參考之前提到的 Tetrate NGINX 文章)。

KUBERNETES_SVC_IP=$( kubectl get svc kubernetes -n default -o jsonpath='{.spec.clusterIP}' )
cat <<EOF | kubectl apply -f - 
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: bookinfo
  name: traefik-ingress-lb
---
kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: bookinfo
  name: traefik-ingress-lb
  labels:
    app: traefik-ingress-lb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: traefik-ingress-lb
  template:
    metadata:
      labels:
        app: traefik-ingress-lb
      annotations:
        traffic.sidecar.istio.io/excludeInboundPorts: "80"
        traffic.sidecar.istio.io/excludeOutboundIPRanges: ${KUBERNETES_SVC_IP}/32
    spec:
      serviceAccountName: traefik-ingress-lb
      containers:
        - name: traefik-ingress-lb
          image: traefik:v2.3
          args:
            - --api.insecure
            - --accesslog=true
            - --providers.kubernetescrd
            - --entrypoints.web.address=:80
            - --log.level=DEBUG
          ports:
            - name: web
              containerPort: 80
            - name: admin
              containerPort: 8080
EOF

確認 Traefik 在 Bookinfo 命名空間的部署。

$  kubectl get pods -n bookinfo -l app=traefik-ingress-lb
NAME                                  READY   STATUS    RESTARTS   AGE
traefik-ingress-lb-669fc4b77d-74mpx   2/2     Running   0          2m35s

獲取服務 IP 並記錄 BOOKINFO_IP 變量值。

BOOKINFO_IP=$(kubectl -n bookinfo get service traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

測試來自 Ingress 80 端口的響應,看看它是否有通往應用的路由。

curl -I $BOOKINFO_IP

確保它返回 “404 Not Found”—— 由於尚未實施 Ingress 規則,所以預計會有 not-200 響應。

配置 Traefik Ingress 規則

Traefik 的 Middleware 頭重寫功能將使 Istio 服務網格正常運行。本例中,需要將主機定義爲 productpage.bookinfo.svc。頭可以根據 Traefik 文檔來定義。

cat <<EOF | kubectl apply -f - 
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: productpage-header
  namespace: bookinfo
spec:
  headers:
    customRequestHeaders:
      Host: productpage.bookinfo.svc
EOF

最後一步是指定 ingress 請求的路由邏輯,因爲本文的重點是服務網格集成。這個定義非常簡單,將所有到達 80 端口的入站請求轉發到名爲 ProductPage 的前沿 bookinfo 應用服務(服務於 9080 端口的流量)。它還使用了上一步創建的中間件對象。

cat <<EOF | kubectl apply -f - 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: productpage
  namespace: bookinfo
spec:
  entryPoints:
    - web
  routes:
  - match: PathPrefix(`/`)
    kind: Rule
    middlewares:
    - name: productpage-header
    services:
    - name: productpage
      port: 9080
EOF

驗證部署功能

重新測試應用程序的響應。

curl -I $BOOKINFO_IP

我們會收到 “200 OK “的回覆。也可以通過瀏覽器測試,使用 http://<BOOKINFO_IP>/productpage

如果在 http://<BOOKINFO_IP>/productpage,就會返回應用響應。

通過查詢 istio-proxy 容器的 bookinfo 命名空間中的 Traefik pod 日誌,可以在 istio-proxy 日誌中看到嚮應用程序發出的請求。沒有傳入請求,因爲它們直接到達 Traefik Ingress。

TRAEFIK_POD=$( kubectl -n bookinfo get pods -l app=traefik-ingress-lb -o jsonpath='{.items[0].metadata.name}' )
kubectl -n bookinfo logs ${TRAEFIK_POD} -c istio-proxy

請注意,請求處理後,日誌需要幾秒鐘才能顯示。只有在 Istio 安裝時使用 meshConfig.accessLogFile=/dev/stdout 標誌的情況下,纔會顯示日誌。

[2021-01-05T20:13:55.015Z] "GET /productpage HTTP/1.1" 200 - "-" 0 5179 1069 1069 "10.32.0.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" "4bd443e9-1a2e-4d30-b1e3-398a5005f240" "productpage.bookinfo.svc" "10.32.0.18:9080" outbound|9080||productpage.bookinfo.svc.cluster.local 10.32.0.19:51810 10.32.0.18:9080 10.32.0.1:0 - default
[2021-01-05T20:13:56.301Z] "GET /static/bootstrap/fonts/glyphicons-halflings-regular.woff2 HTTP/1.1" 200 - "-" 0 18028 3 3 "10.32.0.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" "8cb44552-c3c8-45dd-8674-4af207ce1648" "productpage.bookinfo.svc" "10.32.0.18:9080" outbound|9080||productpage.bookinfo.svc.cluster.local 10.32.0.19:51810 10.32.0.18:9080 10.32.0.1:0 - default

總結

本文演示瞭如何將 Traefik Ingress 作爲 Istio 服務網格的入口點。這裏應用的基本方法應該是適用的,即使你的環境與我們例子中使用的環境不同。當引入服務網格時,Traefik / 服務網格集成可以在不同的雲中成功實施,並使用全新或現有(也就是棕地)部署 Traefik。最終,您將獲得兩者最好的東西:Istio 服務網格與您所選擇的 Ingress 控制器相集成!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/hNH-9JGK_Sa15a8xeClaPw