背景
故障注入
故障注入技術最初是在航空航天領域中開發的,用于模拟和測試飛機、飛彈等複雜系統的可靠性。後來,這項技術逐漸被應用到其他領域,包括計算機軟體、汽車、醫療裝置等。
随着網際網路和軟體系統的快速發展,複雜度和規模不斷擴大。是以,系統中的故障和異常在所難免。為了確定系統在遇到故障時能夠保持穩定運作并盡快恢複,開發人員和運維團隊需要提前預測和處理潛在的故障。故障注入慢慢地在計算機軟體中得到應用。
故障注入的重要性在于它可以幫助開發人員更好地了解系統的行為,并确定哪些部分可能存在缺陷。通過模拟各種可能的故障情況,開發人員可以評估系統在不同條件下的響應能力,并将這些資訊用于改進軟體設計和實作。
故障注入的功能
- • 使開發和測試人員友善地進行可靠性測試,發現潛在的問題并優化系統設計,進而提升系統的健壯性。
- • 幫助驗證系統的異常和故障處理機制是否有效,確定系統在遇到故障時能夠正确地執行故障處理政策。
- • 服務降級是在系統發生故障時,暫時關閉部分功能以確定整體的可用性。故障注入可用于評估服務降級政策,通過模拟故障場景檢驗服務降級的實際表現。
服務網格
服務網格是一種架構模式,用于處理分布式系統中的服務間通信和服務治理問題。服務網格通常由一組網絡代理和服務間通信協定組成,用于管理和控制服務之間的通信。服務網格可以提供諸如服務發現、負載均衡、安全認證、流量控制、故障恢複等功能,以幫助開發人員和運維人員管理分布式系統的複雜性和可靠性。
Flomesh 服務網格
Flomesh 服務網格使用可程式設計代理 Pipy[1] 為核心提供東西、南北向的流量管理和豐富的服務治理能力。通過基于 L7 的流量管理能力,突破計算環境間的網絡隔離,建立一個虛拟的平面網絡,使不同計算環境中應用可以互相通信,實作覆寫多叢集的“大網格”。
故障注入與服務網格
服務網格中的代理對服務的流量進行攔截,可以實作流量的控制。攔截到服務流量時,可以通過注入故障或者異常來測試服務的容錯性和健壯性。比如可以通過服務網格來模拟服務的延遲、錯誤響應等等。
當我們使用傳統的故障注入時,通常需要在應用程式中嵌入特定的代碼或者 SDK 來實作對應用程式行為的修改和控制,比如 Chaos Monkey[2]。而由于服務網格的網絡代理與應用本身的天然解耦合,可以實作無侵入的故障注入。這種無侵入的故障注入不僅可以減少對應用程式的影響,還可以提高故障注入的靈活性和可靠性。
今天就為大家來介紹如何使用 Flomesh 服務網格的故障注入功能。
Flomesh 服務網格的故障注入
Flomesh 服務網格秉持着簡單、易用的設計原則,提供滿足使用者的最小功能集。故障注入功能并未包含在其中,但通過靈活的 插件擴充功能[3] 可以輕松地為服務網格擴充新的功能,這個在之前的文章 使用插件擴充服務網格 中也有過詳細介紹。
這下面的示範中,我們将使用 故障注入插件[4] 實作對目标服務的故障注入。首先我們看一下可注入的故障類型:
- • 延遲響應:在服務調用時,為一定比例的響應人為地加入的延遲,模拟目标服務的不穩定來測試服務的容錯能力、優化負載均衡政策等。
- • 終止響應:模拟服務響應異常終止的情況,進而測試系統的容錯性和健壯性。比如驗證重試機制、降級能力等等。
功能配置
- •
故障類型及配置config
- •
:終止響應時的響應狀态碼,比如httpStatus
、400
、501
503
- •
:終止的百分比,percentage.value
表示對0.5
的響應會被終止50%
- •
:設定延遲的時長,fixedDelay
表示為響應假如 1 秒鐘的延遲1s
- •
:延遲的百分比,percentage.value
表示對0.5
的響應注入延遲50%
- •
延遲delay
- •
終止abort
- •
表示這個配置是插件plugin:
的配置http-fault-injection
- •
: 表示配置生效的負載。比如命名空間destinationRefs
下的 Servicepipy
pipy-ok
kind: PluginConfig
apiVersion: plugin.flomesh.io/v1alpha1
metadata:
name: http-fault-injection-config
namespace: pipy
spec:
config:
delay:
percentage:
value: 0.5
fixedDelay: 1s
abort:
percentage:
value: 0.5
httpStatus: 400
plugin: http-fault-injection
destinationRefs:
- kind: Service
name: pipy-ok
namespace: pipy
示範
建立叢集
export INSTALL_K3S_VERSION=v1.23.8+k3s2
curl -sfL https://get.k3s.io | sh -s - --disable traefik --disable servicelb --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config
安裝服務網格
下載下傳 CLI。
system=$(uname -s | tr [:upper:] [:lower:])
arch=$(dpkg --print-architecture)
release=v1.3.3
curl -L https://github.com/flomesh-io/osm-edge/releases/download/${release}/osm-edge-${release}-${system}-${arch}.tar.gz | tar -vxzf -
./${system}-${arch}/osm version
cp ./${system}-${arch}/osm /usr/local/bin/
安裝服務網格。
osm install
部署示例應用
kubectl create namespace curl
osm namespace add curl
kubectl apply -n curl -f https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.3/manifests/samples/plugins/curl.yaml
kubectl create namespace pipy
osm namespace add pipy
kubectl apply -n pipy -f https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.3/manifests/samples/plugins/pipy-ok.pipy.yaml
# Wait for pods to be up and ready
sleep 2
kubectl wait --for=condition=ready pod -n curl -l app=curl --timeout=180s
kubectl wait --for=condition=ready pod -n pipy -l app=pipy-ok -l version=v1 --timeout=180s
kubectl wait --for=condition=ready pod -n pipy -l app=pipy-ok -l version=v2 --timeout=180s
驗證服務通路。
curl_client="$(kubectl get pod -n curl -l app=curl -o jsonpath='{.items[0].metadata.name}')"
kubectl exec ${curl_client} -n curl -c curl -- curl -ksi http://pipy-ok.pipy:8080 ; echo "";
你将會看到如下的響應,多次請求可以發現 v1 和 v2 版本的服務輪流響應。
HTTP/1.1 200 OK
content-length: 20
connection: keep-alive
Hi, I am PIPY-OK v1!
啟用插件特性
預設情況下,服務網格是沒有開啟插件特性的。可以通過下面的指令開啟:
kubectl patch meshconfig osm-mesh-config -n osm-system -p '{"spec":{"featureFlags":{"enablePluginPolicy":true}}}' --type=merge
故障注入插件
插件的應用包含了兩個部分:
- • 聲明插件:也就是建立插件的過程。插件聲明後,才可以被其他資源引用。
- • 配置插件鍊:服務治理的功能分布于流量處理的各個階段,比如 4 層的處理、7 層的路由、負載均衡等等。插件鍊則是對插件進行編排,指定其工作的階段以及作用的資源。
聲明插件
執行下面的聲明插件。插件是使用 PipyJS[5] 開發的,對故障注入插件感興趣的同學可以通路 Github 浏覽 源碼[6]。
kubectl apply -f https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.3/manifests/samples/plugins/fault-injection.yaml
配置插件鍊
插件鍊
http-fault-injection-chain
:
- •
:插件鍊資源名稱metadata.name
http-fault-injection-chain
- •
spec.chains
- •
:所處的插件鍊名稱,4 個插件鍊之一,這裡是name
也就是出站流量的 HTTP 協定處理階段。inbound-http
- •
:要插入到插件鍊的插件清單,這裡将plugins
插入到插件鍊中。http-fault-injection
- •
:插件鍊作用的目标,使用的是 Kubernetes 标簽選擇器[7] 方案。spec.selectors
- •
:pod 選擇器,選擇标簽podSelector
的 pod。app=pipy-ok
- •
:命名空間選擇器,選擇命名空間被網格納管的命名空間,即namespaceSelector
openservicemesh.io/monitored-by=osm
kubectl apply -f - <<EOF
kind: PluginChain
apiVersion: plugin.flomesh.io/v1alpha1
metadata:
name: http-fault-injection-chain
namespace: pipy
spec:
chains:
- name: inbound-http
plugins:
- http-fault-injection
selectors:
podSelector:
matchLabels:
app: pipy-ok
matchExpressions:
- key: app
operator: In
values: ["pipy-ok"]
namespaceSelector:
matchExpressions:
- key: openservicemesh.io/monitored-by
operator: In
values: ["osm"]
EOF
此時,我們執行前面指令進行驗證,可以發現服務扔可正常通路。這是因為還缺少故障注入的配置。
配置注入故障
注入延遲
這裡我們配置為
50%
的響應加上
2s
的延遲。
kubectl apply -n pipy -f - <<EOF
kind: PluginConfig
apiVersion: plugin.flomesh.io/v1alpha1
metadata:
name: http-fault-injection-config
namespace: pipy
spec:
config:
delay:
percentage:
value: 0.5
fixedDelay: 2s
plugin: http-fault-injection
destinationRefs:
- kind: Service
name: pipy-ok
namespace: pipy
EOF
為了友善看到效果請求前後我們列印下目前的時間。多次請求後可以發現一半的請求響應時間超過 5s。
date; kubectl exec ${curl_client} -n curl -c curl -- curl -ksi http://pipy-ok.pipy:8080 ; echo ""; date
Mon Apr 3 11:21:58 UTC 2023
HTTP/1.1 200 OK
content-length: 20
connection: keep-alive
Hi, I am PIPY-OK v1!
Mon Apr 3 11:22:00 UTC 2023
終結響應
接下來我們修改插件配置,去掉
delay
的配置,為
abort
添加配置:50% 的情況下傳回
500
的響應。
kubectl apply -n pipy -f - <<EOF
kind: PluginConfig
apiVersion: plugin.flomesh.io/v1alpha1
metadata:
name: http-fault-injection-config
namespace: pipy
spec:
config:
abort:
percentage:
value: 0.5
httpStatus: 500
plugin: http-fault-injection
destinationRefs:
- kind: Service
name: pipy-ok
namespace: pipy
EOF
經過驗證,50% 的響應會傳回狀态碼
500
。
HTTP/1.1 500 Internal Server Error
content-length: 0
connection: keep-alive
總結
故障注入技術作為一種重要的測試方法,在軟體工程中已經得到廣泛的應用。随着雲計算和微服務架構的普及,故障注入在分布式系統和服務網格中的應用也越來越受到重視。結合服務網格技術,故障注入可以做到更加的自動化和智能化,良好相容更多的應用場景。
通過擴充故障注入功能,我們再一次體驗了可擴充服務網絡的靈活性。功能可擴充的服務網格通過更強的可定制性、更好更靈活的擴充性,可以滿足使用者多元的需求、複雜的場景。
引用連結
[1]
Pipy: https://github.com/flomesh-io/pipy
[2]
Chaos Monkey: https://github.com/Netflix/chaosmonkey
[3]
插件擴充功能: https://osm-edge-docs.flomesh.io/docs/guides/operating/plugins/
[4]
故障注入插件: https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.3/manifests/samples/plugins/fault-injection.yaml
[5]
PipyJS: https://flomesh.io/pipy/docs/en/reference/pjs
[6]
源碼: https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.3/manifests/samples/plugins/fault-injection.yaml
[7]
Kubernetes 标簽選擇器: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/