天天看點

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

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-ids

names

執行指令,開始實驗:

$ kubectl apply -f remove_container_by_id.yaml           

檢視實驗狀态

執行

kubectl get blade remove-container-by-id -o json

指令,檢視實驗狀态。

觀測結果

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

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

停止實驗

執行指令:

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

,檢視實驗狀态。

可從監控系統觀測到結果

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

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 毫秒。

實驗參數

參數 類型 說明

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

排除掉的端口,預設會忽略掉通信的對端端口,目的是保留通信可用。可以指定多個,使用逗号分隔或者連接配接符表示範圍,例如 22,8000 或者 8000-8010。 這個參數不能與 --local-port 或者 --remote-port 參數一起使用。

exclude-ip

排除受影響的 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

網卡裝置,例如 eth0 (必要參數)。

local-port

本地端口,一般是本機暴露服務的端口。可以指定多個,使用逗号分隔或者連接配接符表示範圍,例如 80,8000-8080。

offset

延遲時間上下浮動的值, 機關是毫秒。

remote-port

遠端端口,一般是要通路的外部暴露服務的端口。可以指定多個,使用逗号分隔或者連接配接符表示範圍,例如 80,8000-8080。

time

延遲時間,機關是毫秒 (必要參數)。

force

強制覆寫已有的 tc 規則,請務必在明确之前的規則可覆寫的情況下使用。

ignore-peer-port

針對添加 --exclude-port 參數,報 ss 指令找不到的情況下使用,忽略排除端口。

timeout

設定運作時長,機關是秒,通用參數。

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           
ChaosBlade:從零開始的混沌工程(五)

可以看到結果符合預期。

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

destination-ip

exclude-port

exclude-ip

interface

local-port

percent

丢包百分比,取值在[0, 100]的正整數 (必要參數)。

remote-port

force

ignore-peer-port

timeout

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
...
# 響應正常           
ChaosBlade:從零開始的混沌工程(五)

這裡在配置中還将

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 内域名通路異常場景。

domain

域名 (必要參數)

ip

映射的 ip (必要參數)

timeout

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
# 無響應           
ChaosBlade:從零開始的混沌工程(五)

可以看到 Pod 的

/etc/hosts

檔案被修改,模拟了 dns 解析異常的場景。

container 内程序場景

殺 container 内指定程序

此實驗會删除指定容器中的

redis-server

程序。

process

程序關鍵詞,會在整個指令行中查找

process-cmd

程序指令,隻會在指令中查找

count

限制殺掉程序的數量,0 表示無限制

signal

指定殺程序的信号量,預設是 9,例如 --signal 15

timeout

設定運作時長,機關是秒,通用參數

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           
ChaosBlade:從零開始的混沌工程(五)

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

redis-server

的程序号發生改變,說明被殺掉後,又被重新拉起。

kubectl delete -f kill_container_process_by_id.yaml

kubectl delete blade kill-container-process-by-id

挂起 container 内指定程序

此實驗會挂起指定容器中的

redis-server

process

process-cmd

timeout

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)。

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

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;">