在現代微服務架構中,Istio 提供了一個強大的服務網格平台,其核心元件 Sidecar Proxy 負責管理服務間的流量。理解 Sidecar 的組態對於控制服務的行為至關重要,包含如何設定入口和出口流量、如何使用 Kiali 和 Jaeger 等工具監控和追蹤服務,以及如何利用 Istio 的彈性功能(如超時、重試和斷路器)提升服務的穩定性。這些技術的整合運用,能有效提高微服務架構的整體韌性和可觀察性,確保系統在面對各種挑戰時仍能保持穩定執行。

Istio 中的 Sidecar Proxy 設定與流量管理

在 Istio 服務網格中,Sidecar Proxy 是一種重要的元件,它被注入到每個 Kubernetes 佈署中,負責處理進出服務的流量。預設情況下,Sidecar Proxy 被組態為接受所有埠上的流量,並且可以將流量轉發到網格中的任何服務。然而,在某些情況下,您可能需要更改此組態,以限制 Sidecar Proxy 只能使用特定的埠和存取特定的服務。這可以透過使用 Istio 中的 Sidecar 資源來實作。

Sidecar 資源的組成

Sidecar 資源由三個主要部分組成:工作負載選擇器(Workload Selector)、入口監聽器(Ingress Listener)和出口監聽器(Egress Listener)。

工作負載選擇器

工作負載選擇器用於決定哪些工作負載將受到 Sidecar 組態的影響。您可以選擇控制名稱空間內的所有 Sidecar,或者提供工作負載選擇器以僅將組態應用於特定的服務。

apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
  name: default-sidecar
  namespace: default
spec:
  workloadSelector:
    labels:
      version: v1
  egress:
  - hosts:
    - "default/*"
    - "istio-system/*"
    - "staging/*"

入口監聽器

入口監聽器用於定義哪些入站流量將被接受。每個入口監聽器都需要設定一個埠號(例如,下面的範例中的 5000)和一個預設端點(例如,127.0.0.1:8080)。預設端點可以是迴路 IP 端點或 Unix 網域通訊端。

ingress:
- port:
    number: 5000
    protocol: HTTP
    name: somename
  defaultEndpoint: 127.0.0.1:8080

出口監聽器

出口監聽器用於定義 Sidecar Proxy 的出站流量屬性。它與入口監聽器具有相似的欄位,但增加了 hosts 欄位。hosts 欄位用於指定服務主機。

egress:
- port:
    number: 8080
    protocol: HTTP
    bind: 127.0.0.1
  hosts:
  - "*/my-api.example.com"

內容解密:

  • apiVersionkind 定義了資源的 API 版本和型別。
  • metadata 部分包含了資源的後設資料,例如名稱和名稱空間。
  • spec 部分定義了 Sidecar 資源的規格,包括工作負載選擇器、入口監聽器和出口監聽器。
  • workloadSelector 用於選擇要應用 Sidecar 組態的工作負載。
  • egress 部分定義了出站流量的屬性,包括要存取的服務主機。
  • ingress 部分定義了入站流量的屬性,包括要接受的埠和預設端點。

提升服務韌性的關鍵策略與實踐

在將單體式應用程式拆解為更小、更易管理的微服務,或是從頭開始實施微服務架構時,你會注意到需要管理的事務變得更多。以前,你只有一個程式碼函式庫,一個佈署單元。而在轉向微服務後,你將進行多次佈署,且程式碼可能分散在多個儲存函式庫中。

什麼是韌性?

韌性是指在面對故障和挑戰時,能夠提供並維持可接受的服務水準。它並不是要避免故障,而是要在故障發生時,以不造成停機或資料遺失的方式做出反應。韌性的目標是在故障發生後,將服務還原到完全運作的狀態。

服務韌性有兩個主要導向:

  1. 高用性:服務在健康狀態下運作,沒有明顯的停機時間,能夠回應請求並滿足其服務水準協定(SLAs)。
  2. 災難復原:關注如何從罕見但重大的事件中還原,涉及資料備份和存檔。

如何實作韌性?

在開發服務時,有幾點需要注意,以實作更高的韌性:

  1. 瞭解需求並定義服務可用性:思考可以容忍多少停機時間,什麼是可接受的,以及服務可用性的定義。
  2. 識別故障點:思考可能出錯的地方,以及如何出錯。
  3. 檢測和還原故障:定義如何檢測故障、如何回應故障,以及如何記錄和監控故障。
  4. 模擬故障條件:使用工具(如 Istio 服務網格)模擬不同的故障條件,以確保能夠檢測和還原故障。
  5. 監控服務狀態:建立監控機制,以瞭解服務的運作狀態和測試結果。

服務韌性策略

有多種策略可以提高服務的韌性:

  1. 使用逾時和重試機制:在進行服務請求時,使用逾時和重試機制,以避免無限等待和資源浪費。
  2. 電路斷路器模式:使用電路斷路器模式,以限制故障對服務的影響,當故障次數超過閾值時,斷路器會跳開,將故障的服務例項從負載平衡池中移除。
  3. 負載平衡和擴充套件:使用負載平衡和擴充套件機制,以提高服務的可用性和韌性。

程式碼範例:逾時和重試機制

import requests
from urllib3.exceptions import TimeoutError

def request_with_retry(url, max_retries=3, timeout=5):
    for attempt in range(max_retries):
        try:
            response = requests.get(url, timeout=timeout)
            response.raise_for_status()
            return response
        except (requests.exceptions.RequestException, TimeoutError) as e:
            if attempt < max_retries - 1:
                continue
            else:
                raise

#### 內容解密:
此範例展示了一個簡單的逾時和重試機制實作其中 `request_with_retry` 函式會對指定的 URL 傳送 GET 請求如果請求失敗或逾時會進行最多三次的重試逾時時間設定為 5這個機制可以避免因暫時性網路問題或服務不可用而導致的請求失敗

1. **`requests.get(url, timeout=timeout)`**傳送 GET 請求並設定逾時時間
2. **`response.raise_for_status()`**檢查請求是否成功如果傳回的 HTTP 狀態碼表示錯誤4xx 或 5xx),則丟擲異常
3. **`except (requests.exceptions.RequestException, TimeoutError) as e:`**捕捉請求過程中可能丟擲的異常包括網路錯誤和逾時錯誤
4. **`if attempt < max_retries - 1:`**如果當前重試次數未達到最大重試次數則繼續下一次重試
5. **`else: raise`**如果重試次數已達上限仍失敗則將異常上拋由上層處理

 #### 電路斷路器狀態轉換
```plantuml
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 內容解密

rectangle "Failure" as node1
rectangle "Timeout" as node2
rectangle "Success" as node3

node1 --> node2
node2 --> node3

@enduml

Istio 監控與追蹤工具詳解

Istio 提供多種預裝工具來幫助使用者監控服務並追蹤請求。在本章中,我們將深入介紹 Grafana 和 Jaeger 這兩款工具,它們在監控服務行為方面發揮著關鍵作用。

使用 Prometheus 和 Grafana 進行指標監控

Grafana 是一款開源的分析與監控平台,能夠使用不同的資料來源並以各種圖表形式進行視覺化展示。Istio 安裝的 Grafana 例項已預先組態好儀錶板,並自動使用 Prometheus 作為資料來源。Prometheus 負責從以下端點抓取指標:

  • istio-mesh:由 Mixer 生成的所有指標
  • envoy:由 Envoy 代理生成的指標,該代理執行在每個服務旁邊
  • mixer:特定於 Mixer 的指標,用於監控 Mixer 本身

首先,需要手動安裝 Prometheus、Grafana 和 Jaeger。以安裝 Prometheus 為例,執行以下命令:

$ kubectl apply -f samples/addons/prometheus.yaml

等待 Prometheus Pod 啟動後,可以使用 istioctl dashboard prometheus 命令開啟 Prometheus 儀錶板。

接著,安裝 Grafana:

$ kubectl apply -f samples/addons/grafana.yaml

使用 istioctl dashboard grafana 命令開啟 Grafana 儀錶板。

Grafana 儀錶板詳解

Istio 自動建立多個 Grafana 儀錶板,用於監控不同層面的服務行為。主要的儀錶板包括:

  • Istio Service Dashboard:顯示服務的詳細圖表和遙測資料
  • Istio Workload Dashboard:顯示工作負載的詳細圖表和遙測資料
  • Istio Mesh Dashboard:顯示服務網格的整體概覽,包括延遲、成功率和請求量等
  • Istio Performance Dashboard:顯示 Istio 元件的效能相關圖表
  • Istio Mixer Dashboard:顯示 Mixer 元件的資源使用情況
  • Istio Control Plane Dashboard:顯示控制平面的資源使用情況

使用 Kiali 提升服務網格可觀測性

Kiali 是一個專為 Istio 設計的視覺化工具,能夠清晰地展示服務網格的拓撲結構及其健康狀態。安裝 Kiali 的命令如下:

$ kubectl apply -f samples/addons/kiali.yaml

使用 istioctl dashboard kiali 開啟 Kiali 儀錶板。

Kiali 功能詳解

Kiali 提供多個檢視來展示服務網格的不同層面,包括:

  • Graph:展示服務之間的拓撲關係和流量流向
  • Applications, Workloads 和 Services:提供不同層面的資源檢視
  • Istio Config:展示 Istio 組態資源的概覽和詳細資訊,協助排查組態錯誤

服務彈性與可觀察性:Kiali、Jaeger 與 Istio 的應用

在微服務架構中,服務彈性(Service Resiliency)是確保系統穩定執行的關鍵要素。Istio 作為一個領先的服務網格(Service Mesh)解決方案,提供了多項功能來增強服務的可觀察性、可管理性和彈性。本文將探討如何利用 Kiali 和 Jaeger 實作服務的可觀察性,並介紹 Istio 的彈性功能,包括超時(Timeout)、重試(Retry)和斷路器(Circuit Breaker)。

使用 Kiali 進行服務監控與管理

Kiali 是 Istio 的一個重要元件,提供了一個視覺化的介面來監控和管理服務網格內的服務互動。透過 Kiali,我們可以輕鬆地檢視服務的拓撲結構、健康狀態、流量分佈等資訊。

Kiali 的主要功能

  1. 服務拓撲圖: Kiali 可以生成服務拓撲圖,直觀地展示服務之間的呼叫關係。
  2. 流量監控: 實時監控服務之間的流量,包括請求量、成功率、延遲等指標。
  3. 組態驗證: 驗證 Istio 組態的有效性,幫助排查組態錯誤。
  4. 流量管理: 支援建立匹配路由、權重路由、暫停流量等操作,簡化了流量管理的複雜度。

分散式追蹤:Jaeger 的應用

Jaeger 是一個開源的分散式追蹤系統,與 Istio 整合後,可以提供端對端的請求追蹤能力,幫助我們理解複雜的服務呼叫鏈路,定位效能瓶頸。

Jaeger 的使用步驟

  1. 安裝 Jaeger: 透過 kubectl apply -f samples/addons/jaeger.yaml 命令安裝 Jaeger。
  2. 存取 Jaeger UI: 使用 istioctl dashboard jaeger 命令開啟 Jaeger 的 Web 介面。
  3. 追蹤分析: 在 Jaeger UI 中,可以根據不同的條件篩選追蹤資料,並深入分析每個請求的呼叫鏈路和耗時情況。

為了使服務能夠被 Jaeger 追蹤,需要在服務程式碼中傳播特定的 HTTP Header,例如 x-request-idx-b3-traceid 等。以下是一個程式碼示例,展示瞭如何在 Hello Web 服務中處理這些 Header:

function getForwardHeaders(req) {
  var headers = {};
  for (var i = 0; i < 7; i++) {
    var traceHeader = traceHeaders[i],
        value = req.get(traceHeader);
    if (value) {
      headers[traceHeader] = value;
    }
  }
  const useragent = req.get('user-agent');
  headers['user-agent'] = useragent;
  return headers;
}

const traceHeaders = [
  'x-request-id',
  'x-b3-traceid',
  'x-b3-spanid',
  'x-b3-parentspanid',
  'x-b3-sampled',
  'x-b3-flags',
  'x-ot-span-context',
];

// 在呼叫下游服務時傳遞 Header
const headers = getForwardHeaders(req);
axios.get(serviceUrl, { headers: headers, timeout: 5000 })

詳細解說

此段程式碼主要功能是提取並轉發HTTP請求中的特定追蹤標頭,以確保請求在不同服務間傳遞時能夠保持一致的追蹤上下文。首先定義了一個getForwardHeaders函式,用於從當前請求中提取特定的追蹤相關的HTTP標頭,並將它們新增到一個新的headers物件中,以便在後續的請求中轉發。這些標頭包括x-request-idx-b3-traceid等,用於實作分散式追蹤功能。同時,該函式也保留了原始請求中的user-agent標頭,以保持客戶端資訊的一致性。在實際發起對下游服務的請求時,這些處理後的headers會被新增到axios請求組態中,從而確保下游服務能夠取得到必要的追蹤資訊。如此一來,便能在Jaeger等分散式追蹤工具中完整地記錄和分析整個請求鏈路的詳細資訊。

Istio 的彈性功能

Istio 提供了一系列彈性功能,包括超時、重試和斷路器,無需修改應用程式碼即可實作。

請求超時

透過在 VirtualService 中組態 timeout 欄位,可以為特定的服務呼叫設定超時時間。例如,為 greeter 服務的 v3 版本設定 0.5 秒的超時:

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: 0.5s

詳細解說

此YAML組態定義了一個名為greeter-service的VirtualService,用於控制對greeter-service主機的HTTP流量。該組態指定了將所有HTTP流量路由到目標主機greeter-service.default.svc.cluster.local的3000埠,並且特別指定了使用v3子集版本。同時,該路由規則設定了0.5秒的超時時間,這意味著任何超過0.5秒仍未完成的請求將被視為失敗並終止。此組態有效地對greeter-servicev3版本實施了超時控制,增強了系統的容錯能力和回應速度。