跳至主内容
版本:下一版本

添加新的混沌实验类型

非官方测试版翻译

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

本文档介绍如何添加新的混沌实验类型。

以下通过 HelloWorldChaos 示例演示添加新混沌实验类型的过程,该实验会在日志中打印 Hello world!。具体步骤包括:

步骤 1:定义 HelloWorldChaos 的 schema

  1. api/v1alpha1 API 目录下创建 helloworldchaos_types.go 文件,内容如下:

    package v1alpha1

    import (
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    )

    // +kubebuilder:object:root=true
    // +chaos-mesh:experiment
    // +chaos-mesh:oneshot=true

    // HelloWorldChaos is the Schema for the helloworldchaos API
    type HelloWorldChaos struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec HelloWorldChaosSpec `json:"spec"`
    Status HelloWorldChaosStatus `json:"status,omitempty"`
    }

    // 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"`
    }

    // HelloWorldChaosStatus defines the observed state of HelloWorldChaos
    type HelloWorldChaosStatus struct {
    ChaosStatus `json:",inline"`
    }

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

    该文件定义了 HelloWorldChaos 的 schema 类型,其可用 YAML 文件描述如下:

    apiVersion: chaos-mesh.org/v1alpha1
    kind: HelloWorldChaos
    metadata:
    name: <resource name>
    namespace: <namespace>
    spec:
    duration: <duration>
    #...

步骤 2:注册 CRD

需要注册 HelloWorldChaos 的 CRD(Custom Resource Definition)才能与 Kubernetes API 交互。

  1. 将上一步生成的 config/crd/bases/chaos-mesh.org_helloworldchaos.yaml 追加到 config/crd/kustomization.yaml 中,以合并到 manifests/crd.yaml:

    resources:
    - bases/chaos-mesh.org_podchaos.yaml
    - bases/chaos-mesh.org_networkchaos.yaml
    - bases/chaos-mesh.org_iochaos.yaml
    - bases/chaos-mesh.org_helloworldchaos.yaml # This is the new line
  2. 在 Chaos Mesh 根目录运行 make generate,生成供 Chaos Mesh 编译的 HelloWorldChaos 样板文件:

    make generate

    随后可在 manifests/crd.yaml 中查看 HelloWorldChaos 的定义。

步骤 3:为 helloworldchaos 对象注册事件处理程序

  1. 创建新文件 controllers/chaosimpl/helloworldchaos/types.go,内容如下:

    package helloworldchaos

    import (
    "context"

    "github.com/go-logr/logr"
    "go.uber.org/fx"
    "sigs.k8s.io/controller-runtime/pkg/client"

    "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    impltypes "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/types"
    "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/utils"
    )

    var _ impltypes.ChaosImpl = (*Impl)(nil)

    type Impl struct {
    client.Client
    Log logr.Logger

    decoder *utils.ContainerRecordDecoder
    }

    // This corresponds to the Apply phase of HelloWorldChaos. The execution of HelloWorldChaos will be triggered.
    func (impl *Impl) Apply(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    impl.Log.Info("Hello world!")
    return v1alpha1.Injected, nil
    }

    // This corresponds to the Recover phase of HelloWorldChaos. The reconciler will be triggered to recover the chaos action.
    func (impl *Impl) Recover(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    impl.Log.Info("Goodbye world!")
    return v1alpha1.NotInjected, nil
    }

    // NewImpl returns a new HelloWorldChaos implementation instance.
    func NewImpl(c client.Client, log logr.Logger, decoder *utils.ContainerRecordDecoder) *impltypes.ChaosImplPair {
    return &impltypes.ChaosImplPair{
    Name: "helloworldchaos",
    Object: &v1alpha1.HelloWorldChaos{},
    Impl: &Impl{
    Client: c,
    Log: log.WithName("helloworldchaos"),
    decoder: decoder,
    },
    ObjectList: &v1alpha1.HelloWorldChaosList{},
    }
    }

    var Module = fx.Provide(
    fx.Annotated{
    Group: "impl",
    Target: NewImpl,
    },
    )
  2. Chaos Mesh 使用 fx 库实现依赖注入。在控制器管理器注册 HelloWorldChaos 时,需在 controllers/chaosimpl/fx.go 中添加:

    var AllImpl = fx.Options(
    gcpchaos.Module,
    stresschaos.Module,
    jvmchaos.Module,
    timechaos.Module,
    helloworldchaos.Module // Add a new line. Make sure you have imported helloworldchaos first.
    //...
    )

    并在 controllers/types/types.goChaosObjects 中添加:

    var ChaosObjects = fx.Supply(
    //...
    fx.Annotated{
    Group: "objs",
    Target: Object{
    Name: "helloworldchaos",
    Object: &v1alpha1.HelloWorldChaos{},
    },
    },
    )

步骤 4:构建 Docker 镜像

  1. 构建生产环境镜像:

    make image
  2. 若使用 minikube 部署 Kubernetes 集群,需将镜像加载至集群:

    minikube image load ghcr.io/chaos-mesh/chaos-dashboard:latest
    minikube image load ghcr.io/chaos-mesh/chaos-mesh:latest
    minikube image load ghcr.io/chaos-mesh/chaos-daemon:latest

步骤 5:运行 HelloWorldChaos

此步骤需部署包含最新修改的 Chaos Mesh 来测试 HelloWorldChaos 功能。

  1. 在集群中注册 CRD:

    kubectl create -f manifests/crd.yaml

    从输出中可看到 HelloWorldChaos 已创建:

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

    现在可通过以下命令获取 HelloWorldChaos 的 CRD:

    kubectl get crd helloworldchaos.chaos-mesh.org
  2. 部署 Chaos Mesh:

    helm install chaos-mesh helm/chaos-mesh -n=chaos-mesh --set controllerManager.leaderElection.enabled=false,dashboard.securityMode=false

    验证部署是否成功,可检查 chaos-mesh 命名空间中的所有 Pod:

    kubectl get pods --namespace chaos-mesh -l app.kubernetes.io/instance=chaos-mesh
  3. 部署测试用 Deployment,这里使用 minikube 文档中的示例 echo 服务:

    kubectl create deployment hello-minikube --image=kicbase/echo-server:1.0

    等待 Pod 进入运行状态:

    kubectl get pods

    示例输出:

    NAME                              READY   STATUS    RESTARTS   AGE
    hello-minikube-77b6f68484-dg4sw 1/1 Running 0 2m
  4. 创建包含以下内容的 hello.yaml 文件:

    apiVersion: chaos-mesh.org/v1alpha1
    kind: HelloWorldChaos
    metadata:
    name: hello-world
    namespace: chaos-mesh
    spec:
    selector:
    labelSelectors:
    app: hello-minikube
    mode: one
    duration: 1h
  5. 运行命令:

    kubectl apply -f hello.yaml
    # helloworldchaos.chaos-mesh.org/hello-world created

    现在可检查 chaos-controller-manager 日志中是否包含 Hello world!

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

    示例输出:

    2023-07-16T06:19:40.068Z INFO records records/controller.go:149 apply chaos {"id": "default/hello-minikube-77b6f68484-dg4sw/echo-server"}
    2023-07-16T06:19:40.068Z INFO helloworldchaos helloworldchaos/types.go:26 Hello world!

后续步骤

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

下一节我们将深入探讨如何扩展 HelloWorldChaos 的行为。