「故障注入 Sidecar「——爲您的微服務注入故障以驗證集羣性能! 因爲導師和實驗室師兄們的科研須要,本人專門以 Sidecar
的模式設計了一個用於錯誤注入的微服務模塊。該模塊能夠與任何微服務應用共同部署運行,爲其模擬cpu、內存等錯誤。 本項目的 Github
地址: https://github.com/iscas-micr...
個人聯繫方式: leontian1024@gmail.com || 或直接留言 歡迎您提出問題批評指點!
目前,本人正在中科院軟件所的微服務研究組從事部分研究工做。因爲本人所在科研小組的研究內容( 微服務自動擴縮容相關 ),須要常常使微服務應用處於"高 CPU 利用率" 和 "高內存使用"的狀態。所以,爲了方便導師和實驗室的各位師兄進行實驗,本人特意開發了一個能夠注入進 Pod 中的錯誤注入容器,來模擬上述的高負載狀態。node
導師和師兄們使用後對個人工做給予了確定,所以我準備將開發過程和簡單使用方法寫成文章作個記錄( 也就是本文 ),一來方便本身往後工做學習,二來也方便有相似實驗需求的其餘同仁們使用這個小項目,爲你們的研究節省時間。更具體的安裝和使用方法,能夠移步本項目 Github 的代碼倉庫,其中有很是詳細的說明。git
什麼是微服務中的"Sidecar 運行模式?"github
上圖: 以 Sidecar 模式部署並運行的微服務單元
Sidecar 運行模式是最近兩年比較火的一種微服務部署和運行方法,它由目前流行的 ServiceMesh(服務網格) 架構推廣而來。docker
具體而言,Sidecar 運行模式是一種"將不屬於業務應用的功能以獨立的容器運行於業務容器旁邊",在 K8s 中表現出的樣子就是將具備不一樣功能的模塊封裝成不一樣的鏡像,並以不一樣的容器運行在同一個 Pod 中。這種說法很是形象,由於 Sidecar 這個單詞的本意就是三輪摩托側面的"跨鬥",這裏形容獨立於業務應用但又與業務應用部署在一塊兒很是合適。api
上圖: Sidecar ,中文意思爲摩托車的跨鬥,不禁讚歎命名的很是生動
本項目的錯誤注入模塊也採用了 Sidecar 這種設計思想,將用於模擬 CPU、內存等故障的模塊獨立封裝成一個鏡像,並在 Pod 啓動時以 Sidecar 的形式運行在主業務容器旁邊。這樣,不用它時他就會安安靜靜地當個美男子,徹底不用擔憂它會影響到正常業務的運行;一旦須要它模擬錯誤產生,因爲與業務容器同處於一個 Pod 之中(而 K8s 又以 Pod 爲基本單元),所以他模擬出的錯誤亦被 K8s 集羣視爲業務應用所在 Pod 產生而被監測到。網絡
上圖: Pod 中的每一個容器都有本身的端口映射到外部主機,所以不會相互影響
本項目在設計之初是採用「在容器內修改環境變量」的方式對容器注入故障的,但事實證實這種方法太low,並且很是麻煩。所以在後續設計和實現中採用了目前較爲流行的經過 REST API 傳遞 POST 請求的方式使容器模擬錯誤,這樣就極大地方便了師兄們展開實驗,並且也能夠模擬出「微服務間調用而產生錯誤」的場景( 上游服務調用錯誤注入的 API 而模擬下游服務產生錯誤 )。架構
此外,本來該項目的實現是單進程的,故每注入一個錯誤都要等待錯誤結束後才能得到應答並注入下一個錯誤,這十分不利於實驗的進行。所以在後面咱們改成了多進程運行,即每當一個錯誤產生時,程序都會創建一個子進程用於運行錯誤故障,而原來的進程則馬上產生注入是否成功的應答並繼續監聽相應的服務端口,從而知足應答實時彙報和多種錯誤同時注入的功能需求。app
上圖: 該程序的主要運行流程-以 「A 進程監聽服務端口」的狀態爲起點
本應用以 Web 服務的方式運行,並封裝爲鏡像保存於 DockerHub 上。所以使用以前須要先以容器的形式運行鏡像。以 docker 命令運行本應用的參考命令以下所示:curl
# 使用 docker 命令簡單測試該應用( 測試版本爲 docker 18.03-ce ) docker run --rm -it -d --name fault-injection-server -p 5000:5000 xinyaotian/micro-fault-injection:1.0.0
待容器就緒後,訪問您啓動該容器的主機 IP 的 5000 號端口,若是出現了使用指引界面,就代表您的服務啓動成功,能夠參考使用說明進行錯誤注入了。ide
上圖: 爲了方便師兄們和你們的使用, 特意在服務首頁製做了簡易的使用方法指引, 爲你們節省查 Github 文檔的時間
本項目主要支持四種故障類型: cpu、內存、磁盤和網絡,均經過 POST 請求向 /fault-inject 搭配相應參數進行注入。具體的注入方法以下所示( 注意更改 IP 和端口號 ):
1.注入 CPU 故障
# fault_type=cpu 指定錯誤故障類型(此處爲 cpu 類型) # thread_num=4 觸發該錯誤的線程數(此處爲 4 個線程) # duration=15 故障持續時間,單位爲秒(此處爲 15 秒) curl -X POST -d 'fault_type=cpu&thread_num=4&duration=15' http://localhost:5000/fault-inject
2. 注入內存故障
# fault_type=mem 指定錯誤故障類型(此處爲 mem 類型) # mem_size=120M 指定內存泄露的數值(此處爲 120M ,注意 M 不能省略) # thread_num=4 觸發該錯誤的線程數(此處爲 4 個線程) # duration=15 故障持續時間,單位爲秒(此處爲 15 秒) curl -X POST -d 'fault_type=mem&mem_size=120M&thread_num=4&duration=15' http://localhost:5000/fault-inject
3.注入磁盤故障
# fault_type=disk 指定錯誤故障類型(此處爲 disk 類型) # io_times=4 # duration=15 故障持續時間,單位爲秒(此處爲 15 秒) curl -X POST -d 'fault_type=disk&io_times=4&duration=15' http://localhost:5000/fault-inject
4.注入網絡故障
# fault_type=net 指定錯誤故障類型(此處爲 net 類型) # net_port=100 curl -X POST -d 'fault_type=net&net_port=100' http://localhost:5000/fault-inject
本項目的鏡像將做爲本來微服務應用的 Sidecar 獨立部署運行, 所以在 K8s 環境中其應該與業務應用部署於同一個 Pod 之中。
您能夠利用 yaml 啓動一個單獨的 Pod 來初步體驗一下這個應用。快讀啓動的 yaml 以下所示( Istio 一樣能夠這樣寫, K8s 版本爲 1.13.1, Istio 版本爲 1.0.6 ):
--- # 爲 fault injection 建立 service 分配端口 # --- apiVersion: v1 kind: Service metadata: name: single-fault-injection namespace: default spec: selector: # deployment identifier # 這個標籤要與 deployment 中相對應 app: fault-injection ports: - protocol: TCP port: 5000 # 容器內端口爲 5000 nodePort: 30050 # 映射至主機的 30050 端口 type: NodePort # 映射方式爲 NodePort --- # 將該模塊做爲一個獨立的 Pod 在 K8s 上進行部署 # --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: single-fault-injection namespace: default spec: replicas: 1 template: metadata: labels: # svc identifier # 這個標籤要與 service 中相對應 app: fault-injection spec: containers: # 錯誤注入模塊的 container - name: fault-injection-container image: xinyaotian/micro-fault-injection:1.0.0 imagePullPolicy: IfNotPresent ports: - containerPort: 5000 # 該容器的資源限制, 錯誤注入可以使其達到峯值 # resources: limits: cpu: "0.4" memory: 128Mi
若是您但願以 Sidecar 的形式將本應用部署在其餘微服務的 Pod 之中一樣可行,這也是本項目的設計初衷。在 K8s 環境下部署和啓動的 yaml 以下所示意( Istio 一樣能夠這樣寫, K8s 版本爲 1.13.1, Istio 版本爲 1.0.6 ):
--- # 爲 fault injection 建立 service 分配端口 # --- apiVersion: v1 kind: Service metadata: name: your-microapp-with-faultinjection namespace: default spec: selector: # deployment identifier # 這個標籤要與 deployment 中相對應 app: sidecar-fault-injection ports: - protocol: TCP port: 5000 nodePort: 30050 type: NodePort --- # 相應的 deployment 配置( 與原應用配置在一塊兒 ) --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: your-microapp-with-faultinjection namespace: default spec: replicas: 1 template: metadata: labels: # svc identifier # 這個標籤要與 service 中相對應 app: sidecar-fault-injection spec: containers: # 你原來應用的 container 信息 - name: your-micro-app image: your-docker-name/project:1.0 imagePullPolicy: IfNotPresent env: - name: PATH_VALUE value: "example" ports: - containerPort: 80 # ------------------- # # Sidecar 錯誤注入模塊的 container - name: fault-injection-sidecar image: xinyaotian/micro-fault-injection:1.0.0 imagePullPolicy: IfNotPresent ports: - containerPort: 5000 # ------------------- # ---
在我本身的實驗集羣上,利用 Istio 啓動該服務,並對其注入內存故障後,能夠在 Grafana 監控面板上清晰地看到微服務 Pod 的內存忽高忽低,很是有趣。 錯誤注入的結果以下圖所示。
上圖: 注入內存故障後, 我本身的 Istio 集羣監測微服務資源面板的可視化展示
項目到這裏已經知足了實驗室內師兄們絕大部分的科研需求。在以後的迭代中預計還會加入故障的產生速率( 例如 CPU 使用率會呈線性或指數上漲等 ),相應的 API 也會採用向前兼容的形式進行擴充( 添加更多的可選參數,不填則設置爲默認值 ),以確保這個版本或以前版本使用者的代碼無需改變而可繼續使用後續版本。
此外,簡單的用戶控制面板也會在後續版本中開發。經過提供的用戶界面,使用者能夠在界面上輸入參數並經過按鈕進行錯誤注入,而再也不僅僅經過發送 POST 請求( 雖然底層原理仍是本地請求 )。相信用戶界面會在彙報演示時爲導師和師兄們帶來諸多便利。
本項目主要以 Sidecar 的方式開發了一個用於錯誤注入的實驗鏡像,並經過在 docker 和 k8s 上運行從而達到對微服務單元注入故障的目標,爲研究集羣自動擴縮容、微服務自動擴縮容等課題提供了前提保障和研究條件。
感謝您的閱讀,若是您對這個項目有什麼更好的建議,或指出哪裏設計有問題,我都會很是歡迎,洗耳恭聽。很是但願於讀完本文的您進行交流,歡迎您在下方留言。
若是您的科研團隊也有相似需求,也很是歡迎與咱們進行合做,並對針對本項目提出寶貴的改進意見。