
前言
在上篇文章中,我們介紹了如何安裝 ChaosBlade Operator,并進行了簡單的使用。從本章開始,所有的實踐章節,都會有配套的
katacode互動式教程,讀者可用通過 katacode,在浏覽器上操作真實的 Kubernetes 和 ChaosBlade。
KataCoda 教程:《ChaosBlade Pod 實驗場景》
位址:
https://katacoda.com/guoxudong/courses/chaosblade/pod-experiment
實驗對象:Pod
Pod 是 Kubernetes 應用程式的基本執行單元,即它是 Kubernetes 對象模型中建立或部署的最小和最簡單的單元。Pod 表示在 叢集 上運作的程序。
Pod 封裝了應用程式容器(或者在某些情況下封裝多個容器)、存儲資源、唯一網絡 IP 以及控制容器應該如何運作的選項。 Pod 表示部署單元:Kubernetes 中應用程式的單個執行個體,它可能由單個 容器 或少量緊密耦合并共享資源的容器組成。
Pod 實驗場景
Pod 作為 Kubernetes 最基本的執行單元,對于 Kubernetes 叢集來說十分重要。那麼對于混沌工程,從 Pod 入手實踐就再合适不過了。
本篇預設已安裝 guestbook 應用和 ChaosBlade Operator。
删除 Pod 場景
實驗目标:删除
chaosblade
命名空間下标簽是
role=master
的 pod。
執行觀測
開始觀察需要删除的 pod:
$ kubectl get pod -l "role=master" -n chaosblade -w
開始實驗
delete_pod_by_labels.yaml
内容:
apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
name: delete-two-pod-by-labels
spec:
experiments:
- scope: pod
target: pod
action: delete
desc: "delete pod by labels"
matchers:
- name: labels
value:
- "role=master"
- name: namespace
value:
- "chaosblade"
- name: evict-count
value:
- "2"
建立終端,并開始實驗:
$ kubectl apply -f delete_pod_by_labels.yaml
檢視實驗狀态
執行指令:
kubectl get blade delete-two-pod-by-labels -o json
,檢視實驗狀态。
檢視實驗結果
通過上面的觀測指令,可以看到 pod 被删除并重新開機,結果符合預期。
停止實驗
kubectl delete -f delete_pod_by_labels.yaml
或者直接删除 blade 資源:
kubectl delete blade delete-two-pod-by-labels
Pod 網絡延遲場景
實驗目标:在 chaosblade 命名空間中,對
redis-master-68857cd57c-dzbs9
Pod 的本地 6379 端口添加 3000 毫秒通路延遲,延遲時間上下浮動 1000 毫秒。
delay_pod_network_by_names.yaml
apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
name: delay-pod-network-by-names
spec:
experiments:
- scope: pod
target: network
action: delay
desc: "delay pod network by names"
matchers:
- name: names
value:
- "redis-master-68857cd57c-dzbs9"
- name: namespace
value:
- "chaosblade"
- name: local-port
value: ["6379"]
- name: interface
value: ["eth0"]
- name: time
value: ["3000"]
- name: offset
value: ["1000"]
擷取 Pod 名稱:
$ kubectl get pod -l app=redis,role=master -o jsonpath={.items..metadata.name}
修改
delay_pod_network_by_names.yaml
中的
name
字段的值。
執行指令,開始實驗:
$ kubectl apply -f delay_pod_network_by_names.yaml
執行
kubectl get blade delay-pod-network-by-names -o json
指令,檢視實驗狀态。
觀測結果
# 擷取實驗 pod ip
$ kubectl get pod -l app=redis,role=master -o jsonpath={.items..status.podIP}
10.42.69.44
# 進入觀測 pod
$ kubectl exec -it redis-slave-6dd975d4c8-2zrkb bash
# 在 pod 中安裝 telnet
$ apt-get update && apt-get install -y telnet
# 測試時間
$ time echo "" | telnet 10.42.69.44 6379
Trying 10.42.69.44...
Connected to 10.42.69.44.
Escape character is '^]'.
Connection closed by foreign host.
real 0m3.790s
user 0m0.007s
sys 0m0.001s
可以看到通路實驗 pod 6379 端口的延遲為 3s 左右,結果符合預期。
kubectl delete -f delay_pod_network_by_names.yaml
kubectl delete blade delay-pod-network-by-names
Pod 網絡丢包場景
redis-master-68857cd57c-dzbs9
Pod 注入丢包率 100% 的故障,隻針對 IP 為 10.42.69.42 的 pod 生效,也就是除 10.42.69.42 以外的 pod 都能正常通路
redis-master-68857cd57c-dzbs9
。
擷取 pod 名稱内容同上。
loss_pod_network_by_names.yaml
apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
name: loss-pod-network-by-names
spec:
experiments:
- scope: pod
target: network
action: loss
desc: "loss pod network by names"
matchers:
- name: names
value:
- "redis-master-68857cd57c-dzbs9"
- name: namespace
value:
- "chaosblade"
- name: interface
value: ["eth0"]
- name: percent
value: ["100"]
- name: timeout
value: ["60"]
- name: destination-ip
value: ["10.42.69.42"]
$ kubectl apply -f loss_pod_network_by_names.yaml
kubectl get blade loss-pod-network-by-names -o json
# 擷取實驗 pod ip
$ kubectl get pod -l app=redis,role=master -o jsonpath={.items..status.podIP}
10.42.69.44
# 進入觀測 pod,IP為:10.42.69.42(被設定丢包率 100%)
$ kubectl exec -it redis-slave-6dd975d4c8-lm8jz bash
# Ping 實驗Pod ip
$ ping 10.42.69.44
PING 10.42.69.44 (10.42.69.44) 56(84) bytes of data.
# 無響應
# 進入觀測 pod,該 pod 未被指定丢包
$ kubectl exec -it redis-slave-6dd975d4c8-2zrkb bash
# Ping 實驗Pod ip
$ ping 10.42.69.44
PING 10.42.69.44 (10.42.69.44) 56(84) bytes of data.
64 bytes from 10.42.69.44: icmp_seq=1 ttl=63 time=0.128 ms
64 bytes from 10.42.69.44: icmp_seq=2 ttl=63 time=0.128 ms
64 bytes from 10.42.69.44: icmp_seq=3 ttl=63 time=0.092 ms
...
# 響應正常
可以看到觀測 pod 通路實驗 pod 丢包率 100%(無法通路),而其他 pod 不受影響,結果符合預期。
這裡在配置中将
timeout
設定為 60 秒,60 秒後 100% 丢包的情況将會消失,這個配置是為了防止因丢包率設定太高,造成機器無法連接配接的情況。與其有相似功能的還有
exclude-port
,該配置指定一些端口不會丢包,以免該 pod 失聯。
kubectl delete -f loss_pod_network_by_names.yaml
kubectl delete blade loss-pod-network-by-names
)
Pod 域名通路異常場景
實驗目标:Pod 内通路指定域名異常。
dns_pod_network_by_names.yaml
apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
name: dns-pod-network-by-names
spec:
experiments:
- scope: pod
target: network
action: dns
desc: "dns pod network by names"
matchers:
- name: names
value:
- "redis-slave-6dd975d4c8-lm8jz"
- name: namespace
value:
- "chaosblade"
- name: domain
value: ["www.baidu.com"]
- name: ip
value: ["10.0.0.1"]
$ kubectl apply -f dns_pod_network_by_names.yaml
kubectl get blade dns-pod-network-by-names -o json
# 進入實驗 pod
$ kubectl exec -it redis-slave-6dd975d4c8-lm8jz bash
# Ping www.baidu.com
$ ping www.baidu.com
# 無響應
可以看到通路指定域名
www.baidu.com
異常,結果符合預期。
kubectl delete -f dns_pod_network_by_names.yaml
kubectl delete blade dns-pod-network-by-names
Pod 檔案系統 I/O 故障場景
實驗目标:給 kubernetes 的 pod 注入檔案系統I/O故障。
注意:此場景需要激活參數,如需使用此功能,請在 chaosblade-operator 參數中添加
--webhook-enable
,或者在安裝時指定:例如 helm 安裝時添加
--webhook-enable
指定。
--set webhook.enable=true
前提條件
- 叢集中部署了
chaosblade-admission-webhook
- 需要注入故障的
設定volume
為mountPropagation
HostToContainer
- pod上面添加了如下annotations:
chaosblade/inject-volume: "data" //需要注入故障的volume name
chaosblade/inject-volume-subpath: "conf" //volume挂載的子目錄
部署測試 pod
chaosblade webhook 會根據 pod 的 annotation,注入 fuse 的 sidecar 容器:
-
指明需要注入故障的 volume name,比如例子中的chaosblade/inject-volume
data
-
指明 volume 挂載路徑的子目錄。上面的例子中,volume 的挂載路徑是chaosblade/inject-volume-subpath
,子目錄是/data
,則在 pod 内,注入I/O異常的目錄是conf
/data/conf
- 指定需要注入故障的 volume 需要指定
,這個字段的含義可以參考官方文檔 VolumesmountPropagation:HostToContainer
# 部署測試 pod
$ kubectl apply -f io-test-pod.yaml
# 檢視 sidecar 是否注入成功
$ kubectl get pod test-7c9fc6fd88-7lx6b -n chaosblade
NAME READY STATUS RESTARTS AGE
test-7c9fc6fd88-7lx6b 2/2 Running 0 4m8s
pod_io.yaml
apiVersion: chaosblade.io/v1alpha1
kind: ChaosBlade
metadata:
name: inject-pod-by-labels
spec:
experiments:
- scope: pod
target: pod
action: IO
desc: "Pod IO Exception by labels"
matchers:
- name: labels
value:
- "app=test"
- name: namespace
value:
- "chaosblade"
- name: method
value:
- "read"
- name: delay
value:
- "1000"
- name: path
value:
- ""
- name: percent
value:
- "60"
- name: errno
value:
- "28"
$ kubectl apply -f pod_io.yaml
kubectl get blade inject-pod-by-labels -o json
# 進入實驗 pod
$ kubectl exec -it test-7c9fc6fd88-7lx6b bash
# 在 pod 内讀取指定目錄中的檔案,如果沒有可以建立一個
$ time cat /data/conf/test.yaml
cat: read error: No space left on device
real 0m3.007s
user 0m0.002s
sys 0m0.002s
# 因為有重試,顯示有 3s 的延遲
# 因為設定了 60% 的異常,所有還是有成功的情況
$ time cat /data/conf/test.yaml
123
real 0m0.004s
user 0m0.002s
sys 0m0.000s
檔案讀取異常,結果符合預期。
在本例中,我們對 read 操作注入兩種異常,異常率為百分之60:
- 對
操作增加 1s 的延遲。read
-
操作傳回錯誤read
28
這裡隻是做了一種類型的實驗,更多的實驗類型詳見
官方文檔kubectl delete -f pod_io.yaml
kubectl delete blade inject-pod-by-labels
删除測試 pod:
kubectl delete -f io-test-pod.yaml
結語
本篇我們使用 ChaosBlade Operator 對 Kubernetes Pod 資源進行混沌工程實驗,可以看到 ChaosBlade 的操作簡單易懂且功能強大,通過模拟不同的故障,可以檢驗我們系統監控報警的時效性,也可以檢驗我們系統在遇到故障時的情況,根據這些情況對系統進行調整,進而完善系統架構,增加可用性。
這裡隻是對于每種場景進行了簡單的實驗,而每個場景不止有一種實驗方式,使用者可以通過調整參數進行不同的實驗。