大數據

ChaosBlade:從零開始的混沌工程(五)

前言

上篇文章中,我們介紹瞭如何使用 ChaosBlade Operator 對 node 資源進行混沌實驗。從本章將繼續對 Kubernetes Container 資源的混沌實驗進行講解,同時也配套了 katacode 交互式教程,讀者可用通過 katacode,在瀏覽器上操作真實的 Kubernetes 和 ChaosBlade,同時本篇也是系列文章的倒數第二篇,實踐內容的最後一篇。

chaosblade.io 官網已經正式上線,在官網的互動教程模塊,也可以找到 ChaosBlade 的 KataCoda 教程,目前官網由我維護,有任何問題,歡迎在 ISSUE 中進行反饋。

KataCoda 教程:《ChaosBlade Container 實驗場景》

地址:https://katacoda.com/guoxudong/courses/chaosblade/chaosblade-container-experimentt

實驗對象:Container

Pod 由一個或多個容器(Container)組成。容器(Container)是一種用來打包已經編譯好的代碼以及運行時需要的各個依賴項的技術。您運行的每個容器都是可以重複運行的;包含依賴項的標準化意味著您在任何地點運行它都會得到相同的結果。

Container 實驗場景

之前的文章,本篇默認已安裝 guestbook 應用和 ChaosBlade Operator。

container 資源自身的場景

刪除 container

實驗目標:刪除 chaosblade 命名空間下,Pod 名為 guestbook-7b87b7459f-cqkq2 中 container id 是 c6cdcf60b82b854bc4bab64308b466102245259d23e14e449590a8ed816403ed 的容器。

開始實驗

remove_container_by_id.yaml 內容:

apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
  name: remove-container-by-id
spec:
  experiments:
  - scope: container
    target: container
    action: remove
    desc: "remove container by id"
    matchers:
    - name: container-ids
      value: ["c6cdcf60b82b854bc4bab64308b466102245259d23e14e449590a8ed816403ed"]
      # pod name
    - name: names
      value: ["guestbook-7b87b7459f-cqkq2"]
    - name: namespace
      value: ["chaosblade"]

獲取 container 名稱:

$ kubectl get pod guestbook-7b87b7459f-cqkq2 -o custom-columns=CONTAINER:.status.containerStatuses[0].name,ID:.status.containerStatuses[0].containerID

修改 remove_container_by_id.yaml 中的 container-idsnames

執行命令,開始實驗:

$ kubectl apply -f remove_container_by_id.yaml

查看實驗狀態

執行 kubectl get blade remove-container-by-id -o json 命令,查看實驗狀態。

觀測結果

查看容易 ID,可以看到容器ID發生了變化,舊容器被刪除了,拉起了新容器。

刪除 container

停止實驗

執行命令:kubectl delete -f remove_container_by_id.yaml

或者直接刪除 blade 資源:kubectl delete blade remove-container-by-id

container 內CPU負載場景

實驗目標:指定 chaosblade 命名空間下 Pod 名為 guestbook-7b87b7459f-cqkq2,container id 為 2ff814b246f86,使其 CPU 負載為 100%。

實驗準備

由於使用 helm 安裝的 guestbook 沒有對資源進行限制,進行負載實驗的話,會導致整個節點的故障,所以在實驗之前需要對資源進行限制

$ kubectl patch deployment redis-slave --patch '{"spec": {"template": {"spec": {"containers": [{"name": "redis-slave","resources": {"limits":{"cpu":"300m","memory":"512Mi"} }}]}}}}'

開始實驗

increase_container_cpu_load_by_id.yaml 內容:

apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
  name: increase-container-cpu-load-by-id
spec:
  experiments:
  - scope: container
    target: cpu
    action: fullload
    desc: "increase container cpu load by id"
    matchers:
    - name: container-ids
      value:
      - "5ad91eb49c1c6f8357e8d455fd27dad5d0c01c5cc3df36a3acdb1abc75f68a11"
    - name: cpu-percent
      value: ["100"]
      # pod names
    - name: names
      value: ["redis-slave-55d8c8ffbd-jd8sm"]
    - name: namespace
      value: ["chaosblade"]

獲取 container 名稱:

$ kubectl get pod redis-slave-55d8c8ffbd-jd8sm -o custom-columns=CONTAINER:.status.containerStatuses[0].name,ID:.status.containerStatuses[0].containerID

修改 increase_container_cpu_load_by_id.yaml 中的 container-idsnames

查看實驗狀態

執行命令:kubectl get blade increase-container-cpu-load-by-id -o json,查看實驗狀態。

觀測結果

可從監控系統觀測到結果

container 內CPU負載場景

停止實驗

執行命令:kubectl delete -f increase_container_cpu_load_by_id.yaml

或者直接刪除 blade 資源:kubectl delete blade increase-container-cpu-load-by-id

container 內網絡實驗場景

該場景與 Pod 實驗場景類似。

container 網絡延遲場景

實驗目標:對 chaosblade 命名空間中,對 redis-master-68857cd57c-hknb6 Pod 中 container id 是 02655dfdd9f0f712a10d63fdc6721f4dcee0a390e37717fff068bf3f85abf85e 的容器的 6379 端口添加 3000 毫秒訪問延遲,延遲時間上下浮動 1000 毫秒。

實驗參數

參數 類型 說明
destination-ip string 目標 IP. 支持通過子網掩碼來指定一個網段的IP地址, 例如 192.168.1.0/24. 則 192.168.1.0~192.168.1.255 都生效。你也可以指定固定的 IP,如 192.168.1.1 或者 192.168.1.1/32,也可以通過都號分隔多個參數,例如 192.168.1.1,192.168.2.1。
exclude-port string 排除掉的端口,默認會忽略掉通信的對端端口,目的是保留通信可用。可以指定多個,使用逗號分隔或者連接符表示範圍,例如 22,8000 或者 8000-8010。 這個參數不能與 --local-port 或者 --remote-port 參數一起使用。
exclude-ip string 排除受影響的 IP,支持通過子網掩碼來指定一個網段的IP地址, 例如 192.168.1.0/24. 則 192.168.1.0~192.168.1.255 都生效。你也可以指定固定的 IP,如 192.168.1.1 或者 192.168.1.1/32,也可以通過都號分隔多個參數,例如 192.168.1.1,192.168.2.1。
interface string 網卡設備,例如 eth0 (必要參數)。
local-port string 本地端口,一般是本機暴露服務的端口。可以指定多個,使用逗號分隔或者連接符表示範圍,例如 80,8000-8080。
offset string 延遲時間上下浮動的值, 單位是毫秒。
remote-port string 遠程端口,一般是要訪問的外部暴露服務的端口。可以指定多個,使用逗號分隔或者連接符表示範圍,例如 80,8000-8080。
time string 延遲時間,單位是毫秒 (必要參數)。
force 強制覆蓋已有的 tc 規則,請務必在明確之前的規則可覆蓋的情況下使用。
ignore-peer-port 針對添加 --exclude-port 參數,報 ss 命令找不到的情況下使用,忽略排除端口。
timeout string 設定運行時長,單位是秒,通用參數。

開始實驗

delay_container_network_by_id.yaml 內容:

apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
  name: delay-container-network-by-id
spec:
  experiments:
  - scope: container
    target: network
    action: delay
    desc: "delay container network by container id"
    matchers:
    - name: container-ids
      value:
      - "02655dfdd9f0f712a10d63fdc6721f4dcee0a390e37717fff068bf3f85abf85e"
    - name: names
      value:
      - "redis-master-68857cd57c-hknb6"
    - name: namespace
      value:
      - "chaosblade"
    - name: local-port
      value: ["6379"]
    - name: interface
      value: ["eth0"]
    - name: time
      value: ["3000"]
    - name: offset
      value: ["1000"]

獲取 Pod 名稱和 container id:

$ kubectl get pod redis-master-68857cd57c-hknb6 -o custom-columns=POD_NAME:.metadata.name,CONTAINER:.status.containerStatuses[0].name,ID:.status.containerStatuses[0].containerID

修改 delay_container_network_by_id.yaml 中的 container-idsnames

執行命令,開始實驗:

$ kubectl apply -f delay_container_network_by_id.yaml

查看實驗狀態

執行 kubectl get blade delay-container-network-by-id -o json 命令,查看實驗狀態.

觀測結果

# 獲取實驗 pod ip
$ kubectl get pod -l app=redis,role=master -o jsonpath={.items..status.podIP}
10.42.0.19
# 進入觀測 pod
$ kubectl exec -it redis-slave-55d8c8ffbd-jd8sm bash
# 在 pod 中安裝 telnet
$ apt-get update && apt-get install -y telnet
# 測試時間
$ time echo "" | telnet 10.42.0.19 6379
Trying 10.42.0.19...
Connected to 10.42.0.19.
Escape character is '^]'.
Connection closed by foreign host.

real    0m3.790s
user    0m0.007s
sys     0m0.001s

container 網絡延遲場景

可以看到結果符合預期。

停止實驗

執行命令:kubectl delete -f delay_container_network_by_id.yaml

或者直接刪除 blade 資源:kubectl delete blade delay-container-network-by-id

container 網絡丟包場景

實驗目標:對 chaosblade 命名空間中,對 redis-master-68857cd57c-hknb6 Pod 中 container id 是 02655dfdd9f0f712a10d63fdc6721f4dcee0a390e37717fff068bf3f85abf85e 的容器注入丟包率 100% 的故障,只針對 IP 為 10.42.0.26 的 pod 生效,也就是除 10.42.0.26 以外的 pod 都能正常訪問 redis-master-68857cd57c-hknb6

實驗參數

參數 類型 說明
destination-ip string 目標 IP. 支持通過子網掩碼來指定一個網段的IP地址, 例如 192.168.1.0/24. 則 192.168.1.0~192.168.1.255 都生效。你也可以指定固定的 IP,如 192.168.1.1 或者 192.168.1.1/32,也可以通過都號分隔多個參數,例如 192.168.1.1,192.168.2.1。
exclude-port string 排除掉的端口,默認會忽略掉通信的對端端口,目的是保留通信可用。可以指定多個,使用逗號分隔或者連接符表示範圍,例如 22,8000 或者 8000-8010。 這個參數不能與 --local-port 或者 --remote-port 參數一起使用。
exclude-ip string 排除受影響的 IP,支持通過子網掩碼來指定一個網段的IP地址, 例如 192.168.1.0/24. 則 192.168.1.0~192.168.1.255 都生效。你也可以指定固定的 IP,如 192.168.1.1 或者 192.168.1.1/32,也可以通過都號分隔多個參數,例如 192.168.1.1,192.168.2.1。
interface string 網卡設備,例如 eth0 (必要參數)。
local-port string 本地端口,一般是本機暴露服務的端口。可以指定多個,使用逗號分隔或者連接符表示範圍,例如 80,8000-8080。
percent string 丟包百分比,取值在[0, 100]的正整數 (必要參數)。
remote-port string 遠程端口,一般是要訪問的外部暴露服務的端口。可以指定多個,使用逗號分隔或者連接符表示範圍,例如 80,8000-8080。
force 強制覆蓋已有的 tc 規則,請務必在明確之前的規則可覆蓋的情況下使用。
ignore-peer-port 針對添加 --exclude-port 參數,報 ss 命令找不到的情況下使用,忽略排除端口。
timeout string 設定運行時長,單位是秒,通用參數。

開始實驗

oss_container_network_by_id.yaml 內容:

apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
  name: loss-container-network-by-id
spec:
  experiments:
  - scope: container
    target: network
    action: loss
    desc: "loss container network by container id"
    matchers:
    - name: container-ids
      value:
      - "02655dfdd9f0f712a10d63fdc6721f4dcee0a390e37717fff068bf3f85abf85e"
    - name: names
      value:
      - "redis-master-68857cd57c-hknb6"
    - name: namespace
      value:
      - "chaosblade"
    - name: interface
      value: ["eth0"]
    - name: percent
      value: ["100"]
    - name: timeout
      value: ["60"]
    - name: destination-ip
      value: ["10.42.0.26"]

獲取 pod 名稱和 container id 內容同上。

執行命令,開始實驗:

$ kubectl apply -f loss_container_network_by_id.yaml

查看實驗狀態

執行 kubectl get blade loss-container-network-by-id -o json 命令,查看實驗狀態。

觀測結果

# 獲取實驗 pod ip
$ kubectl get pod -l app=redis,role=master -o jsonpath={.items..status.podIP}
10.42.0.19
# 進入觀測 pod,IP為:10.42.0.26(被設置丟包率 100%)
$ kubectl exec -it redis-slave-55d8c8ffbd-jd8sm bash
# Ping 實驗Pod ip
$ ping 10.42.0.19
PING 10.42.0.19 (10.42.0.19) 56(84) bytes of data.
# 無響應

# 進入觀測 pod,該 pod 未被指定丟包
$ kubectl exec -it redis-slave-55d8c8ffbd-22tsc bash
# Ping 實驗Pod ip
$ ping 10.42.0.19
PING 10.42.0.19 (10.42.0.19) 56(84) bytes of data.
64 bytes from 10.42.0.19: icmp_seq=1 ttl=64 time=0.065 ms
64 bytes from 10.42.0.19: icmp_seq=2 ttl=64 time=0.051 ms
64 bytes from 10.42.0.19: icmp_seq=3 ttl=64 time=0.078 ms
...
# 響應正常

container 網絡丟包場景

這裡在配置中還將 timeout 設置為 60 秒,60 秒後 100% 丟包的情況將會消失,這個配置是為了防止因丟包率設置太高,造成機器無法連接的情況。與其有相似功能的還有 exclude-port,該配置用來指定排除掉的丟包端口。

停止實驗

執行命令:kubectl delete -f loss_container_network_by_id.yaml

或者直接刪除 blade 資源:kubectl delete blade loss-container-network-by-id

container 域名訪問異常場景

實驗目標:本實驗通過修改本地的 hosts,篡改域名地址映射,模擬 container 內域名訪問異常場景。

實驗參數

參數 類型 說明
domain string 域名 (必要參數)
ip string 映射的 ip (必要參數)
timeout string 設定運行時長,單位是秒,通用參數。

開始實驗

tamper_container_dns_by_id.yaml 內容:

apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
  name: tamper-container-dns-by-id
spec:
  experiments:
  - scope: container
    target: network
    action: dns
    desc: "tamper container dns by id"
    matchers:
    - name: container-ids
      value:
      - "02655dfdd9f0f712a10d63fdc6721f4dcee0a390e37717fff068bf3f85abf85e"
    - name: domain
      value: ["www.baidu.com"]
    - name: ip
      value: ["10.0.0.1"]
      # pod names
    - name: names
      value: ["redis-master-68857cd57c-hknb6"]
      # or use pod labels
    - name: namespace
      value: ["chaosblade"]

獲取 pod 名稱和 container id 內容同上。

執行命令,開始實驗:

$ kubectl apply -f tamper_container_dns_by_id.yaml

查看實驗狀態

執行 kubectl get blade tamper-container-dns-by-id -o json 命令,查看實驗狀態.

觀測結果

# 進入實驗 pod
$ kubectl exec -it redis-master-68857cd57c-hknb6 bash
# Ping www.baidu.com
$ ping www.baidu.com
# 無響應

container 域名訪問異常場景

可以看到 Pod 的 /etc/hosts 文件被修改,模擬了 dns 解析異常的場景。

container 內進程場景

殺 container 內指定進程

此實驗會刪除指定容器中的 redis-server 進程。

參數

參數 類型 說明
process string 進程關鍵詞,會在整個命令行中查找
process-cmd string 進程命令,只會在命令中查找
count string 限制殺掉進程的數量,0 表示無限制
signal string 指定殺進程的信號量,默認是 9,例如 --signal 15
timeout string 設定運行時長,單位是秒,通用參數

開始實驗

kill_container_process_by_id.yaml 內容:

apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
  name: kill-container-process-by-id
spec:
  experiments:
  - scope: container
    target: process
    action: kill
    desc: "kill container process by id"
    matchers:
    - name: container-ids
      value:
      - "94bc61ac84fb505f3f89b3ce5e4cc804ea8501ed091940b17b0f492835dc57d1"
    - name: process
      value: ["redis-server"]
    - name: names
      value: ["redis-slave-55d8c8ffbd-4pz8m"]
    - name: namespace
      value: ["chaosblade"]

選擇一個 pod,獲取容器 ID ,修改 kill_container_process_by_id.yaml 中的 container-ids 值。

執行命令,開始實驗:

$ kubectl apply -f kill_container_process_by_id.yaml

查看實驗狀態

執行 kubectl get blade kill-container-process-by-id -o json 命令,查看實驗狀態。

觀測結果

# 開始實驗前查看容器 id
$ kubectl get pod redis-slave-55d8c8ffbd-4pz8m -o custom-columns=POD_NAME:.metadata.name,CONTAINER:.status.containerStatuses[0].name,ID:.status.containerStatuses[0].containerID
POD_NAME                        CONTAINER      ID
redis-slave-55d8c8ffbd-4pz8m   redis-master   docker://bfc9ca01fac33f60d300485f96549644b634f274351df1d4897526451f49e3fb
# 實驗後查看容器 id
$ kubectl get pod redis-slave-55d8c8ffbd-4pz8m -o custom-columns=POD_NAME:.metadata.name,CONTAINER:.status.containerStatuses[0].name,ID:.status.containerStatuses[0].containerID
POD_NAME                       CONTAINER     ID
redis-slave-55d8c8ffbd-4pz8m   redis-slave   docker://94bc61ac84fb505f3f89b3ce5e4cc804ea8501ed091940b17b0f492835dc57d1

殺 container 內指定進程

容器 id 變化,主進程被殺掉後容器進行了重啟,符合實驗逾期。

redis-server 的進程號發生改變,說明被殺掉後,又被重新拉起。

停止實驗

執行命令:kubectl delete -f kill_container_process_by_id.yaml

或者直接刪除 blade 資源:kubectl delete blade kill-container-process-by-id

掛起 container 內指定進程

此實驗會掛起指定容器中的 redis-server 進程。

參數

參數 類型 說明
process string 進程關鍵詞,會在整個命令行中查找
process-cmd string 進程命令,只會在命令中查找
timeout string 設定運行時長,單位是秒,通用參數

開始實驗

stop_container_process_by_names.yaml 內容:

apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
  name: stop-container-process-by-id
spec:
  experiments:
  - scope: container
    target: process
    action: stop
    desc: "kill container process by id"
    matchers:
    - name: container-ids
      value:
      - "bfc9ca01fac33f60d300485f96549644b634f274351df1d4897526451f49e3fb"
    - name: process
      value: ["redis-server"]
    - name: names
      value: ["redis-slave-55d8c8ffbd-4pz8m"]
    - name: namespace
      value: ["chaosblade"]

選擇一個節點,修改 stop_container_process_by_names.yaml 中的 names 值。

執行命令,開始實驗:

$ kubectl apply -f stop_container_process_by_names.yaml

查看實驗狀態

執行 kubectl get blade stop-container-process-by-names -o json 命令,查看實驗狀態。

觀測結果

# 進入實驗 pod
$ kubectl exec -it redis-slave-55d8c8ffbd-4pz8m bash
# 查看 redis-server 進程號
$ ps aux| grep redis-server
root      5632  0.0  0.0  41520  4168 ?        Tl   06:28   0:06 redis-server *:6379

可以看到 redis-server 此刻進程處於暫停狀態了(T)。

掛起 container 內指定進程

停止實驗

執行命令:kubectl delete -f stop_container_process_by_names.yaml

或者直接刪除 blade 資源:kubectl delete blade stop-container-process-by-names

結語

仔細看過前面幾篇文章的同學獲取會發現,不同場景的混沌實驗中的參數與操作方式有些類似。其實對於這些在不同場景,比如 Pod、Node 和 Container 中進行混沌實驗的實現是一致的,都是基於 blade 這個 CLI 工具,只對對其在不同場景進行了不同的封裝,這就涉及到了混沌工程實驗規範,下篇文章我們就來談談混沌工程模型混沌工程實驗規範,看看混沌工程的實現應該遵循怎麼樣的模型和規範。

<img src="https://tva3.sinaimg.cn/large/ad5fbf65gy1gfm3j2vo79g20b90b9x6r.gif" style="width: 150px;">

Leave a Reply

Your email address will not be published. Required fields are marked *