使用Istio打造微服務(第1部分)

做者:Rinor Maloku 
譯者:殷龍飛 
審校:孫海洲 
原文:https://medium.com/google-cloud/back-to-microservices-with-istio-p1-827c872daa53


Istio 是一個由Google,IBM和Lyft團隊合做開發的開源項目,它提供了基於微服務的應用程序複雜性的解決方案,僅舉幾例:css

  • 流量管理 :超時,重試,負載均衡,html

  • 安全性: 最終用戶身份驗證和受權,前端

  • 可觀察性: 跟蹤,監控和記錄。git

全部這些均可以在應用程序層中解決,可是您的服務再也不是「微型」,相對於提供業務價值的資源,實現這些的全部額外工做都是公司資源的壓力。咱們來舉個例子:github

PM:添加反饋功能須要多長時間?web

開發:兩個衝刺(敏捷開發中的術語,通常一個衝刺週期30天)。正則表達式

PM:什麼......? 那只是一個CRUD!算法

開發:建立CRUD很容易,但咱們須要對用戶和服務進行身份驗證和受權。並且因爲網絡不可靠,咱們須要在客戶端實施重試和熔斷器,並確保咱們不會佔用整個系統,咱們須要Timeout和Bulkheads,另外還要檢測咱們須要監控的問題,跟蹤[... ]sql

PM:那麼咱們就把它放在產品服務中吧。哎呀!chrome

你明白了,必須知足全部形式才能夠爲咱們添加一項巨大的服務(有不少不是業務功能的代碼)。在本文中,咱們將展現Istio如何從咱們的服務中刪除全部上述交叉問題。

注意: 本文假設您具備Kubernetes的知識。若是不是這種狀況,我建議您閱讀 我對Kubernetes的介紹,而後繼續閱讀本文。

關於Istio

在沒有Istio的世界中,一個服務向另外一個服務直接發出請求,而且在發生故障的狀況下,服務須要經過重試,超時,打開熔斷器等來處理它。

爲了解決這個問題,Istio經過與服務徹底分離,並經過攔截全部網絡通訊來提供一種巧妙的解決方案。這樣作能夠實現:

  • Fault Tolerance  - 使用響應狀態代碼,它能夠在請求失敗並重試時理解。

  • Canary Rollouts  - 僅將指定百分比的請求轉發到新版本的服務。

  • 監控和指標  - 服務響應所花費的時間。

  • 跟蹤和可觀察性  - 它在每一個請求中添加特殊header,並在集羣中跟蹤它們。

  • 安全性  - 提取JWT令牌並對用戶進行身份驗證和受權。

僅舉幾例(僅舉幾例),讓您感興趣! 咱們來看一些技術細節吧!

Istio的架構

Istio攔截全部網絡流量,並經過在每一個pod中注入智能代理做爲sidecar來應用一組規則。啓用全部功能的代理包括 數據平面, 而且這些代理可由控制平面 動態配置。

數據平面

注入的代理使Istio可以輕鬆知足咱們的要求。舉個例子,咱們來看看重試和熔斷器功能。

總結一下:

  1. Envoy將請求發送到服務B的第一個實例,但它失敗了。

  2. Envoy sidecar重試。(1)

  3. 返回對調用代理的失敗請求。

  4. 這將打開熔斷器並在後續請求中調用下一個服務。(2)

這意味着您沒必要使用另外一個重試庫,您沒必要在編程語言X,Y或Z中開發本身的Circuit Breaking和Service Discovery實現。全部這些都是開箱即用的。這些功能都是經過Istio來實現,你不須要更改代碼。

很好! 如今你想加入Istio的航行,但你仍然有一些疑慮,一些懸而未決的問題。這是一個一刀切的方案,你對它持懷疑態度,由於它老是最終成爲一刀切的無解方案!

你最終低聲說了這個問題:「這是可配置的嗎?」

歡迎個人朋友來巡航,咱們將爲你們介紹一下控制平面。

控制平面

由三個組件組成: PilotMixerCitadel,它們組合使用Envoys來路由流量,實施策略和收集遙測數據。以下圖所示。

Envoy(即數據平面)使用由Istio定義的 Kubernetes自定義資源定義 進行配置。這意味着對你而言,它只是另外一個具備熟悉語法的Kubernetes資源。建立後將由控制平面獲取,並將其應用於Envoy。

服務與Istio的關係

咱們描述了Istio與咱們服務的關係,但咱們反過來思考一下,咱們的服務與Istio的關係是什麼?

坦率地說,咱們的服務對Istio的存在有着儘量多的瞭解,就像魚對水同樣,他們會問本身「這究竟是什麼水?」。

這意味着您能夠選擇一個工做集羣,在部署了Istio的組件後,其中的服務將繼續工做,而且以相同的方式,您能夠刪除組件,一切都會很好。能夠理解的是,您將失去Istio提供的功能。

咱們已經有足夠的理論,下面讓咱們把這些理論付諸實踐!

Istio實踐

Istio至少須要一個具備4個vCPU和8 GB RAM的Kubernetes集羣。要快速設置集羣並跟進本文,我建議使用Google雲端平臺,它爲新用戶提供 300美圓的免費試用版

使用Kubernetes命令行工具建立集羣並配置訪問後,咱們已準備好使用Helm Package管理器安裝Istio。

安裝Helm

按照官方文檔中的說明在您的計算機上安裝Helm客戶端 。咱們將在下一節中使用它來生成Istio安裝模板。

安裝Istio

最新版本下載Istio的資源,將內容提取到一個咱們將稱之爲的目錄中[istio-resources]

要輕鬆識別Istio資源 istio-system,請在Kubernetes集羣中建立命名空間 :

$ kubectl create namespace istio-system複製代碼

而後進入到 [istio-resources] 目錄並執行如下命令來完成安裝 :

$ helm template install/kubernetes/helm/istio \  --set global.mtls.enabled = false \  --set tracing.enabled = true \  --set kiali.enabled = true \  --set grafana.enabled = true \  --namespace istio-system > istio.yaml複製代碼

上面的命令將Istio的核心組件輸出到文件 istio.yaml 中。咱們使用如下參數自定義模板:

  • global.mtls.enabled 設置爲false以保持引入的重點。

  • tracing.enabled 容許使用jaeger跟蹤請求。

  • kiali.enabled 在咱們的集羣中安裝Kiali以實現服務和流量的可視化

  • grafana.enabled 安裝Grafana,爲了收集指標的可視化。

經過執行如下命令應用生成的資源

$ kubectl apply -f istio.yaml複製代碼

這標誌着咱們集羣中Istio安裝的完成!等到istio-system命名空間中的全部pod都處於Running或Completed狀態,執行如下命令:

$ kubectl get pods -n istio-system複製代碼

如今咱們已準備好繼續下一部分,咱們將在其中啓動並運行示例應用程序。

Sentiment Analysis應用架構

咱們將使用Kubernetes簡介文章中使用的相同微服務應用程序,它足以在實踐中展現Istio的功能。

該應用程序由四個微服務組成:

  • SA-Frontend服務 :提供前端Reactjs應用程序。

  • SA-WebApp服務 :處理對Sentiment Analysis的請求。

  • SA-Logic服務 :執行sentiment Analysis。

  • SA反饋服務 :接收用戶關於分析準確性的反饋。

在圖6中,除了服務以外,咱們還看到Ingress Controller在Kubernetes中將傳入的請求路由到適當的服務,Istio使用了一個名爲Ingress Gateway的相似概念,將在本文的後續部分中介紹。

使用Istio Proxies運行應用程序

要跟進本文,請克隆存儲庫istio-mastery( github.com/rinormaloku… ),其中包含Kubernetes和Istio的應用程序和清單。

Sidecar Injection

注入是 自動手動 完成的 。要啓用自動sidecar注入,咱們須要 istio-injection=enabled 經過執行如下命令 來標記命名空間 :

$ kubectl label namespace default istio-injection=enabled namespace/default labeled複製代碼

從如今開始,部署到默認命名空間的每一個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-app created service/sa-web-app created複製代碼

在部署的服務中,經過執行如下命令 kubectl get pods 驗證pod有兩個容器(service和sidecar), 並確保準備好後,咱們看到值「 2/2 」表示兩個容器都在運行。以下所示:

$ kubectl get pods NAME                           READY     STATUS    RESTARTS   AGE sa-feedback-55f5dc4d9c-c9wfv   2/2       Running   0          12m sa-frontend-558f8986-hhkj9     2/2       Running   0          12m sa-logic-568498cb4d-2sjwj      2/2       Running   0          12m sa-logic-568498cb4d-p4f8c      2/2       Running   0          12m sa-web-app-599cf47c7c-s7cvd    2/2       Running   0          12m複製代碼

視覺呈如今圖7中。

如今,應用程序啓動並運行,咱們須要容許傳入流量到達咱們的應用程序。

入口網關

容許流量進入集羣的最佳作法是經過Istio的 入口網關 將其自身置於集羣的邊緣,並在傳入流量上實現Istio的功能,如路由,負載均衡,安全性和監控。

在Istio的安裝過程當中, Ingress Gateway 組件和在外部公開它的服務已安裝到集羣中。要獲取服務外部IP,請執行如下命令:

$ kubectl get svc -n istio-system -l istio=ingressgateway NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP istio-ingressgateway   LoadBalancer   10.0.132.127   13.93.30.120複製代碼

在本文的後續部分中,咱們將訪問此IP上的應用程序(稱爲EXTERNAL-IP),爲方便起見,經過執行如下命令將其保存在變量中:

$ EXTERNAL_IP=$(kubectl get svc -n istio-system \
  -l app=istio-ingressgateway \
  -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
複製代碼

若是您在瀏覽器中訪問此IP而且您將收到服務不可用錯誤,則 默認狀況下Istio將阻止任何傳入流量, 直到咱們定義網關。

網關資源

網關是在咱們的集羣中安裝Istio時定義的Kubernetes自定義資源定義,使咱們可以指定咱們但願容許傳入流量的端口,協議和主機。

在咱們的場景中,咱們但願容許全部主機在端口80上使用HTTP流量。達到如下定義:

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 Gateway,在咱們的示例中,它是安裝在Istio設置上的默認入口網關控制器。

經過執行如下命令應用配置:

$ kubectl apply -f resource-manifests/istio/http-gateway.yaml
gateway.networking.istio.io/http-gateway created
複製代碼

網關如今容許在端口80中進行訪問,但它不知道在何處路由請求。這須要使用Virtual Service來實現。

VirtualService資源

VirtualService指示Ingress Gateway如何路由容許進入集羣的請求。

對於咱們度過即將到來的應用程序請求 HTTP網關 必須被路由到 sa-frontendsa-web-appsa-feedback 服務(出了如圖8)。

讓咱們分解如下路由到SA-Frontend的請求:

  • **/** 應將精確路徑 路由到SA-Frontend以獲取Index.html

  • **/static/*** 應將前綴路徑 路由到SA-Frontend以獲取前端所需的任何靜態文件,如Css和JavaScript文件。

  • 匹配正則表達式的路徑'^.*\.(ico|png|jpg)$' 應該路由到SA-Frontend,咱們應該把圖像資源路由到前端。

這是經過如下配置實現的:

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
複製代碼

這裏的重點是:

  1. 此VirtualService適用於經過http網關 發出的請求

  2. 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服務器會建立一個由Istio控制平面接收的事件,而後將新配置應用於每一個pod的Envoy代理。Ingress Gateway控制器是另外一個由控制平面配置的Envoy,如圖9所示。

如今能夠訪問Sentiment Analysis應用程序了 http://{EXTERNAL-IP}/ 。若是您得到Not Found狀態,請不要擔憂

有時須要配置生效才能更新envoy的緩存

在轉到下一部分以前,請使用該應用程序生成一些流量。

Kiali - 可觀察性

要訪問Kiali的Admin UI,請執行如下命令:

$ kubectl port-forward \
    $(kubectl get pod -n istio-system -l app=kiali \
    -o jsonpath='{.items[0].metadata.name}') \
    -n istio-system 20001
複製代碼

http://localhost:20001/ 使用「admin」(不含引號)爲用戶和密碼打開登陸。有不少有用的功能,例如檢查Istio組件的配置,根據攔截網絡請求和回答收集的信息可視化服務,「誰在調用誰?」,「哪一個版本的服務有故障?」等等,花一些時間檢驗Kiali的功能,而後再轉到下一節,用Grafana可視化指標!

Grafana - 度量可視化

使用Grafana將Istio收集的指標劃分爲Prometheus和Visualized。要訪問Grafana的Admin UI,請執行如下命令並打開http://localhost:3000

$ kubectl -n istio-system port-forward \
    $(kubectl -n istio-system get pod -l app=grafana \
    -o jsonpath={.items[0].metadata.name}) 3000
複製代碼

在左上角單擊菜單Home 並選擇 Istio Service Dashboard 並在左上角選擇以sa-web-app開頭的服務,您將看到收集的指標,以下圖所示:

個人媽呀,這是一個沒有任何數據的視圖,管理層永遠不會贊同這一點。讓咱們經過執行如下命令生成一些負載:

$ while true; do \
    curl -i http://$EXTERNAL_IP/sentiment \
    -H 「Content-type: application/json」 \
    -d ‘{「sentence」: 「I love yogobella」}’; \
    sleep .8; done
複製代碼

如今咱們擁有更漂亮的圖表,此外,咱們擁有Prometheus用於監控和Grafana用於可視化指標這些使人驚訝的工具,使咱們可以隨時瞭解服務的性能,健康情況,升級或降級!

最後,咱們將研究整個服務中的跟蹤請求。

Jaeger - 追蹤

咱們須要跟蹤,由於咱們所擁有的服務越多,就越難找出失敗的緣由。咱們來看下面圖片中的簡單案例:

請求進入,失敗,

緣由是什麼

第一次服務

仍是第二個

?二者都有例外狀況,讓咱們來看看每一個日誌。你發現本身這麼作了多少次? 咱們的工做更像是軟件偵探而不是開發人員。

這是微服務中的一個廣泛問題,它使用分佈式跟蹤系統解決,其中服務將惟一的header相互傳遞,而後將此信息轉發到請求跟蹤放在一塊兒的分佈式跟蹤系統。一個例子如圖13所示。

Istio使用Jaeger Tracer實現OpenTracing API,這是一個獨立於供應商的框架。要訪問Jaegers UI,請執行如下命令:

$ kubectl port-forward -n istio-system \
    $(kubectl get pod -n istio-system -l app=jaeger \
    -o jsonpath='{.items[0].metadata.name}') 16686
複製代碼

而後在 http://localhost:16686 中打開UI,選擇 sa-web-app 服務,

若是下拉列表中未顯示該

服務,

則在頁面上生成一些活動並點擊刷新

。隨後單擊該按鈕 查找痕跡, 這顯示最近的痕跡,選擇任何和全部的痕跡的詳細分類將會顯示 ,如圖14所示。

跟蹤顯示:

  1. 請求來到 istio-ingressgateway (它是第一次與其中一個服務聯繫,所以對於生成跟蹤ID的請求)而後網關將請求轉發給 sa-web-app 服務。

  2. sa-web-app 服務中,請求由Envoysidecar拾取並建立一個span(這就是咱們在跟蹤中看到它的緣由)並轉發到 sa-web-app 容器實例。

  3. 這裏方法 sentimentAnalysis 處理請求。這些跟蹤由應用程序生成,這意味着須要更改代碼)。

  4. 從POST請求sa-logic開始的位置。跟蹤ID須要sa-web-app傳遞 。

5. ...

注意 :在第4點,咱們的應用程序須要獲取Istio生成的header,並在下一個請求時將其傳遞下來,以下圖所示。

Istio作主要的繁重工做,由於它在傳入的請求上生成header,在每一個sidecar上建立新的span,傳遞它們,可是若是沒有咱們的服務傳遞header,咱們將失去請求的完整跟蹤。

要傳遞的header是:

x-request-id
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
x-ot-span-context
複製代碼

儘管這是一項簡單的任務,但已經有許多庫 能夠簡化這一過程,例如在 sa-web-app服務中, RestTemplate 客戶端經過簡單地依賴項中 添加Jaeger和OpenTracing庫來傳遞header 。

注意:Sentiment Analysis應用程序展現了Flask,Spring和ASP.NET Core的實現。

如今,在調查咱們開箱即用(或部分開箱即用)以後,讓咱們來看看這裏的主題,細粒度路由,管理網絡流量,安全性等等!

流量管理

使用Envoy的Istio爲您的集羣提供了許多新功能,從而實現:

  • 動態請求路由 :Canary部署,A/B測試,

  • 負載均衡: 簡單和一致的哈希平衡,

  • 故障恢復 :超時,重試,熔斷器,

  • 故障注入 :延遲,停止請求等

在本文的序列中,咱們將在咱們的應用程序中展現這些功能,並在此過程當中介紹一些新概念。咱們將研究的第一個概念是DestinationRules,並使用那些咱們將啓用A/B測試的概念。

A/B測試 - 實踐中的目的地規則

當咱們有兩個版本的應用程序(一般版本視覺上有所不一樣)時使用A/B測試,而且咱們不是100%確定會增長用戶交互,所以咱們同時嘗試兩個版本並收集指標。

執行如下命令以部署演示A/B測試所需的前端的第二個版本:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created
複製代碼

綠色版本的部署清單有兩點不一樣:

  1. 該image基於不一樣的標籤: istio-green

  2. pod標有 version: green

而做爲雙方部署在標籤 app: sa-frontend 經過虛擬服務路由的請求 sa-external-services 的服務 sa-frontend 會被轉發到全部的實例,並將於負載採用循環算法,這將致使在圖16中提出的負載均衡問題。

找不到這些文件,由於它們在應用程序的不一樣版本中的命名方式不一樣。讓咱們驗證一下:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js
$ curl --silent http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js
複製代碼

這意味着請求一個版本的靜態文件的index.html能夠被負載均衡到提供另外一個版本的pod,其中能夠理解的是其餘文件不存在。

這意味着,爲了讓咱們的應用程序正常工做,咱們須要引入限制「爲index.html服務的應用程序的版本,必須爲後續請求提供服務」。

咱們將使用Consistent Hash Loadbalancing來實現這一點,這 使用預約義屬性(例如HTTP header)未來自同一客戶端的請求轉發到同一後端實例的過程。由 DestionatioRules提供。

DestinationRules

VirtualService 將請求路由到正確的服務以後,而後使用 DestinationRules, 咱們能夠指定適用於此服務實例的流量的策略,如圖17所示。

注意: 圖17以易於理解的方式可視化Istio資源如何影響網絡流量。可是,準確地說,決定將請求轉發到哪一個實例是由CRD配置的Ingress Gateway的Envoy作出的。

使用目標規則,咱們能夠將負載均衡配置爲具備一致性哈希,並確保同一用戶由同一服務實例響應。經過如下配置實現:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-frontend
spec:
  host: sa-frontend
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: version   # 1
複製代碼
  1. 根據「version」標頭的內容生成一致的哈希。

經過執行如下命令應用配置並嘗試一下!

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend created
複製代碼

執行如下命令並驗證在指定版本header時是否得到相同的文件:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
複製代碼

注意: 爲了方便在瀏覽器中進行測試,您可使用此 Chrome擴展程序 向版本header添加不一樣的值,。

DestinationRules具備更多LoadBalancing功能,全部詳細信息均可以查看 官方文檔

在繼續更詳細地探索VirtualService以前,請執行如下命令,刪除應用程序的綠色版本和目標規則:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions 「sa-frontend-green」 deleted
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io 「sa-frontend」 deleted
複製代碼

鏡像服務 - 實踐中的虛擬服務

當咱們想要測試生產中的更改但不影響最終用戶時,會使用影子或鏡像,所以咱們將請求鏡像到具備更改並評估它的第二個實例中。

更簡單的是,當你的一個同事選擇最關鍵的問題並製做一個超大的合併請求,而且沒人能真正審查。

要測試此功能,能夠 經過執行如下命令 建立SA-Logic的第二個實例(

這是buggy的

):

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created
複製代碼

執行如下命令並驗證全部實例都標有相應的版本,另外還有app=sa-logic標記:

$ kubectl get pods -l app=sa-logic --show-labels
NAME                              READY   LABELS
sa-logic-568498cb4d-2sjwj         2/2     app=sa-logic,version=v1
sa-logic-568498cb4d-p4f8c         2/2     app=sa-logic,version=v1
sa-logic-buggy-76dff55847-2fl66   2/2     app=sa-logic,version=v2
sa-logic-buggy-76dff55847-kx8zz   2/2     app=sa-logic,version=v2
複製代碼

sa-logic 服務目標pod標記爲 app=sa-logic時,任何傳入請求將在全部實例之間進行負載均衡,如圖18所示。

但咱們但願將請求路由到版本爲v1的實例,並鏡像到版本爲v2的實例,如圖19所示。

這是使用VirtualService與DestinationRule結合實現的,其中目標規則指定到特定子集的子集和VirtualService路由。

使用目標規則指定子集

咱們使用如下配置定義子集:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-logic
spec:
  host: sa-logic    # 1
  subsets:
  - name: v1        # 2
    labels:
      version: v1   # 3
  - name: v2
    labels:
      version: v2  
複製代碼
  1. 主機定義此規則僅在向 sa-logic 服務發生路由時適用

  2. 路由到子集實例時使用的子集名稱。

  3. Label定義了須要匹配的鍵值對,以使實例成爲子集的一部分。

應用執行如下命令的配置:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-destinationrule.yaml
 destinationrule.networking.istio.io/sa-logic created
複製代碼

經過定義子集,咱們能夠繼續並配置VirtualService以應用於請求 sa-logic 所在的請求:

  1. 路由到名爲v1的子集,

  2. 鏡像到名爲v2的子集。

這是經過如下清單實現的:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic          
  http:
  - route:
    - destination:
        host: sa-logic  
        subset: v1      
    mirror:             
      host: sa-logic     
      subset: v2
複製代碼

因爲一切配置都是不言自明的,讓咱們看看它的執行:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic created
複製代碼

經過執行如下命令添加一些負載:

$ while true; do curl -v http://$EXTERNAL_IP/sentiment \
    -H 「Content-type: application/json」 \
    -d ‘{「sentence」: 「I love yogobella」}’; \
    sleep .8; done
複製代碼

檢查Grafana中的結果,在那裏咱們能夠看到有錯誤的版本大約有60%的請求失敗,但沒有一個失敗影響最終用戶,由於它們被當前活動的服務響應。

在本節中,咱們第一次看到應用於咱們服務的envoy的VirtualService,當對此 sa-web-app 提出請求時, sa-logic 經過sidecar Envoy,經過VirtualService配置爲路由到子集v1並鏡像到服務的子集v2 sa-logic

我能夠看到你在想「Darn man Virtual Services很簡單!」,在下一節中,咱們將把句子擴展爲「Simply Amazing!」。

金絲雀部署

Canary Deployment是向少數用戶推出新版本應用程序的過程,做爲驗證缺乏問題的一個步驟,而後向更普遍的受衆提供更高質量的發佈保證。

咱們將繼續使用相同的buggy子集 sa-logic 來演示canary部署。

讓咱們大膽地開始,經過應用下面的VirtualService,將20%的用戶發送到有缺陷的版本(這表明金絲雀部署)和80%的健康服務:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic    
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 80         # 1
    - destination: 
        host: sa-logic
        subset: v2
      weight: 20         # 1
複製代碼
  1. 權重指定要轉發到目標或目標子集的請求的百分比。

sa-logic 使用如下命令 更新之前的 虛擬服務配置:

$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-versusyaml
 virtualservice.networking.istio.io/sa-logic configured
複製代碼

咱們當即看到咱們的一些請求失敗了:

$ while true; do \
   curl -i http://$EXTERNAL_IP/sentiment \
   -H 「Content-type: application/json」 \
   -d ‘{「sentence」: 「I love yogobella」}’ \
   --silent -w 「Time: %{time_total}s \t Status: %{http_code}\n」 \
   -o /dev/null; sleep .1; done
Time: 0.153075s Status: 200
Time: 0.137581s Status: 200
Time: 0.139345s Status: 200
Time: 30.291806s Status: 500
複製代碼

VirtualServices啓用了Canary Deployments,經過這種方法,咱們將潛在的損害減小到了20%的用戶羣。漂亮! 如今,每當咱們對代碼不安全時,咱們就可使用Shadowing和Canary Deployments,換句話說,老是如此。😜

超時和重試

代碼並不老是錯誤的。在「 分佈式計算的8個謬誤 」列表中,第一個謬論是「網絡可靠」。網絡不可靠,這就是咱們須要超時和重試的緣由。

出於演示目的,咱們將繼續使用有缺陷的版本 sa-logic,其中隨機故障模擬網絡的不可靠性。

有缺陷的服務有三分之一的機會花費太長時間來響應,三分之一的機會之內部服務器錯誤結束,其他的成功完成。

爲了緩解這些問題並改善用戶體驗,咱們能夠:

  1. 若是服務時間超過8秒,則超時

  2. 重試失敗的請求。

這是經過如下資源定義實現的:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 50
    - destination: 
        host: sa-logic
        subset: v2
      weight: 50
    timeout: 8s           # 1
    retries:
      attempts: 3         # 2
      perTryTimeout: 3s   # 3
複製代碼
  1. 請求的超時時間爲8秒,

  2. 它嘗試了3次,

  3. 若是嘗試時間超過3秒,則嘗試將請求標記爲失敗。

這是一種優化,由於用戶不會等待超過8秒,而且咱們在發生故障時重試三次,從而增長了致使響應成功的機會。

使用如下命令應用更新的配置:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic configured
複製代碼

並查看Grafana圖表,瞭解成功率的改善狀況(如圖21所示)。

sa-logic-buggy 經過執行如下命令 進入下一部分delete 和VirtualService 以前 :

$ kubectl delete deployment sa-logic-buggy
deployment.extensions 「sa-logic-buggy」 deleted
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io 「sa-logic」 deleted
複製代碼

熔斷器和隔離模式

微服務架構中的兩個重要模式,能夠實現服務的自我修復。

熔斷器 是用來阻止請求將視爲不健康服務的一個實例,並使它可以恢復,在此期間客戶端的請求轉發到該服務的健康狀況(增長成功率)。

隔離模式 整個系統降級來隔離錯誤,防止錯誤傳播,舉一個隔離故障例子,服務B處於損壞狀態和其它服務(服務B的客戶端)發出請求到服務B,這將致使該客戶端將使用了本身的線程池,將沒法提供其餘請求(即便這些請求與服務B無關)。

我將跳過這些模式的實現,由於您能夠查看 官方文檔中的實現,我很興奮地展現身份驗證和受權,這將是下一篇文章的主題。

第一部分 - 摘要

在本文中,咱們在Kubernetes集羣中部署了Istio,並使用其自定義資源定義(如 網關VirtualServicesDestinationRules 及其組件)啓用瞭如下功能:

  • 使用 Kiali,經過查看正在運行的服務,它們如何執行,以及它們關係,來觀察咱們的服務 。

  • 使用 PrometheusGrafana 進行收集和可視化 。

  • 請求 Jaeger 跟蹤 (Hunter的德語)。

  • 對網絡流量進行全面細粒度控制,實現 Canary DeploymentsA/B測試和Shadowing

  • 輕鬆實現 重試,超時和CircuitBreakers

全部這些均可以在沒有代碼更改或任何其餘依賴性的狀況下實現,從而使您的服務保持小巧,易於操做和維護

對於您的開發團隊來講,消除這些跨領域的問題並將它們集中到Istio的控制平面,意味着新服務很容易引入,它們不會佔用大量資源,由於開發人員能夠專一於解決業務問題。到目前爲止,沒有任何開發人員抱怨「必須解決有趣的業務問題!」。

我很樂意在下面的評論中聽到您的想法,並隨時在 Twitter 或個人頁面 rinormaloku.com 上與我 聯繫,並繼續關注下一篇文章,咱們將解決最後一層認證和受權問題!

相關文章
相關標籤/搜索