基於阿里雲 ASK 的 Istio 微服務應用部署初探

asjkghas發表於2022-06-10

作者:王飛龍(不物)

目前 Kubernetes 已經成為業界容器編排系統的事實標準,基於 Kubernetes 的雲原生應用生態(Helm, Istio, Knative, Kubeflow, Spark on Kubernetes 等)更是讓 Kubernetes 成為雲作業系統。在這樣的背景下,Serverless 容器成為現有 Container as a Service 的進化方向之一,一方面通過 Serverless 方式根本性解決了 Kubernetes 自身的管理複雜性,讓使用者無需受困於 Kubernetes 叢集容量規劃、安全維護、故障診斷;另一方面也進一步釋放了雲端計算的能力,將安全、可用性、可伸縮性等需求由基礎設施實現。

ASK 作為阿里雲 Serverless Kubernetes 平臺 [ 1] ,不僅有免運維、秒級彈性、超大 Pod 容量、彈性預測等重磅能力,更重要的是它依然是一個標準 Kubernetes 平臺。

本文會通過在 ASK 上試用 Istio 部署微服務應用的方式,來驗證 ASK 對標準 Kubernetes 的相容性。Istio 作為 Service Mesh(服務網格)的領導解決方案,一方面本身足夠複雜具有代表性,另一方面它也代表了雲原生時代微服務架構的趨勢具有參考意義。

現在就讓我們開始吧!

建立叢集

試用 Istio 前,需要準備一個 ASK 叢集。登入阿里雲控制檯,選擇產品與服務 > 容器服務 Kubernetes 版,在左側邊欄選擇叢集進入叢集列表頁面。點選右上角建立叢集開始建立叢集,配置叢集引數如下:

  • 叢集名稱:hello-istio
  • 叢集規格:Pro 版
  • 地域:美國(矽谷)
  • 付費型別:按量付費
  • Kubernetes 版本:1.20.11-aliyun.1
  • 專有網路:自動建立
  • Service CIDR:172.21.0.0/20
  • API Server 訪問:標準型I(slb.s2.small)
  • 使用 EIP 暴露 API Server:是
  • 時區:Aisa/Shanghai(UTC+08:00)
  • 服務發現:CoreDNS
  • 使用日誌服務:建立新 Project

確認配置後點選建立叢集進入等待叢集建立完成。Istio 依賴 DNS 服務,這裡選擇建立叢集時預設安裝 CoreDNS 元件。

 title=

叢集建立完成後,進入叢集列表 > hello-istio > 詳情 > 叢集資訊 > 連線資訊頁面,複製公網訪問內容到本地/tmp/kube/config 檔案,並通過如下命令配置好 kubelet:

$ export KUBECONFIG=/tmp/kube/config

試用 Istio

kubectl 配置好後就可以開始在叢集安裝和試用 Istio。

下載 Istio

進入 Istio 釋出頁面 [ 2] 下載針對作業系統的安裝檔案,也可以通過如下命令下載並提取最新版本:

$ curl -L https://istio.io/downloadIstio | sh -

因為我本機~/bin 目錄已加入 PATH,這裡我將提取的 Istio 目錄複製~/bin 目錄,並建好軟連結。

$ cp istio-1.13.3 ~/bin
$ cd ~/bin
$ ln -s istio-1.13.3/bin/istioctl
$ ls -al ~/bin/
total 28
drwxr-xr-x   5 feilong.wfl staff   160  5  4 22:40 ./
drwxr-xr-x+ 95 feilong.wfl staff  3040  5  8 22:30 ../
drwxr-x---   9 feilong.wfl staff   288  4 15 00:48 istio-1.13.3/
lrwxr-xr-x   1 feilong.wfl staff    25  5  4 22:40 istioctl -> istio-1.13.3/bin/istioctl*

如果 istioctl --help 命令輸出正常,則 istioctl 已正確配置。

安裝 Istio

  1. 本次安裝採用 demo profile [ 3] ,它包含了一組專為測試準備的功能集合,另外還有使用者生產或效能測試的配置組合。
$ istioctl install --set profile=demo -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete
  1. 給名稱空間新增標籤,指示 Istio 在部署應用的時候,自動注入 Envoy 邊車代理:
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled

部署示例應用

  1. 部署 Bookinfo 示例應用 [ 4]
$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/platform/kube/bookinfo.yaml
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
  1. 檢查 Pod 已就緒:
$ kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-79f774bdb9-t2jhq       2/2     Running   0          2m54s
productpage-v1-6b746f74dc-qc9lg   2/2     Running   0          2m46s
ratings-v1-b6994bb9-tmbh6         2/2     Running   0          2m51s
reviews-v1-545db77b95-xdhp4       2/2     Running   0          2m49s
reviews-v2-7bf8c9648f-4gn6f       2/2     Running   0          2m48s
reviews-v3-84779c7bbc-jfndj       2/2     Running   0          2m48s
要等待並確保所有的 Pod 達到此狀態:就緒狀態(READY)的值為 2/2 、狀態(STATUS)的值為 Running。基於平臺的不同,這個操作過程可能會花費幾分鐘的時間。
  1. 檢查 Service 已就緒:
$ kubectl get services
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   172.21.11.168   <none>        9080/TCP   59s
kubernetes    ClusterIP   172.21.0.1      <none>        443/TCP    33m
productpage   ClusterIP   172.21.0.124    <none>        9080/TCP   51s
ratings       ClusterIP   172.21.9.7      <none>        9080/TCP   57s
reviews       ClusterIP   172.21.13.223   <none>        9080/TCP   55s
  1. 確保網頁服務正常。如果命令返回頁面標題,則應用已在叢集中執行。
$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>

對外開放服務

現在,BookInfo 應用已經部署,但還不能被外界訪問。 要開放訪問,需要建立 Istio 入站閘道器(Ingress Gateway), 它會把一個路徑路由到網格內的服務。

  1. 把應用關聯到 Istio 閘道器:
$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
  1. 確保配置檔案沒有問題:
$ istioctl analyze
✔ No validation issues found when analyzing namespace: default.

確定入站 IP 和埠

使用如下命令為訪問閘道器設定 INGRESS_HOST 和 INGRESS_PORT 兩個變數:

$ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
$ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')

設定變數 GATEWAY_URL,並確保 IP 地址和埠均成功的賦值給了該變數:

$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
$ echo "$GATEWAY_URL"
47.88.21.82:80

驗證外部訪問

執行下面命令,獲取 Bookinfo 應用的外部訪問地址:

$ echo "http://$GATEWAY_URL/productpage"
http://47.88.21.82:80/productpage

複製上面命令的輸出地址到瀏覽器並訪問,確認 Bookinfo 已經實現了外部訪問。重新整理頁面,發現 Book Reviews 的顯示樣式會不斷變化。

 title=

檢視儀表盤

儀表盤能幫助瞭解服務網格的結構、展示網路的拓撲結構、分析網格的健康狀態。

  1. 首先安裝 Kiali 和其他外掛,等待部署完成。
$ kubectl apply -f ~/bin/istio-1.13.3/samples/addons
$ kubectl rollout status deployment/kiali -n istio-system
Waiting for deployment "kiali" rollout to finish: 0 of 1 updated replicas are available...
deployment "kiali" successfully rolled out
  1. 訪問 Kiali 儀表板。
$ istioctl dashboard kiali
  1. 在左側的導航選單,選擇 Graph,然後在 Namespace 下拉選單中,選擇 default

Kiali 儀表板展示了網格的概覽、以及 Bookinfo 示例應用的各個服務之間的關係。 它還提供過濾器來視覺化流量的流動。

 title=

新增預設目標規則

使用 Istio 控制 Bookinfo 版本路由前,需要先在目標規則 [ 5] 中定義好可用的版本。執行以下命令為 Bookinfo 服務建立預設的目標規則:

$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/destination-rule-all.yaml
destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created

等待幾秒鐘,目標規則生效。您可以使用如下命令檢視目標規則:

$ kubectl get destinationrules
NAME          HOST          AGE
details       details       30s
productpage   productpage   32s
ratings       ratings       31s
reviews       reviews       32s

路由所有流量到 v1 版本

執行以下命令建立 Virtual Service 將所有流量路由到微服務的 v1 版本:

$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created
virtualservice.networking.istio.io/ratings created
virtualservice.networking.istio.io/details created

您可以通過再次重新整理 Bookinfo 應用程式的/productpage 頁面測試新配置。請注意,無論您重新整理多少次,頁面的評論部分都不會顯示評級星標。這是因為當前已將 Istio 配置為評論服務的所有流量路由到版本 reviews:v1,而此版本的服務不訪問星級評分服務。

基於使用者身份的路由

接下來將更改路由配置,實現將來自特定使用者的所有流量路由到特定的服務版本。示例中來自名為 Jason 使用者的所有流量將被路由到服務 review:v2。

Istio 對使用者身份沒有任何特殊的內建機制。本例中,productpage 服務在所有到 reviews 服務的 HTTP 請求中都增加了一個自定義的 end-user 請求頭,從而達到效果。
  1. 執行以下命令以啟用基於使用者的路由:
$ kubectl apply -f ~/bin/istio-1.13.3/samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
virtualservice.networking.istio.io/reviews created
  1. 確保規則已建立:
$ kubectl get virtualservice reviews -o yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"reviews","namespace":"default"},"spec":{"hosts":["reviews"],"http":[{"match":[{"headers":{"end-user":{"exact":"jason"}}}],"route":[{"destination":{"host":"reviews","subset":"v2"}}]},{"route":[{"destination":{"host":"reviews","subset":"v1"}}]}]}}
  creationTimestamp: "2022-05-15T16:05:55Z"
  generation: 1
  name: reviews
  namespace: default
  resourceVersion: "1984849"
  uid: f3bd3dcb-d83c-4a75-9511-1fc9308ca05b
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1
  1. 在 Bookinfo 應用程式的/productpage 上,以使用者 jason 身份登入。重新整理瀏覽器,看到每個評論旁邊顯示星級評分。

 title=

  1. 以其他使用者身份登入,重新整理瀏覽器。發現星級評分消失了。

原理和限制

資料平面,Istio 通過向 Pod 注入的 Sidecar 代理(istio-proxy)來負責協調和控制微服務之前的所有網路通訊。為了讓 Sidecar 代理(istio-proxy)劫持業務容器流量,Istio 需要向 Pod 所在網路下發 iptables 規則。常規安裝模式下,iptables 規則下發是由 Istio 向 Pod 注入的初始化容器 istio-init 完成。向 Pod 網路下發 iptables 規則需要容器可以使用 NET_ADMIN 和 NET_RAW 兩個高許可權的能力(Capabilities)。ASK 叢集中這兩個高許可權能力受 ASK Pod Security Policy [ 6] 和 ECI Container Security Policy [ 7] 的影響。

ASK Pod Security Policy 的 CAPS 為 *,表示沒有限制。

$ kubectl get psp
NAME             PRIV   CAPS   SELINUX    RUNASUSER   FSGROUP    SUPGROUP   READONLYROOTFS   VOLUMES
ack.privileged   true   *      RunAsAny   RunAsAny    RunAsAny   RunAsAny   false            *

ECI Container Security Policy 允許通過容器安全上下文配置即可。Istio 中 Pod 注入模板檔案~/bin/istio-1.13.3/manifests/charts/istio-control/istio-discovery/files/injection-template.yaml 包含如下程式碼:不啟用 Istio CNI 外掛 [ 8] 將新增 NET_ADMIN 和 NET_RAW 兩個高許可權能力:

securityContext:
  allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }}
  privileged: {{ .Values.global.proxy.privileged }}
  capabilities:
{{- if not .Values.istio_cni.enabled }}
    add:
    - NET_ADMIN
    - NET_RAW
{{- end }}
    drop:
    - ALL

所以從原理上分析當前 ASK 叢集使用 Istio 沒有相容性問題。

總結

本次在 ASK 上試用 Istio 這類高複雜度的軟體,未發現相容性問題。又從原理上正面分析論證了產生相容性問題的可能性較低。因此,ASK 對原生 Kubernetes 還是有著極好的相容性。後續將在 ASK 叢集上深入探索 Istio 其他功能,以進一步驗證 ASK 對原生 Kubernetes 的相容性。

參考連結:

[1] 阿里雲 Serverless Kubernetes

https://help.aliyun.com/docum...

[2] Istio 釋出頁面

https://github.com/istio/isti...

[3] demo profile**

https://istio.io/latest/docs/...

[4] Bookinfo 示例應用

https://istio.io/latest/zh/do...

[5] 目標規則

https://istio.io/latest/docs/concepts/traffic-management/#destination-rules)中定義好可用的版本中定義好可用的版本)

[6] ASK Pod Security Policy

https://help.aliyun.com/docum...

[7] ECI Container Security Policy

https://help.aliyun.com/docum...

[8] Istio CNI 外掛

https://istio.io/latest/docs/...

點選此處,瞭解阿里雲 ASK 更多詳情和最佳實踐

相關文章