跳至主内容
版本:2.6.7

扩展 Chaos Daemon 接口

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

添加新的混沌实验类型中,您已添加了HelloWorldChaos,该实验可在 Chaos Controller Manager 的日志中输出Hello world!

若要让HelloWorldChaos向目标 Pod 注入故障,您需要扩展 Chaos Daemon 的接口。

技巧

建议继续操作前先阅读 Chaos Mesh 架构

本文涵盖以下内容:

选择器

api/v1alpha1/helloworldchaos_type.go中,您已定义包含ContainerSelectorHelloWorldSpec

// HelloWorldChaosSpec defines the desired state of HelloWorldChaos
type HelloWorldChaosSpec struct {
// ContainerSelector specifies the target for injection
ContainerSelector `json:",inline"`

// Duration represents the duration of the chaos
// +optional
Duration *string `json:"duration,omitempty"`

// RemoteCluster represents the remote cluster where the chaos will be deployed
// +optional
RemoteCluster string `json:"remoteCluster,omitempty"`
}

//...

// GetSelectorSpecs is a getter for selectors
func (obj *HelloWorldChaos) GetSelectorSpecs() map[string]interface{} {
return map[string]interface{}{
".": &obj.Spec.ContainerSelector,
}
}

在 Chaos Mesh 中,选择器用于定义混沌实验的作用范围,包括目标命名空间、注解、标签等。

选择器也可以是更具体的值(例如AWSChaos中的AWSSelector)。通常每个混沌实验只需一个选择器,但像NetworkChaos这样的实验例外——当进行网络分区时需要两个选择器来标识两个对象。

关于选择器的更多信息,请参阅定义混沌实验作用域

实现 gRPC 接口

为使 Chaos Daemon 能接收 Chaos Controller Manager 的请求,您需要实现新的 gRPC 接口。

  1. pkg/chaosdaemon/pb/chaosdaemon.proto中添加 RPC:

    service ChaosDaemon {
    ...

    rpc ExecHelloWorldChaos(ExecHelloWorldRequest) returns (google.protobuf.Empty) {}
    }

    message ExecHelloWorldRequest {
    string container_id = 1;
    }

    然后执行以下命令更新相关chaosdaemon.pb.go文件:

    make proto
  2. 在 Chaos Daemon 中实现 gRPC 服务。

    pkg/chaosdaemon目录下创建helloworld_server.go文件,内容如下:

    package chaosdaemon

    import (
    "context"

    "github.com/golang/protobuf/ptypes/empty"

    "github.com/chaos-mesh/chaos-mesh/pkg/bpm"
    "github.com/chaos-mesh/chaos-mesh/pkg/chaosdaemon/pb"
    )

    func (s *DaemonServer) ExecHelloWorldChaos(ctx context.Context, req *pb.ExecHelloWorldRequest) (*empty.Empty, error) {
    log := s.getLoggerFromContext(ctx)
    log.Info("ExecHelloWorldChaos", "request", req)

    pid, err := s.crClient.GetPidFromContainerID(ctx, req.ContainerId)
    if err != nil {
    return nil, err
    }

    cmd := bpm.DefaultProcessBuilder("sh", "-c", "ps aux").
    SetContext(ctx).
    SetNS(pid, bpm.MountNS).
    Build(ctx)
    out, err := cmd.Output()
    if err != nil {
    return nil, err
    }
    if len(out) != 0 {
    log.Info("cmd output", "output", string(out))
    }

    return &empty.Empty{}, nil
    }

    chaos-daemon接收到ExecHelloWorldChaos请求后,您将看到当前容器内的进程列表。

  3. 在应用混沌实验时发送 gRPC 请求

    每个混沌实验都有生命周期:先applyrecover。但某些混沌实验默认无法恢复(例如 PodChaos 中的 PodKill 和 HelloWorldChaos),这类实验称为 OneShot 实验。我们在 HelloWorldChaos 模式中定义的 +chaos-mesh:oneshot=true 就是标记。

    HelloWorldChaos 处于 apply 阶段时,混沌控制器管理器需要向 chaos-daemon 发送请求。需更新 controllers/chaosimpl/helloworldchaos/types.go

    func (impl *Impl) Apply(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    impl.Log.Info("Apply helloworld chaos")

    decodedContainer, err := impl.decoder.DecodeContainerRecord(ctx, records[index], obj)
    if err != nil {
    return v1alpha1.NotInjected, err
    }

    pbClient := decodedContainer.PbClient
    containerId := decodedContainer.ContainerId

    _, err = pbClient.ExecHelloWorldChaos(ctx, &pb.ExecHelloWorldRequest{
    ContainerId: containerId,
    })
    if err != nil {
    return v1alpha1.NotInjected, err
    }

    return v1alpha1.Injected, nil
    }

    func (impl *Impl) Recover(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    impl.Log.Info("Recover helloworld chaos")
    return v1alpha1.NotInjected, nil
    }
    信息

    由于无需恢复 HelloWorldChaos,因为 HelloWorldChaosOneShot 实验。您可根据实际需求在开发的其他混沌实验类型中实现恢复逻辑。

验证 HelloWorldChaos 输出

现在可以验证 HelloWorldChaos 的输出效果:

  1. 添加新混沌实验类型文档说明构建 Docker 镜像,并加载到集群

    备注

    若使用 minikube,请注意部分版本无法覆盖同标签的现有镜像。建议先删除旧镜像再加载新镜像。

  2. Update Chaos Mesh:

  3. 部署测试用 Pod:

    kubectl apply -f https://raw.githubusercontent.com/chaos-mesh/apps/master/ping/busybox-statefulset.yaml
  4. 创建 hello-busybox.yaml 文件,内容如下:

    apiVersion: chaos-mesh.org/v1alpha1
    kind: HelloWorldChaos
    metadata:
    name: hello-busybox
    namespace: chaos-mesh
    spec:
    selector:
    namespaces:
    - busybox
    mode: all
    duration: 1h
  5. 运行以下命令:

    kubectl apply -f hello-busybox.yaml
    # helloworldchaos.chaos-mesh.org/hello-busybox created
    • 现在检查 chaos-controller-manager 日志中是否出现 Apply helloworld chaos 记录:

      kubectl logs -n chaos-mesh chaos-controller-manager-xxx

      示例输出:

      2023-07-16T08:20:46.823Z INFO records records/controller.go:149 apply chaos {"id": "busybox/busybox-0/busybox"}
      2023-07-16T08:20:46.823Z INFO helloworldchaos helloworldchaos/types.go:27 Apply helloworld chaos
    • 检查 Chaos Daemon 的日志:

      kubectl logs -n chaos-mesh chaos-daemon-xxx

      示例输出:

      2023-07-16T08:20:46.833Z INFO chaos-daemon.daemon-server chaosdaemon/server.go:187 ExecHelloWorldChaos {"namespacedName": "chaos-mesh/hello-busybox", "request": "container_id:\"docker://5e01e76efdec6aa0934afc15bb80e121d58b43c529a6696a01a242f7ac68f201\""}
      2023-07-16T08:20:46.834Z INFO chaos-daemon.daemon-server.background-process-manager.process-builder pb/chaosdaemon.pb.go:4568 build command {"namespacedName": "chaos-mesh/hello-busybox", "command": "/usr/local/bin/nsexec -m /proc/104710/ns/mnt -- sh -c ps aux"}
      2023-07-16T08:20:46.841Z INFO chaos-daemon.daemon-server chaosdaemon/server.go:187 cmd output {"namespacedName": "chaos-mesh/hello-busybox", "output": "PID USER TIME COMMAND\n 1 root 0:00 sh -c echo Container is Running ; sleep 3600\n"}
      2023-07-16T08:20:46.856Z INFO chaos-daemon.daemon-server chaosdaemon/server.go:187 ExecHelloWorldChaos {"namespacedName": "chaos-mesh/hello-busybox", "request": "container_id:\"docker://bab4f632a0358529f7d72d35e014b8c2ce57438102d99d6174dd9df52d093e99\""}
      2023-07-16T08:20:46.864Z INFO chaos-daemon.daemon-server.background-process-manager.process-builder pb/chaosdaemon.pb.go:4568 build command {"namespacedName": "chaos-mesh/hello-busybox", "command": "/usr/local/bin/nsexec -m /proc/104841/ns/mnt -- sh -c ps aux"}
      2023-07-16T08:20:46.867Z INFO chaos-daemon.daemon-server chaosdaemon/server.go:187 cmd output {"namespacedName": "chaos-mesh/hello-busybox", "output": "PID USER TIME COMMAND\n 1 root 0:00 sh -c echo Container is Running ; sleep 3600\n"}

    您将看到两条独立的 ps aux 输出记录,分别对应两个不同的 Pod。

后续规划

如果您在操作过程中遇到任何问题,请在 Chaos Mesh 仓库提交 issue

若想深入了解实现原理,可继续阅读 controllers/README.md 和各类控制器的源代码。

现在您已准备好成为 Chaos Mesh 的开发者!欢迎访问 Chaos Mesh issues 寻找入门任务并开始贡献吧!