筆記。 翻譯。:服務網格無疑已成為現代基礎架構中微服務架構應用程式的相關解決方案。 雖然 Istio 可能是許多 DevOps 工程師經常掛在嘴邊的,但它是一個相當新的產品,雖然其提供的功能很全面,但可能需要大量時間來熟悉。 德國工程師 Rinor Maloku 在電信公司 Orange Networks 負責大客戶的雲端運算,他編寫了一系列精彩的材料,讓您快速深入了解 Istio。 他從 Istio 一般可以做什麼以及如何快速親眼看到它開始了他的故事。
Istio — 與 Google、IBM 和 Lyft 團隊合作開發的開源專案。 它解決了基於微服務的應用程式中出現的複雜性,例如:
- 交通管理:超時、重試、負載平衡;
- 安全:最終使用者身份驗證和授權;
- 可觀察性:追蹤、監控、記錄。
這些都可以在應用層面解決,但之後你的服務將不再是「微」的。 所有為解決這些問題而付出的額外努力都是對公司資源的浪費,而這些資源本來可以直接用於商業價值。 讓我們來看一個例子:
專案經理:新增回饋功能需要多長時間?
開發人員:兩次衝刺。MP:什麼?...這只是 CRUD!
R:做CRUD是比較容易的部分,但我們還是需要對使用者和服務進行身份驗證和授權。 由於網路不可靠,您將需要實現重複的請求,以及斷路器模式 在客戶中。 此外,為了確保整個系統不會崩潰,您將需要逾時和隔板 (有關上述兩種模式的更多詳細信息,請參閱本文後面的內容 - 大約翻譯。),並為了發現問題、監控、追踪,[...]MP:哦,那我們就把這個功能插入到產品服務中吧。
我認為這個想法很明確:增加一項服務所需的步驟和精力是巨大的。 在本文中,我們將了解 Istio 如何從服務中消除上述所有複雜性(並非旨在成為業務邏輯)。
注意:本文假設您具備 Kubernetes 的應用知識。 否則,我建議閱讀
Istio理念
在沒有 Istio 的世界中,一個服務直接向另一個服務發出請求,如果發生故障,服務必須自行處理:進行新的嘗試、提供超時、打開斷路器等。
Kubernetes 中的網路流量
Istio 提供了一種專門的解決方案,與服務完全分離,並透過幹擾網路通訊來運作。 因此它實現了:
- 容錯:根據回應中的狀態碼,了解請求是否失敗並重新執行。
- 金絲雀推出:僅將固定百分比的請求重新導向到新版本的服務。
- 監控和指標: 服務花了多久時間才回應?
- 追蹤和可觀察性:為每個請求添加特殊標頭並在叢集中追蹤它們。
- 安全:檢索 JWT 令牌,對使用者進行身份驗證和授權。
這些只是引起您興趣的一些可能性(實際上只是一些!)。 現在讓我們深入探討技術細節!
Istio架構
Istio 攔截所有網路流量並對其應用一組規則,以 sidecar 容器的形式將智慧代理插入到每個 pod 中。 激活所有功能的代理形成 數據平面,並且可以使用動態配置它們 控制平面.
數據平面
插入 pod 中的代理可以讓 Istio 輕鬆滿足我們的需求。 例如,讓我們檢查一下重試和斷路器功能。
Envoy 中如何實現重試與熔斷
總結:
- 使者 (我們正在討論位於 sidecar 容器中的代理,該容器分佈為
單獨的產品 - 大約。 譯) 向服務 B 的第一個實例發送請求並失敗。 - Envoy Sidecar 再次嘗試 (重試). (1)
- 請求失敗並返回到呼叫它的代理。
- 這將打開斷路器並為後續請求呼叫下一個服務。 (2)
這意味著您不必使用另一個重試庫,也不必使用程式語言 X、Y 或 Z 自行實現熔斷和服務發現。所有這些以及更多功能都是開箱即用的在 Istio 中並且不需要 沒有 代碼的變化。
偉大的! 現在你可能想和 Istio 一起去旅行,但你仍然有一些疑慮,一些懸而未決的問題。 如果這是適用於生活中所有場合的通用解決方案,那麼您自然會產生懷疑:畢竟,所有此類解決方案實際上都不適用於任何情況。
最後你問:“它可以定制嗎?”
現在您已準備好進行海上航行,讓我們來熟悉一下控制平面。
控制平面
它由三個部分組成: 飛行員, 混頻器 и 堡壘,它們協同工作來配置 Envoy 來路由流量、執行策略和收集遙測資料。 從原理上講,一切都是這樣的:
控制平面與資料平面的交互
Envoy(即資料平面)使用以下配置
服務與 Istio 的關係
我們已經描述了 Istio 與服務的關係,但沒有反過來:服務與 Istio 有何關係?
老實說,當服務問自己「水到底是什麼?」時,它們就會意識到 Istio 的存在,就像魚意識到水一樣。
插圖
因此,您可以使用工作集群,在部署 Istio 元件後,位於其中的服務將繼續工作,而在刪除這些元件後,一切都會恢復正常。 顯然,在這種情況下您將失去 Istio 提供的功能。
理論已經足夠了——讓我們將這些知識付諸實踐!
Istio 實踐
Istio 需要一個至少具有 4 個 vCPU 和 8 GB 可用 RAM 的 Kubernetes 叢集。 要快速設定叢集並按照文章中的說明進行操作,我建議使用 Google Cloud Platform,它為新使用者提供了
建立叢集並透過控制台實用程式設定對 Kubernetes 的存取後,您可以透過 Helm 套件管理器安裝 Istio。
舵安裝
在您的電腦上安裝 Helm 用戶端,如中所述
安裝 Istio
從以下位置下載 Istio 資源 [istio-resources]
.
為了輕鬆識別 Istio 資源,請在 K8s 叢集中建立命名空間 istio-system
:
$ 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
(即 mTLS 身份驗證已停用 - 約)簡化我們的約會流程; -
tracing.enabled
包括使用 Jaeger 進行請求追蹤; -
kiali.enabled
將 Kiali 安裝到叢集中以視覺化服務和流量; -
grafana.enabled
安裝 Grafana 來視覺化收集的指標。
讓我們透過以下命令使用生成的資源:
$ kubectl apply -f istio.yaml
集群上Istio安裝完成! 等待所有 Pod 都位於命名空間中 istio-system
將能夠 Running
或 Completed
透過執行以下命令:
$ kubectl get pods -n istio-system
現在我們準備好繼續下一部分,我們將啟動並運行應用程式。
情感分析應用程式的架構
讓我們使用已經提到的情緒分析微服務應用程式的範例
該應用程式由四個微服務組成:
- 服務 SA-前端,它服務於 Reactjs 應用程式的前端;
- 服務 SA-Web應用程式,它提供情緒分析查詢;
- 服務 SA邏輯,它自己執行
情緒分析 ; - 服務 SA-回饋,它接收用戶關於分析準確性的回饋。
在此圖中,除了服務之外,我們還看到了入口控制器,它在 Kubernetes 中將傳入請求路由到適當的服務。 Istio 在其 Ingress Gateway 中使用了類似的概念,稍後將介紹更多詳細資訊。
使用 Istio 代理程式運行應用程式
對於本文中提到的進一步操作,請克隆您的存儲庫
插入邊車
可以進行插入操作 自動 或 手工。 若要自動插入 sidecar 容器,您需要為命名空間設定標籤 istio-injection=enabled
,這是透過以下命令完成的:
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled
現在每個 Pod 將部署在預設命名空間中(default
)將收到其邊車容器。 為了驗證這一點,讓我們透過前往儲存庫的根目錄來部署測試應用程式 [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
部署服務後,讓我們透過執行命令來檢查 pod 是否有兩個容器(包含服務本身及其 sidecar) kubectl get pods
並確保在該列下 READY
指定值 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
從視覺上看,它看起來像這樣:
Envoy 代理程式位於其中一個 Pod 中
現在應用程式已啟動並運行,我們需要允許傳入流量進入應用程式。
入口網關
實現這一點(允許叢集中的流量)的最佳實踐是透過 入口網關 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 會阻止所有傳入流量,網關尚未定義。
網關資源
網關是 Kubernetes 中的 CRD(自訂資源定義),在叢集中安裝 Istio 後定義,並能夠指定我們希望允許傳入流量的連接埠、協定和主機。
在我們的範例中,我們希望允許所有主機在連接埠 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。 在我們的例子中,這是 Ingress Gateway 控制器,預設安裝在 Istio 中。
透過調用以下命令應用配置:
$ kubectl apply -f resource-manifests/istio/http-gateway.yaml gateway.networking.istio.io/http-gateway created
網關現在允許存取連接埠 80,但不知道將請求路由到哪裡。 為此你需要 虛擬服務.
虛擬服務資源
VirtualService 告訴 Ingress Gateway 如何路由叢集內允許的請求。
透過 http-gateway 對我們的應用程式發出的請求必須傳送到 sa-frontend、sa-web-app 和 sa-feedback 服務:
需要設定VirtualServices的路由
讓我們看看應該發送到 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
Важныемоменты:
- 此 VirtualService 指的是透過以下方式傳送的請求 http網關;
- В
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。 所有這一切在圖中看起來像這樣:
用於請求路由的 Istio-IngressGateway 配置
情緒分析應用程式現已推出 http://{EXTERNAL-IP}/
。 如果您出現「未找到」狀態,請不要擔心: 有時配置生效和 Envoy 快取更新需要更長的時間.
在繼續之前,先使用該應用程式來產生流量。 (為了後續行動的清晰性,它的存在是必要的 - 大約翻譯。).
Kiali:可觀察性
若要存取 Kiali 管理介面,請執行以下命令:
$ kubectl port-forward
$(kubectl get pod -n istio-system -l app=kiali
-o jsonpath='{.items[0].metadata.name}')
-n istio-system 20001
....然後打開
Grafana:指標視覺化
在 Istio 中收集的指標進入 Prometheus 並使用 Grafana 進行視覺化。 若要進入 Grafana 管理介面,請執行以下命令,然後開啟
$ kubectl -n istio-system port-forward
$(kubectl -n istio-system get pod -l app=grafana
-o jsonpath={.items[0].metadata.name}) 3000
點擊選單 首頁 左上角並選擇 Istio 服務儀表板 在左上角,從服務開始 sa-網路應用程式查看收集的指標:
這裡等待我們的是一場空洞且完全無聊的表演——管理層永遠不會批准這一點。 讓我們使用以下命令建立一個小負載:
$ while true; do
curl -i http://$EXTERNAL_IP/sentiment
-H "Content-type: application/json"
-d '{"sentence": "I love yogobella"}';
sleep .8; done
現在我們有了更好的圖表,除此之外,還有用於監控的精彩 Prometheus 工具和用於可視化指標的 Grafana,這將使我們能夠了解性能、運行狀況、服務隨時間的改進/退化。
最後,讓我們看看服務中的追蹤請求。
耶格:追蹤
我們需要跟踪,因為我們擁有的服務越多,找到故障原因就越困難。 我們來看一個簡單的案例,如下圖:
隨機失敗請求的典型範例
請求來了,落下—— 是什麼原因? 第一次服務? 還是第二個? 兩者都有例外 - 讓我們看看每個的日誌。 您多久發現自己這樣做一次? 我們的工作更像是軟體偵探而不是開發人員...
這是微服務中的常見問題,可以透過分散式追蹤系統解決,其中服務相互傳遞唯一的標頭,然後將此資訊轉發到追蹤系統,在追蹤系統中與請求資料進行比較。 這是一個例子:
TraceId用於識別請求
Istio 使用 Jaeger Tracer,它實作了獨立於供應商的 OpenTracing API 框架。 您可以使用以下命令存取 Jaeger 使用者介面:
$ kubectl port-forward -n istio-system
$(kubectl get pod -n istio-system -l app=jaeger
-o jsonpath='{.items[0].metadata.name}') 16686
現在去
該追蹤顯示:
- 請求進來了 istio-ingressgateway (這是與其中一個服務的第一次交互,並為請求產生追蹤 ID),之後網關將請求發送到服務 sa-網路應用程式.
- 在職 sa-網路應用程式 請求被 Envoy sidecar 接收,在跨度中創建一個「子」(這就是我們在追蹤中看到它的原因)並重定向到容器 sa-網路應用程式. (
跨度 - Jaeger 中的邏輯工作單元,具有名稱、操作的開始時間及其持續時間。 Span 可以嵌套和排序。 跨距的有向無環圖形成一條跡。 — 約。 譯) - 這裡的請求是透過方法處理的 情緒分析。 這些追蹤已經由應用程式生成,即他們需要更改程式碼。
- 從這一刻起,發起POST請求 薩邏輯。 追蹤 ID 必須轉送自 sa-網路應用程式.
- ...
注意:在步驟 4 中,應用程式應該看到 Istio 產生的標頭並將其傳遞給後續請求,如下圖所示:
(A) Istio 負責轉發 header; (B) 服務負責標頭
Istio 完成了大部分工作,因為... 為傳入請求產生標頭,在每個 sidecare 中建立新的跨度並轉發它們。 但是,如果不使用服務內部的標頭,完整的請求追蹤路徑將會遺失。
必須考慮以下標頭:
x-request-id
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
x-ot-span-context
這不是一項困難的任務,但為了簡化其實現,已經有
請注意,情緒分析應用程式演示了 Flask、Spring 和 ASP.NET Core 中的實作。
現在我們已經清楚了開箱即用(或幾乎開箱即用)的內容,讓我們來看看微調路由、網路流量管理、安全性等!
筆記。 翻譯。:請閱讀 Rinor Maloku 提供的 Istio 資料的下一部分來了解這一點,其翻譯將在不久的將來出現在我們的部落格上。 更新 (14 月 XNUMX 日):
譯者PS
另請閱讀我們的博客:
- “回到 Istio 的微服務”:
第 2 部分(路由、流量控制) ,第3部分(身份驗證和授權) ; - «
Conduit - Kubernetes 的輕量級服務網格 “; - «
什麼是服務網格,為什麼我需要它 [用於具有微服務的雲應用程序]? “; - «
Kubernetes 網路圖解指南。 第 1 部分和第 2 部分 “; - «
這個 sidecar 容器是如何[在 Kubernetes 中]出現在這裡的? “。
來源: www.habr.com