前言
在
上篇文章中,我們介紹了如何使用 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 安裝的
沒有對資源進行限制,進行負載實驗的話,會導緻整個節點的故障,是以在實驗之前需要對資源進行限制。
$ 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"]
$ 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
kubectl delete blade increase-container-cpu-load-by-id
container 内網絡實驗場景
該場景與 Pod 實驗場景類似。
container 網絡延遲場景
實驗目标:對 chaosblade 命名空間中,對
redis-master-68857cd57c-hknb6
Pod 中 container id 是
02655dfdd9f0f712a10d63fdc6721f4dcee0a390e37717fff068bf3f85abf85e
的容器的 6379 端口添加 3000 毫秒通路延遲,延遲時間上下浮動 1000 毫秒。
實驗參數
參數 | 類型 | 說明 |
---|---|---|
| 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。 |
| 排除掉的端口,預設會忽略掉通信的對端端口,目的是保留通信可用。可以指定多個,使用逗号分隔或者連接配接符表示範圍,例如 22,8000 或者 8000-8010。 這個參數不能與 --local-port 或者 --remote-port 參數一起使用。 | |
| 排除受影響的 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。 | |
| 網卡裝置,例如 eth0 (必要參數)。 | |
| 本地端口,一般是本機暴露服務的端口。可以指定多個,使用逗号分隔或者連接配接符表示範圍,例如 80,8000-8080。 | |
| 延遲時間上下浮動的值, 機關是毫秒。 | |
| 遠端端口,一般是要通路的外部暴露服務的端口。可以指定多個,使用逗号分隔或者連接配接符表示範圍,例如 80,8000-8080。 | |
| 延遲時間,機關是毫秒 (必要參數)。 | |
| 強制覆寫已有的 tc 規則,請務必在明确之前的規則可覆寫的情況下使用。 | |
| 針對添加 --exclude-port 參數,報 ss 指令找不到的情況下使用,忽略排除端口。 | |
| 設定運作時長,機關是秒,通用參數。 |
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
kubectl delete blade delay-container-network-by-id
container 網絡丢包場景
redis-master-68857cd57c-hknb6
02655dfdd9f0f712a10d63fdc6721f4dcee0a390e37717fff068bf3f85abf85e
的容器注入丢包率 100% 的故障,隻針對 IP 為
10.42.0.26
的 pod 生效,也就是除
10.42.0.26
以外的 pod 都能正常通路
redis-master-68857cd57c-hknb6
| ||
| ||
| ||
| ||
| ||
| 丢包百分比,取值在[0, 100]的正整數 (必要參數)。 | |
| ||
| ||
| ||
|
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
kubectl delete blade loss-container-network-by-id
container 域名通路異常場景
實驗目标:本實驗通過修改本地的 hosts,篡改域名位址映射,模拟 container 内域名通路異常場景。
| 域名 (必要參數) | |
| 映射的 ip (必要參數) | |
|
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"]
$ 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
程序。
| 程序關鍵詞,會在整個指令行中查找 | |
| 程序指令,隻會在指令中查找 | |
| 限制殺掉程序的數量,0 表示無限制 | |
| 指定殺程序的信号量,預設是 9,例如 --signal 15 | |
| 設定運作時長,機關是秒,通用參數 |
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
kubectl delete blade kill-container-process-by-id
挂起 container 内指定程序
此實驗會挂起指定容器中的
redis-server
| ||
| ||
|
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
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;">