After preparing the development environment, let's develop a new type of chaos, HelloWorldChaos, which only prints a "Hello World!" message to the log. Generally, to add a new chaos type for Chaos Mesh, you need to take the following steps:

Add the chaos object in controller

In Chaos Mesh, all chaos types are managed by the controller manager. To add a new chaos type, you need to start from adding the corresponding reconciler type in the controller, as instructed in the following steps:

  • Add the HelloWorldChaos object in the controller manager main.go.

You will notice existing chaos types such as PodChaos, NetworkChaos and IOChaos. Add the new type below them:

  1. if err = (&controllers.HelloWorldChaosReconciler{
  2. Client: mgr.GetClient(),
  3. Log: ctrl.Log.WithName("controllers").WithName("HelloWorldChaos"),
  4. }).SetupWithManager(mgr); err != nil {
  5. setupLog.Error(err, "unable to create controller", "controller", "HelloWorldChaos")
  6. os.Exit(1)
  7. }
  • Under controllers, create a helloworldchaos_controller.go file and edit it as below:
  1. package controllers
  2.  
  3. import (
  4. "github.com/go-logr/logr"
  5.  
  6. chaosmeshv1alpha1 "github.com/pingcap/chaos-mesh/api/v1alpha1"
  7.  
  8. ctrl "sigs.k8s.io/controller-runtime"
  9. "sigs.k8s.io/controller-runtime/pkg/client"
  10. )
  11.  
  12. // HelloWorldChaosReconciler reconciles a HelloWorldChaos object
  13. type HelloWorldChaosReconciler struct {
  14. client.Client
  15. Log logr.Logger
  16. }
  17.  
  18. // +kubebuilder:rbac:groups=pingcap.com,resources=helloworldchaos,verbs=get;list;watch;create;update;patch;delete
  19. // +kubebuilder:rbac:groups=pingcap.com,resources=helloworldchaos/status,verbs=get;update;patch
  20.  
  21. func (r *HelloWorldChaosReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
  22. logger := r.Log.WithValues("reconciler", "helloworldchaos")
  23.  
  24. // the main logic of `HelloWorldChaos`, it prints a log `Hello World!` and returns nothing.
  25. logger.Info("Hello World!")
  26.  
  27. return ctrl.Result{}, nil
  28. }
  29.  
  30. func (r *HelloWorldChaosReconciler) SetupWithManager(mgr ctrl.Manager) error {
  31. return ctrl.NewControllerManagedBy(mgr).
  32. //exports `HelloWorldChaos` object, which represents the yaml schema content the user applies.
  33. For(&chaosmeshv1alpha1.HelloWorldChaos{}).
  34. Complete(r)
  35. }

Note:

The comment // +kubebuilder:rbac:groups=pingcap.com… is an authority control mechanism that decides which account can access this reconciler. To make it accessible by the dashboard and chaos-controller-manager, you need to modify collector-rbac.yaml and controller-manager-rbac.yaml accordingly:

  1. - apiGroups: ["pingcap.com"]
  2. resources:
  3. - podchaos
  4. - networkchaos
  5. - iochaos
  6. - helloworldchaos # Add this line in all pingcap.com group
  7. verbs: ["*"]

Register the CRD

The HelloWorldChaos object is a custom resource object in k8s. This means you need to register the corresponding CRD in the K8s API. To do this, modify kustomization.yaml by adding the corresponding line as shown below:

  1. resources:
  2. - bases/pingcap.com_podchaos.yaml
  3. - bases/pingcap.com_networkchaos.yaml
  4. - bases/pingcap.com_iochaos.yaml
  5. - bases/pingcap.com_helloworldchaos.yaml # this is the new line

Implement the schema type

To implement the schema type for the new chaos object, add helloworldchaos_types.go in the api directory and modify it as below:

  1. package v1alpha1
  2.  
  3. import (
  4. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  5. )
  6.  
  7. // +kubebuilder:object:root=true
  8.  
  9. // HelloWorldChaos is the Schema for the helloworldchaos API
  10. type HelloWorldChaos struct {
  11. metav1.TypeMeta `json:",inline"`
  12. metav1.ObjectMeta `json:"metadata,omitempty"`
  13. }
  14.  
  15. // +kubebuilder:object:root=true
  16.  
  17. // HelloWorldChaosList contains a list of HelloWorldChaos
  18. type HelloWorldChaosList struct {
  19. metav1.TypeMeta `json:",inline"`
  20. metav1.ListMeta `json:"metadata,omitempty"`
  21. Items []HelloWorldChaos `json:"items"`
  22. }
  23.  
  24. func init() {
  25. SchemeBuilder.Register(&HelloWorldChaos{}, &HelloWorldChaosList{})
  26. }

With this file added, the HelloWorldChaos schema type is defined and can be called by the following yaml lines:

  1. apiVersion: pingcap.com/v1alpha1
  2. kind: HelloWorldChaos
  3. metadata:
  4. name: <name-of-this-resource>
  5. namespace: <ns-of-this-resource>

Make the docker image

Having the object successfully added, you can make a docker image and push it to your registry:

  1. make
  2. make docker-push

Please note that the default DOCKER_REGISTRY is localhost:5000, which is preset in hack/kind-cluster-build.sh. You can overwrite it to any registry to which you have access permission.

Run Chaos

You are almost there. In this step, you will pull the image and apply it for testing.

Note that before you pull any image for chaos-mesh (using helm install or helm upgrade), modify values.yaml of helm template to replace the default image with what you just pushed to your local registry.

In this case, the template uses pingcap/chaos-mesh:latest as the default target registry, so you need to replace it with localhost:5000, as shown below:

  1. clusterScoped: true
  2.  
  3. # Also see clusterScoped and controllerManager.serviceAccount
  4. rbac:
  5. create: true
  6.  
  7. controllerManager:
  8. serviceAccount: chaos-controller-manager
  9. ...
  10. image: localhost:5000/pingcap/chaos-mesh:latest
  11. ...
  12. chaosDaemon:
  13. image: localhost:5000/pingcap/chaos-daemon:latest
  14. ...
  15. dashboard:
  16. image: localhost:5000/pingcap/chaos-dashboard:latest
  17. ...

Now take the following steps to run chaos:

  • Get the related custom resource type for chaos-mesh:
  1. kubectl apply -f manifests/
  2. kubectl get crd podchaos.pingcap.com
  • Install Chaos Mesh:
  1. helm install helm/chaos-mesh --name=chaos-mesh --namespace=chaos-testing --set chaosDaemon.runtime=containerd --set chaosDaemon.socketPath=/run/containerd/containerd.sock
  2. kubectl get pods --namespace chaos-testing -l app.kubernetes.io/instance=chaos-mesh

The arguments —set chaosDaemon.runtime=containerd —set chaosDaemon.socketPath=/run/containerd/containerd.sock is used to to support network chaos on kind.

  • Create chaos.yaml in any location with the lines below:
  1. apiVersion: pingcap.com/v1alpha1
  2. kind: HelloWorldChaos
  3. metadata:
  4. name: hello-world
  5. namespace: chaos-testing
  • Apply the chaos.
  1. kubectl apply -f /path/to/chaos.yaml
  2. kubectl get HelloWorldChaos -n chaos-testing

Now you should be able to check the Hello World! result in the log:

  1. kubectl logs chaos-controller-manager-{pod-post-fix} -n chaos-testing
  2. # {pod-post-fix} is a random string generated by k8s, you can check yours
  3. # by kubectl get po -n chaos-testing

Next steps

Congratulations! You have just added a chaos type for Chaos Mesh successfully. Let us know if you run into any issues during the process. If you feel like doing other types of contributions, refer to [Add facilities to chaos daemon (WIP)].