新增混沌实验类型

    本文档介绍如何开发一种新的混沌实验类型。

    以开发一种名为 HelloWorldChaos 的混沌实验类型为例,它的功能是向日志中输出一行 “Hello world!”。为了完成这一目标,你需要完成以下步骤:

    • 第 1 步:定义混沌实验的结构类型
    • 第 2 步:注册 CRD
    • 第 3 步:注册混沌实验的处理函数
    • 第 4 步:编译 Docker 镜像
    • 第 5 步:运行混沌实验
    1. 在 API 目录 中新建一个名为 helloworldchaos_types.go 的文件,写入以下内容:

      这个文件定义了 HelloWorldChaos 的结构类型,它可以用一个 YAML 文件描述:

      1. apiVersion: chaos-mesh.org/v1alpha1
      2. kind: HelloWorldChaos
      3. metadata:
      4. name: <资源名>
      5. namespace: <命名空间名>
      6. spec:
      7. duration: <持续时间>
      8. status:
      9. experiment: <实验状态>
      10. ...
    2. 在 Chaos Mesh 根目录下运行 make generate,为 HelloWorldChaos 生成一些用于编译 Chaos Mesh 的辅助代码。

    第 2 步:注册 CRD

    在 Kubernetes API 中注册 HelloWorldChaos 的 CRD,使 HelloWorldChaos 成为一种 Kubernetes 自定义资源。

    1. 在根目录下运行 make yaml

      生成的 YAML 文件位于 config/crd/bases/chaos-mesh.org_helloworldchaos.yaml

    2. 为将这个 YAML 文件合并入 manifests/crd.yaml 中,修改 config/crd/kustomization.yaml,在其中加入新的一行:

      1. resources:
      2. - bases/chaos-mesh.org_podchaos.yaml
      3. - bases/chaos-mesh.org_networkchaos.yaml
      4. - bases/chaos-mesh.org_iochaos.yaml
      5. - bases/chaos-mesh.org_helloworldchaos.yaml # 新增一行
    3. 再次运行 make yaml,HelloWorldChaos 的定义就会出现在 manifests/crd.yaml 里。 如需确认,你可以使用 git diff 命令。

    1. 创建一个新文件 controllers/chaosimpl/helloworldchaos/types.go 并写入如下内容:

      1. package helloworldchaos
      2. import (
      3. "context"
      4. "github.com/go-logr/logr"
      5. "go.uber.org/fx"
      6. "sigs.k8s.io/controller-runtime/pkg/client"
      7. "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
      8. "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/utils"
      9. "github.com/chaos-mesh/chaos-mesh/controllers/common"
      10. "github.com/chaos-mesh/chaos-mesh/controllers/utils/chaosdaemon"
      11. )
      12. type Impl struct {
      13. client.Client
      14. Log logr.Logger
      15. }
      16. // Apply applies HelloWorldChaos
      17. func (impl *Impl) Apply(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
      18. impl.Log.Info("Hello world!")
      19. return v1alpha1.Injected, nil
      20. }
      21. // Recover means the reconciler recovers the chaos action
      22. func (impl *Impl) Recover(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
      23. impl.Log.Info("Goodbye world!")
      24. return v1alpha1.NotInjected, nil
      25. }
      26. func NewImpl(c client.Client, log logr.Logger, decoder *utils.ContainerRecordDecoder) *common.ChaosImplPair {
      27. return &common.ChaosImplPair{
      28. Name: "helloworldchaos",
      29. Object: &v1alpha1.HelloWorldChaos{},
      30. Impl: &Impl{
      31. Client: c,
      32. Log: log.WithName("helloworldchaos"),
      33. decoder: decoder,
      34. },
      35. ObjectList: &v1alpha1.HelloWorldChaosList{},
      36. }
      37. }
      38. var Module = fx.Provide(
      39. fx.Annotated{
      40. Group: "impl",
      41. Target: NewImpl,
      42. },
      43. )
      1. ...
      2. gcpchaos.Module,
      3. stresschaos.Module,
      4. jvmchaos.Module,
      5. timechaos.Module,
      6. helloworldchaos.Module // 新增一行,注意处理 import

      以及在 controllers/types/types.go 中加入:

      1. ...
      2. fx.Annotated{
      3. Group: "objs",
      4. Target: Object{
      5. Name: "timechaos",
      6. Object: &v1alpha1.TimeChaos{},
      7. },
      8. },
      9. fx.Annotated{
      10. Group: "objs",
      11. Target: Object{
      12. Object: &v1alpha1.GCPChaos{},
      13. },
      14. },
      15. fx.Annotated{
      16. Target: Object{
      17. Name: "helloworldchaos",
      18. Object: &v1alpha1.HelloWorldChaos{},
      19. },
      20. },

    第 4 步:编译 Docker 镜像

    1. 在完成了前面所有步骤后,你可以尝试编译镜像:

      1. make
    2. 将镜像推送到本地的 Docker Registry 中:

    3. 如果你的 Kubernetes 集群部署在 kind 上,则还需要将镜像加载进 kind 中:

      1. kind load docker-image localhost:5000/chaos-mesh/chaos-mesh:latest
      2. kind load docker-image localhost:5000/chaos-mesh/chaos-daemon:latest
      3. kind load docker-image localhost:5000/chaos-mesh/chaos-dashboard:latest

    在这一步中,你需要部署修改版的 Chaos Mesh 并测试 HelloWorldChaos。

    在你部署 Chaos Mesh 之前(使用 helm installhelm upgrade),请修改 helm 模板的 helm/chaos-mesh/values.yaml,把镜像更换成你本地 Docker Registry 中的镜像。

    Chaos Mesh 的模板使用 chaos-mesh/chaos-mesh:latest 作为默认 Registry,你需要把它换成 DOCKER_REGISTRY 环境变量的值(默认为 localhost:5000),示例如下:

    1. controllerManager:
    2. image: localhost:5000/chaos-mesh/chaos-mesh:latest
    3. ...
    4. chaosDaemon:
    5. image: localhost:5000/chaos-mesh/chaos-daemon:latest
    6. ...
    7. dashboard:
    8. image: localhost:5000/chaos-mesh/chaos-dashboard:latest
    9. ...

    完成上述模板修改后,请尝试运行 HelloWorldChaos。

    1. 将 CRD 注册进集群:

      1. kubectl create -f manifests/crd.yaml

      可以看到 HelloWorldChaos 已经被创建:

      1. customresourcedefinition.apiextensions.k8s.io/helloworldchaos.chaos-mesh.org created

      现在可以查看 HelloWorldChaos 的 CRD:

      1. kubectl get crd helloworldchaos.chaos-mesh.org
      1. helm install chaos-mesh helm/chaos-mesh --namespace=chaos-testing --set chaosDaemon.runtime=containerd --set chaosDaemon.socketPath=/run/containerd/containerd.sock

      验证一下安装是否成功,查询 chaos-testing 命名空间的 Pod:

      注意

      --set chaosDaemon.runtime=containerd --set chaosDaemon.socketPath=/run/containerd/containerd.sock 是用来在 kind 上运行 NetworkChaos 的。

    2. 部署用于测试的目标 Pod:

      1. kubectl apply -f https://raw.githubusercontent.com/chaos-mesh/apps/master/ping/busybox-statefulset.yaml

      请确保用于测试的目标 Pod 可以正常运行。

    3. 创建一个名为 chaos.yaml 的文件,写入以下内容:

      1. apiVersion: chaos-mesh.org/v1alpha1
      2. kind: HelloWorldChaos
      3. metadata:
      4. name: hello-world
      5. namespace: chaos-testing
      6. spec:
      7. selector:
      8. namespaces:
      9. - busybox
      10. mode: one
      11. duration: 1h
    4. 运行混沌实验:

      1. kubectl apply -f /path/to/chaos.yaml
      1. kubectl get HelloWorldChaos -n chaos-testing

      现在查看 chaos-controller-manager 的日志,就会看到 Hello World!

      1. kubectl logs chaos-controller-manager-{pod-post-fix} -n chaos-testing

      显示日志如下:

      1. 2021-06-24T06:42:26.858Z INFO records apply chaos {"id": "chaos-testing/chaos-daemon-vsmc5"}
      注意

      {pod-post-fix} 是一个随机串。你可以运行 来查看它。

    探索更多

    如果你在新增混沌实验类型的过程中遇到了问题,请在 GitHub 创建一个 issue 向 Chaos Mesh 团队反馈。

    如果你想进一步尝试开发工作,请参阅 。