在微服務架構中,確保服務的穩定性和可靠性至關重要。Istio 提供了豐富的服務彈性功能,例如請求重試和斷路器,可以有效地應對網路故障和服務異常。本文將詳細介紹如何使用 Istio 組態這些功能,並結合 Fortio、Grafana 和 Jaeger 等工具進行測試和監控。此外,本文還會探討 Istio 的安全架構,包括身份驗證和授權機制,以確保服務間通訊的安全性。

服務彈性與容錯機制

在前面的章節中,我們已經瞭解瞭如何利用 Istio 來監控和觀察服務之間的通訊。在本章節中,我們將進一步探討服務彈性(Service Resiliency)的相關概念,包括請求重試(Request Retries)和斷路器(Circuit Breakers)。

請求重試

請求重試是一種常見的容錯機制,用於在服務呼叫失敗時進行重試。在 Istio 中,我們可以透過組態 VirtualService 來實作請求重試。

組態請求重試

以下是一個範例,展示瞭如何在 VirtualService 中組態請求重試:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: greeter-service
spec:
  hosts:
  - greeter-service
  http:
  - route:
    - destination:
        host: greeter-service.default.svc.cluster.local
        port:
          number: 3000
        subset: v3
    timeout: 2s
    retries:
      attempts: 3
      perTryTimeout: 0.5s

在這個範例中,我們組態了請求重試的次數為 3 次,每次重試的超時時間為 0.5 秒。

請求重試的效果

透過 Jaeger 的追蹤資料,我們可以看到請求重試的效果。如下圖所示: 此圖示 在這個圖中,我們可以看到三次請求都被傳送到了 /version 端點,並且每次重試的時間間隔為 0.5 秒。

內容解密:

  1. 請求重試的組態:在 VirtualService 中,我們透過 retries 欄位來組態請求重試的次數和超時時間。
  2. Jaeger 追蹤資料:透過 Jaeger 的追蹤資料,我們可以看到請求重試的效果,包括每次重試的時間和結果。
  3. 請求重試的作用:請求重試可以提高服務的可用性和容錯性,減少因臨時性錯誤導致的請求失敗。

斷路器

斷路器是一種用於防止服務過載和故障擴散的機制。在 Istio 中,我們可以透過組態 DestinationRule 來實作斷路器。

組態斷路器

以下是一個範例,展示瞭如何在 DestinationRule 中組態斷路器:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: greeter-service
spec:
  host: greeter-service.default.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        http2MaxRequests: 10
        maxRequestsPerConnection: 5
    outlierDetection:
      consecutiveErrors: 3
      interval: 10s
      baseEjectionTime: 10m
      maxEjectionPercent: 10

在這個範例中,我們組態了斷路器的相關引數,包括連續錯誤次數、掃描間隔、基礎驅逐時間和最大驅逐百分比。

斷路器的作用

斷路器可以檢測到服務的異常,並將其從負載平衡池中移除,以防止進一步的請求失敗。

內容解密:

  1. 斷路器的組態:在 DestinationRule 中,我們透過 outlierDetection 欄位來組態斷路器的相關引數。
  2. 斷路器的作用:斷路器可以檢測到服務的異常,並將其從負載平衡池中移除,以防止進一步的請求失敗。
  3. 斷路器的好處:斷路器可以提高服務的可用性和容錯性,減少因服務故障導致的請求失敗。

Service Resiliency 服務彈性與容錯機制

在微服務架構中,服務彈性(Service Resiliency)是確保系統穩定執行的關鍵要素。本章將探討如何利用 Istio 實作服務彈性,並介紹相關策略和模式。

使用 Istio 組態 VirtualService

首先,我們需要定義一個 VirtualService 來管理對 greeter-service 的請求。以下是組態範例:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: greeter-service
spec:
  hosts:
  - greeter-service.default.svc.cluster.local
  http:
  - route:
    - destination:
        host: greeter-service.default.svc.cluster.local
        port:
          number: 3000

內容解密:

  • apiVersionkind 定義了資源的型別和版本。
  • metadata.name 指定了 VirtualService 的名稱。
  • spec.hosts 定義了該 VirtualService 所管理的服務主機名稱。
  • http.route.destination 指定了請求轉發的目的地和埠。

使用 Fortio 進行負載測試

為了展示電路斷路器(Circuit Breaker)的效果,我們將使用 Fortio 進行負載測試。首先,佈署 Fortio:

kubectl create -f code/ch4/fortio.yaml

然後,從 Fortio Pod 向 greeter-service 發起簡單的請求:

export FORTIO_POD=$(kubectl get pod | grep fortio | awk '{ print $1 }')
kubectl exec -it $FORTIO_POD -c fortio -- fortio load -curl http://greeter-service:3000/hello

內容解密:

  • kubectl create 佈署 Fortio。
  • fortio load 對指定 URL 發起請求。

電路斷路器測試

為了觸發電路斷路,將 greeter-service 的副本數縮減至 1:

kubectl scale deploy greeter-service-{v1,v2,v3} --replicas=1

然後,使用 Fortio 發起 20 個請求,並設定 2 個並發連線:

kubectl exec -it $FORTIO_POD -c fortio -- fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://greeter-service:3000/hello

輸出結果顯示,部分請求失敗,表明電路斷路器生效。

Testing Services 服務測試

本章將探討如何利用 Istio 的功能進行服務測試,特別是在服務彈性方面的測試。

Injecting HTTP Delays 注入 HTTP 延遲

透過在 VirtualService 中定義故障注入,可以模擬不同的網路問題。以下是注入 HTTP 延遲的範例:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: greeter-service
spec:
  hosts:
  - greeter-service
  http:
  - route:
    - destination:
        host: greeter-service.default.svc.cluster.local
        port:
          number: 3000
    fault:
      delay:
        percent: 50
        fixedDelay: 2s

內容解密:

  • fault.delay 定義了延遲注入的組態。
  • percent 指定了延遲發生的機率。
  • fixedDelay 指定了延遲的時間長度。

Observing Delays in Grafana 在 Grafana 中觀察延遲

佈署上述組態後,透過不斷向 helloweb.dev 傳送請求,並在 Grafana 中觀察 greeter-service 的表現,可以看到相關圖表資料的變化。

while true; do sleep 1; curl -H "Host: helloweb.dev" http://$GATEWAY; done

內容解密:

  • 此命令迴圈傳送請求到指定閘道器,以產生流量。

使用 Grafana 和 Jaeger 觀察服務延遲與錯誤注入

在微服務架構中,觀察服務之間的延遲和錯誤對於問題的診斷和系統的穩定性至關重要。本篇文章將介紹如何利用 Grafana 和 Jaeger 來觀察和分析服務之間的延遲,以及如何透過 Istio 注入 HTTP 延遲和錯誤來測試服務的健壯性。

Grafana Dashboard 與服務延遲觀察

首先,我們來看看如何使用 Grafana 來觀察服務之間的延遲。在我們的例子中,我們有一個名為 helloweb 的服務,它呼叫了 greeter-service。透過在 Grafana 中建立適當的 Dashboard,我們可以觀察到客戶端請求的持續時間、來自上游服務的延遲等指標。

Client Request Duration

這個圖表顯示了客戶端請求的持續時間,包括 p50、p90 和 p99 的值。透過觀察 p99 的值,我們可以看到 99% 的請求在 2.4 秒內完成,而 1% 的請求則花費了更長的時間。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Istio服務彈性與容錯機制實踐

package "安全架構" {
    package "網路安全" {
        component [防火牆] as firewall
        component [WAF] as waf
        component [DDoS 防護] as ddos
    }

    package "身份認證" {
        component [OAuth 2.0] as oauth
        component [JWT Token] as jwt
        component [MFA] as mfa
    }

    package "資料安全" {
        component [加密傳輸 TLS] as tls
        component [資料加密] as encrypt
        component [金鑰管理] as kms
    }

    package "監控審計" {
        component [日誌收集] as log
        component [威脅偵測] as threat
        component [合規審計] as audit
    }
}

firewall --> waf : 過濾流量
waf --> oauth : 驗證身份
oauth --> jwt : 簽發憑證
jwt --> tls : 加密傳輸
tls --> encrypt : 資料保護
log --> threat : 異常分析
threat --> audit : 報告生成

@enduml

Incoming Request Duration by Source

這個圖表顯示了來自上游服務(在本例中是 helloweb)的請求延遲。如果有多個版本的 helloweb 服務,我們可以清楚地看到哪個版本的延遲更高或更低。

使用 Jaeger 觀察追蹤

除了 Grafana,我們還可以使用 Jaeger 來觀察請求的追蹤資訊。透過在 Jaeger 中搜尋最小持續時間為 2 秒的追蹤記錄,我們可以找到那些耗時較長的請求,並進一步分析其原因。

Jaeger - trace with a 2 second HTTP delay

在 Jaeger 的追蹤記錄中,我們可以看到 hellowebgreeter-service 的請求總共花費了 2.03 秒,而 greeter-service 本身只花費了 5.9 毫秒。

發現問題

透過結合 Grafana 和 Jaeger,我們可以有效地發現服務中的潛在問題。例如,如果我們在 greeter-service 中注入一個 6 秒的延遲,我們會在 Grafana 中看到成功率下降和客戶端請求持續時間增加。

Grafana - 6-second delay causing timeouts

同時,在 Jaeger 中,我們可以看到一些追蹤記錄中出現了錯誤標籤,這表明請求在完成之前就超時了。

注入 HTTP Aborts

除了延遲之外,我們還可以透過 Istio 注入 HTTP 中止錯誤,以測試服務的健壯性。透過定義一個傳回 HTTP 404 狀態碼的 VirtualService,我們可以模擬某些請求失敗的情況。

Grafana - 404 status in graph

在 Grafana 中,我們可以看到由於注入的中止錯誤,HTTP 404 狀態碼的數量增加了。同時,在 Jaeger 中搜尋包含 HTTP 404 狀態碼的追蹤記錄,可以看到這些請求沒有到達 greeter-service,而是在 sidecar proxy 處被攔截並傳回了 HTTP 404。

內容解密:
  1. 使用 Grafana 和 Jaeger:本段落講解了如何利用這兩個工具來監控和分析微服務架構中的延遲和錯誤。
  2. Grafana Dashboard:重點介紹瞭如何透過 Grafana 觀察客戶端請求持續時間和上游服務延遲。
  3. Jaeger 追蹤:說明瞭如何使用 Jaeger 分析耗時較長的請求及其追蹤資訊。
  4. 發現問題:描述瞭如何透過注入延遲和錯誤來測試服務的健壯性,並利用 Grafana 和 Jaeger 發現潛在問題。
  5. 注入 HTTP Aborts:介紹瞭如何模擬 HTTP 中止錯誤,並觀察其對系統的影響。

進階測試案例:結合HTTP延遲與錯誤注入

在瞭解基本的故障注入工作原理後,可以進一步結合HTTP延遲和HTTP錯誤來創造更複雜的測試案例。以下是一個範例組態,展示如何同時注入這兩種型別的故障:

同時注入HTTP 404錯誤和6秒延遲

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: greeter-service
spec:
  hosts:
  - greeter-service
  http:
  - route:
    - destination:
        host: greeter-service.default.svc.cluster.local
        port:
          number: 3000
    fault:
      abort:
        percentage:
          value: 10
        httpStatus: 404
      delay:
        percentage:
          value: 10
        fixedDelay: 6s

內容解密:

  1. 故障注入組態:在fault欄位下組態了兩種故障型別:abortdelay
    • abort:對10%的請求傳回HTTP 404錯誤。
    • delay:對10%的請求引入6秒的延遲。
  2. 路由組態:請求被路由到greeter-service服務的3000埠。
  3. 百分比組態percentage.value用於指定故障發生的機率。

根據User-Agent的故障注入

進一步結合流量管理的功能,可以實作根據特定條件的故障注入,例如針對來自Firefox瀏覽器的請求:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: greeter-service
spec:
  hosts:
  - greeter-service
  http:
  - fault:
      abort:
        percentage:
          value: 10
        httpStatus: 404
    match:
    - headers:
        user-agent:
          regex: '.*Firefox.*'
    route:
    - destination:
        host: greeter-service.default.svc.cluster.local
        port:
          number: 3000
  - route:
    - destination:
        host: greeter-service.default.svc.cluster.local
        port:
          number: 3000

內容解密:

  1. 匹配條件:使用match欄位根據user-agent頭部匹配來自Firefox的請求。
  2. 故障注入:對匹配的請求中的10%注入HTTP 404錯誤。
  3. 預設路由:未匹配的請求按照第二個路由規則正常轉發。

Istio安全架構

Istio提供了一套全面的安全解決方案,包括身份驗證、授權和加密等功能。其安全架構涉及多個元件:

主要元件

  • 證書頒發機構(CA):負責管理和頒發證書。
  • Sidecar和Perimeter代理:實作客戶端和伺服器端之間的加密通訊。
  • Envoy代理擴充套件:管理遙測和稽核。
  • 組態API伺服器:分發身份驗證、授權策略和安全命名資訊。

安全架構圖

此圖示展示了Istio安全架構的不同元件及其職責。

身份驗證與授權

Istio使用SPIFFE(Secure Production Identity Framework for Everyone)標準來頒發和管理服務身份。在Kubernetes中,服務賬戶用於服務身份。SPIFFE ID的格式為spiffe://cluster-name/ns/namespace/sa/service-account-name

檢視服務賬戶和對應的Secret

$ kubectl describe sa default
Name:                default
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   default-token-pjqr9
Tokens:              default-token-pjqr9
Events:              <none>

內容解密:

  1. kubectl describe sa default:檢視名為default的服務賬戶的詳細資訊。
  2. Mountable secrets:顯示可掛載的Secret名稱,該Secret包含證書和Token。
  3. Tokens:列出與服務賬戶相關聯的Token名稱。