混沌工程工具-阿里ChaosBlade的實現說明之一

原文請見7DGroup已聲明原創的公衆號文章。
7DGroup公衆號
根據混沌工程的principles,裏面這樣定義了:
Chaos Engineering is the discipline of experimenting on a system
in order to build confidence in the system’s capability
to withstand turbulent conditions in production.
中文翻譯是這樣的:
混沌工程是在分佈式系統上進行實驗的學科, 目的是建立對系統抵禦生產環境中失控條件的能力以及信心。
(英文中似乎沒有分佈式系統這個字眼,看來中文翻譯的時候把範圍說小了。)
它有原則描述:
建立一個圍繞穩定狀態行爲的假說
多樣化真實世界的事件
在生產環境中運行實驗
持續自動化運行實驗
最小化爆炸半徑
看着有些比較新鮮的詞還挺有意思。也有人把它和異常測試、故障測試啥的給區分開來說明。要說還是得整概念,概念還是要先於技術的發展,給技術指導一個方向,而落地嘛,總是需要一些時間的。
據說阿里的chaosblade開源工具算是具有混沌工程特點的工具。下面看一下它的功能。

安裝配置

二進制包形式

下載並解壓

[gaolou@7dgroup2 ~]$ wget -c https://github.com/chaosblade-io/chaosblade/releases/download/v0.2.0/chaosblade-0.2.0.linux-amd64.tar.gz
[gaolou@7dgroup2 ~]$ tar zxvf chaosblade-0.2.0.linux-amd64.tar.gz

docker形式

[root@VM_0_10_centos ~]# docker pull registry.cn-hangzhou.aliyuncs.com/chaosblade/chaosblade-demo:latest
[root@VM_0_10_centos ~]# docker run -it registry.cn-hangzhou.aliyuncs.com/chaosblade/chaosblade-demo:latest

blade使用

模擬CPU

模擬CPU負載

[gaolou@7dgroup2 chaosblade-0.2.0]$ ./blade  create cpu fullload
{"code":200,"success":true,"result":"cb6300fd4899c537"}
[gaolou@7dgroup2 chaosblade-0.2.0]$

查看模擬效果

TOP查看結果
在這裏插入圖片描述
Perf查看結果
在這裏插入圖片描述
burnCpu這個方法裏的。關鍵源碼如下:


func runBurnCpu(ctx context.Context, cpuCount int, cpuPercent int, pidNeeded bool, processor string) int {
  args := fmt.Sprintf(`%s --nohup --cpu-count %d --cpu-percent %d`,
    path.Join(util.GetProgramPath(), burnCpuBin), cpuCount, cpuPercent)
  if pidNeeded {
    args = fmt.Sprintf("%s --cpu-processor %s", args, processor)
  }
  args = fmt.Sprintf(`%s > /dev/null 2>&1 &`, args)
  response := channel.Run(ctx, "nohup", args)
  if !response.Success {
    stopBurnCpuFunc()
    bin.PrintErrAndExit(response.Err)
  }
  if pidNeeded {
    // parse pid
    newCtx := context.WithValue(context.Background(), exec.ProcessKey, fmt.Sprintf("cpu-processor %s", processor))
    pids, err := exec.GetPidsByProcessName(burnCpuBin, newCtx)
    if err != nil {
      stopBurnCpuFunc()
      bin.PrintErrAndExit(fmt.Sprintf("bind cpu core failed, cannot get the burning program pid, %v", err))
    }
    if len(pids) > 0 {
      // return the first one
      pid, err := strconv.Atoi(pids[0])
      if err != nil {
        stopBurnCpuFunc()
        bin.PrintErrAndExit(fmt.Sprintf("bind cpu core failed, get pid failed, pids: %v, err: %v", pids, err))
      }
      return pid
    }
  }
  return -1
}

刪除CPU負載

[gaolou@7dgroup2 chaosblade-0.2.0]$ ./blade destroy cb6300fd4899c537
{"code":200,"success":true,"result":"command: cpu fullload --debug false --help false"}
[gaolou@7dgroup2 chaosblade-0.2.0]$

模擬磁盤滿

模擬磁盤滿

[root@7dgroup2 chaosblade-0.2.0]# ./blade create disk fill --size 20480
{"code":200,"success":true,"result":"a3f62976fe766d4a"}

查看模擬效果

[root@7dgroup2 bin]# watch -n 1 "df -h | grep /dev/vda1"
Every 1.0s: df -h | grep /dev/vda1                                               Tue Aug 13 17:46:15 2019  |

/dev/vda1        40G   33G  4.8G  88% /

Every 1.0s: df -h | grep /dev/vda1                                               Tue Aug 13 17:46:25 2019

/dev/vda1        40G   34G  3.9G  90% /

Every 1.0s: df -h | grep /dev/vda1                                               Tue Aug 13 17:46:36 2019

/dev/vda1        40G   35G  2.8G  93% /

Every 1.0s: df -h | grep /dev/vda1                                               Tue Aug 13 17:47:13 2019

/dev/vda1        40G   37G  760M  99% /

Every 1.0s: df -h | grep /dev/vda1                                               Tue Aug 13 17:48:10 2019

/dev/vda1        40G   38G  109M 100% /

Every 1.0s: df -h | grep /dev/vda1                                               Tue Aug 13 17:49:10 2019

/dev/vda1        40G   38G     0 100% /

刪除磁盤滿模擬

[root@7dgroup2 chaosblade-0.2.0]# ./blade destroy a3f62976fe766d4a
{"code":200,"success":true,"result":"command: disk fill --help false --size 20480 --debug false"}
[root@7dgroup2 chaosblade-0.2.0]# watch -n 1 "df -h | grep /dev/vda1"

Every 1.0s: df -h | grep /dev/vda1                                               Tue Aug 13 17:49:34 2019

/dev/vda1        40G   32G  6.0G  85% /

查看模擬磁盤滿進程

Total DISK READ :       5.40 M/s | Total DISK WRITE :      65.33 M/s
Actual DISK READ:       6.41 M/s | Actual DISK WRITE:      89.98 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
.......
17369 be/4 root       11.23 K/s   64.96 M/s  0.00 % 37.49 % dd if=/dev/zero of=/chaos_fi~M count=20480 iflag=fullblock
.......

通過查看io高的進程就可以看到這兩個進程。也就是說,chaosblade調用dd實現的IO高模擬。關鍵實現代碼如下:

// write burn
func burnWrite(size, count string) {
  for {
    args := fmt.Sprintf(`if=/dev/zero of=%s bs=%sM count=%s oflag=dsync`, tmpDataFile, size, count)
    response := channel.Run(context.Background(), "dd", args)
    channel.Run(context.Background(), "rm", fmt.Sprintf(`-rf %s`, tmpDataFile))
    if !response.Success {
      bin.PrintAndExitWithErrPrefix(response.Err)
      return
    }
  }
}
// read burn
func burnRead(fileSystem, size, count string) {
  for {
    // "if" arg in dd command is file system value, but "of" arg value is related to mount point
    args := fmt.Sprintf(`if=%s of=/dev/null bs=%sM count=%s iflag=dsync,direct,fullblock`, fileSystem, size, count)
    response := channel.Run(context.Background(), "dd", args)
    if !response.Success {
      bin.PrintAndExitWithErrPrefix(fmt.Sprintf("The file system named %s is not supported or %s", fileSystem, response.Err))
    }
  }
}

一個讀一個寫。

這個chaosblade實際上可以看做是一個工具集,集成了各種小工具。
混沌的帽子在這個工具,現在套着還是有點大。要想用它來實現上千上萬個節點的模擬,還需要各種集成配置,遠程執行等工具的配合。
大家再回過頭來看看上面寫的混沌工程定義的原則。這些模擬有沒有符合這些原則呢?如果各位有處理生產環境的經驗的話,會知道,這樣的模擬,其實和真實環境下的CPU高、IO高的邏輯還是有不同的。
通常我們說一個應用程序的在CPU高的情況下是否能保持健壯。有兩種含義:
其他程序在消耗CPU較高的情況下,被測試的程序是否能保持健壯。
是指的是這個應用本身的代碼消耗了大量CPU的情況下,被測試程序是否能保持健壯。
有處理過生產類似問題的朋友們會知道,第一種情況,除了部署上的不合理會出現之外,幾乎是看不到的。chaosblade其實是模擬的這種情況。而第二種情況,chaosblade現在還是做不到的。
但第二種情況卻是測試過程中的重點。

其實英文中的chaos的含義是混亂。這和中文的混沌是非常不同的概念,現在這個概念被翻譯成混沌,真是拉低了混沌這個詞本身該有的寓意。

關於此工具的其他功能實現,如果有人有興趣,後面再接着寫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章