Skip to content

Architecture

Big picture

Litmus has two planes. The Chaos Control Plane (ChaosCenter) is the central tool that constructs, schedules, and visualizes chaos workflows. The Chaos Execution Plane is a chaos agent plus operators that run and monitor the experiment inside a target Kubernetes cluster. This split is stated directly in the README (README.md:31-52).

This repository holds the control plane (under chaoscenter/). The execution plane operators live in separate repositories: chaos-operator reconciles the ChaosEngine resource, chaos-runner starts the experiment job, litmus-go injects the fault, and chaos-exporter exposes results as Prometheus metrics.

Components

graphql/server

The GraphQL API and the heart of the control plane. It is a gqlgen-generated schema served over Gin, with MongoDB as the state store. The server entry point is chaoscenter/graphql/server/server.go:94, the executable schema is built at server.go:124, services are wired at server.go:185, and the /query endpoint is mounted at server.go:192.

authentication

A separate REST authentication service under chaoscenter/authentication/, with a dex integration under chaoscenter/authentication/dex-server/. The entry point is chaoscenter/authentication/api/main.go.

subscriber

The chaos agent that runs in each target cluster. It dials back to the control plane over a websocket and applies pushed manifests to the cluster. Its entry point is chaoscenter/subscriber/subscriber.go:138, and it starts listening for actions at subscriber.go:159.

web, event-tracker, upgrade-agents

The React UI (chaoscenter/web/), an event tracker, and upgrade agents round out the control plane services.

How a request flows

This traces re-running an existing experiment (the RunChaosExperiment mutation) from the API to the target cluster. All anchors are at the pinned commit.

  1. chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go:24 RunChaosExperiment is the resolver entry point. It runs an RBAC check with authorization.ValidateRole at :31, loads the experiment from MongoDB at :43, and calls RunChaosWorkFlow at :50.
  2. chaoscenter/graphql/server/pkg/chaos_experiment_run/handler/handler.go:670 RunChaosWorkFlow confirms the target infra is active, sorts revisions newest-first to pick the latest manifest, and branches to RunCronExperiment if the kind is cronworkflow.
  3. handler.go:934 GenerateExperimentManifestWithProbes expands probes into the manifest, then handler.go:944 calls chaos_infrastructure.SendExperimentToSubscriber(...).
  4. chaoscenter/graphql/server/pkg/chaos_infrastructure/infra_utils.go:226 SendExperimentToSubscriber delegates to SendRequestToSubscriber at infra_utils.go:206, which pushes the action onto the agent's in-memory channel at infra_utils.go:220 (observer <- newAction).
  5. The subscriber in the target cluster receives the action. chaoscenter/subscriber/subscriber.go:159 starts AgentConnect (chaoscenter/subscriber/pkg/requests/webhook.go:16), which builds the subscription { infraConnect(...) } query at webhook.go:17 and dials the websocket at webhook.go:30, then applies the pushed manifest to Kubernetes.
  6. On the server side, the subscription resolver is chaoscenter/graphql/server/graph/chaos_infrastructure.resolvers.go:272 InfraConnect. It registers the channel in data_store.Store.ConnectedInfra[infraID] at :287, then waits on ctx.Done() to delete the channel and mark the infra inactive on disconnect.

Key design decisions

The control plane never connects out to a target cluster. Instead, each target cluster's subscriber dials back to the control plane on startup and holds an infraConnect GraphQL subscription open (chaoscenter/subscriber/pkg/requests/webhook.go:17, chaos_infrastructure.resolvers.go:272). At experiment time the server just pushes an action onto that open channel (infra_utils.go:219).

The benefit is reach: a target cluster behind NAT or a firewall only needs outbound connectivity, and one ChaosCenter can govern many clusters.

The trade-off is that connection state lives in the GraphQL server process memory. The ConnectedInfra map of channels is part of StateData in chaoscenter/graphql/server/pkg/data-store/store.go:10-18. A server restart drops every agent connection until each redials, and the state is not shared across replicas. The InfraConnect resolver force-disconnects a duplicate connection for the same infra ID (chaos_infrastructure.resolvers.go:281-285), so the control plane effectively assumes a singleton.

Extension points

  • Chaos custom resources (README.md:39-52): ChaosExperiment is the installable fault template and supports BYOC (bring-your-own-chaos) for third-party fault tooling; ChaosEngine binds a fault to a target and defines steady-state probes; ChaosResult holds the verdict that the exporter reads.
  • ChaosHub: experiment bundles shared and versioned through litmuschaos/chaos-charts.
  • Resilience probes: http, cmd, k8s, and prom probes defined under chaoscenter/graphql/server/pkg/probe/.
  • GitOps: experiment sync under chaoscenter/graphql/server/pkg/gitops.