通過 Istio 重新實現微服務 (三):使用 Istio 代理執行應用
情感分析應用的架構
我們將會繼續使用 Kubernetes 入門文章 中的樣例,它較為複雜,足以通過實踐展示 Istio 的特性。
這個應用由四個微服務組成:
- SA-Frontend 服務:前端的 Reactjs 應用;
- SA-WebApp 服務:處理情感分析的請求;
- SA-Logic 服務:執行情感分析;
- SA-Feedback 服務:接收使用者關於分析精確性的反饋。
在圖 6 中,除了服務之外,我們還看到了 Ingress Controller,在 Kubernetes 中,它會將傳入的請求路由至對應的服務,Istio 採用了類似的概念,名為 Ingress Gateway,在本文後續的內容中,我們將會對其進行介紹。
使用 Istio 代理執行應用
如果要要跟著本文一起練習的話,讀者可以 clone 該 GitHub 倉庫 istio-mastery ,其中包含了適用於 Kubernetes 和 Istio 的應用程式與 manifest。
Sidecar 注入
注入可以 自動 或 手動 完成。如果要啟用自動化的 Sidecar 注入,我們需要使用 istio-injection=enabled
來標記名稱空間,這可以通過執行如下的命令來實現:
複製程式碼
$ kubectl label namespacedefaultistio-injection=enabled namespace/defaultlabeled
現在,預設名稱空間中部署的所有 pod 都將會被注入 sidecar。切換至 [istio-mastery]
倉庫的根目錄,並執行如下的命令:
複製程式碼
$ kubectl apply -f resource-manifests/kube persistentvolumeclaim/sqlite-pvc created deployment.extensions/sa-feedback created service/sa-feedback created deployment.extensions/sa-frontend created service/sa-frontend created deployment.extensions/sa-logic created service/sa-logic created deployment.extensions/sa-web-appcreated service/sa-web-appcreated
執行如下的命令並檢查 Ready 列,我們會看到“2/2”,這表明第二個容器已經注入進來了。
複製程式碼
$ kubectlgetpods NAME READY STATUS RESTARTS AGE sa-feedback-55f5dc4d9c-c9wfv2/2Running012m sa-frontend-558f8986-hhkj92/2Running012m sa-logic-568498cb4d-s9ngt2/2Running012m sa-web-app-599cf47c7c-s7cvd2/2Running012m
服務已經啟動並運行了,每個容器都包含了 sidecar 代理,如圖 7 所示。
但是,要訪問服務,我們需要允許傳入的流量進入叢集,也就是所謂的 Ingress 流量。
Ingress 閘道器
允許流量進入叢集的一個最佳實踐就是使用 Istio 的 Ingress 閘道器,它處於叢集的邊緣並且靠近傳入的流量,它能夠實現 Istio 的多項特性,比如路由、安全和監控。
在 Istio 安裝的時候,Ingress 閘道器元件以及將其暴露給外部的服務已經安裝到了叢集中,我們可以通過如下的命令獲取它的外部 IP:
複製程式碼
$ kubectlgetsvc -n istio-system -listio=ingressgateway NAMETYPECLUSTER-IP EXTERNAL-IP PORT(S) istio-ingressgateway LoadBalancer 10.0.132.127 13.93.30.120 80:31380/TCP,443[...]
在本文後續的內容中,我們將會通過該 IP(將其稱為 EXTERNAL-IP
)訪問應用程式,為了便利起見,我們通過下面的命令將其儲存到變數中:
複製程式碼
$EXTERNAL_IP=$(kubectlgetsvc -n istio-system \ -lapp=istio-ingressgateway \ -ojsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
如果你在瀏覽器中訪問該 IP 的話,將會看到服務不可用的錯誤,預設情況下,在我們定義閘道器之前,Istio 會阻止所有傳入的流量。
閘道器資源
閘道器是一種 Kubernetes 自定義資源定義(Kubernetes Custom Resource Definition),它是我們在叢集中安裝 Istio 時所定義的,藉助它,我們能夠指定允許傳入流量的埠、協議和主機。
在我們的場景中,我們想要為所有主機開放 80 埠。我們可以通過如下的定義來進行配置:
複製程式碼
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: http-gateway spec: selector: istio: ingressgateway servers: -port: number:80 name: http protocol: HTTP hosts: -"*"
除了 istio: ingressgateway
選擇器之外,所有配置項的含義均不言自明。通過使用這個選擇器,我們可以指定哪個 Ingress 閘道器使用該配置,在我們的場景中,也就是在 Istio 安裝時的預設 Ingress 閘道器控制器。
通過執行如下的命令,應用該配置:
複製程式碼
$ kubectl apply -f resource-manifests/istio/http-gateway.yaml gateway.networking.istio.io"http-gateway"created
閘道器允許我們訪問 80 埠,但是它還不知道要將請求路由至何處,而這一功能是通過 Virtual Service 來實現的。
VirtualService 資源
VirtualService 能夠指導 Ingress 閘道器如何路由允許進入叢集的請求。
對於我們的應用來說,通過 http-gateway 的請求必須要路由至 sa-frontend 、 sa-web-app 和 sa-feedback 服務(如圖 8 所示)。
現在,我們拆分一下應該路由至 SA-Frontend 的請求:
/ /static/* ^.*\.(ico|png|jpg)$
這樣,我們就會得到如下的配置:
複製程式碼
kind: VirtualService metadata: name: sa-external-services spec: hosts: -"*" gateways: - http-gateway #1 http: -match: -uri: exact: / -uri: exact: /callback -uri: prefix: /static -uri: regex:'^.*\.(ico|png|jpg)$' route: -destination: host: sa-frontend #2 port: number:80
這裡的重點在於:
- VirtualService 將會應用於通過 http-gateway 的請求;
- destination 定義了請求要路由至哪個服務。
注意:上面的配置在 sa-virtualservice-external.yaml
檔案中,它還包含了路由至 SA-WebApp 和 SA-Feedback 的配置,但是簡潔期間,我們將其省略了。
通過執行如下的命令,應用 VirtualService:
複製程式碼
$ kubectl apply -f resource-manifests/istio/sa-virtualservice-external.yaml virtualservice.networking.istio.io"sa-external-services"created
注意:當我們應用該資源時(其實所有的 Istio 資源均如此),Kubernetes API Server 會建立一個新的事件,該事件會被 Istio 的控制平面接收到,然後會將新的配置應用到每個 pod 的 envoy 代理上。Ingress Gateway 控制器是 Control Plane 配置的另外一個 Envoy,如圖 9 所示。
現在,我們可以通過 http://{{EXTERNAL-IP}}/
訪問情感分析應用了。如果你遇到 Not Found 狀態的話,請不要擔心,有時候配置生效並更新 envoy 快取會耗費一點時間。
在轉入下一部分之前,你需要使用該應用生成一些流量。
系列回顧