前言
在上篇文章中,我們介紹瞭如何使用 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-ids
和 names
。
執行命令,開始實驗:
$ kubectl apply -f remove_container_by_id.yaml
查看實驗狀態
執行 kubectl get blade remove-container-by-id -o json
命令,查看實驗狀態。
觀測結果
查看容易 ID,可以看到容器ID發生了變化,舊容器被刪除了,拉起了新容器。
停止實驗
執行命令: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-ids
和 names
。
查看實驗狀態
執行命令:kubectl get blade increase-container-cpu-load-by-id -o json
,查看實驗狀態。
觀測結果
可從監控系統觀測到結果
停止實驗
執行命令: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-ids
和 names
。
執行命令,開始實驗:
$ 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
可以看到結果符合預期。
停止實驗
執行命令: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
...
# 響應正常
這裡在配置中還將 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
# 無響應
可以看到 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
容器 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)。
停止實驗
執行命令: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;">