Self-hosted service
projectsveltos/addon-controller avatar
projectsveltos/addon-controller

Sveltos pushes one add-on definition to many clusters from one controller

Sveltos Kubernetes add-on controller programmatically deploys add-ons and applications in tens of clusters. Support for ClusterAPI powered clusters, Helm charts, kustomize ,YAMLs. Sveltos has built-in support for multi-tenancy.

589 stars53 forksGoApache-2.0

At a glance

What is it?
Sveltos is a Kubernetes add-on controller that runs in a management cluster and deploys Helm charts, raw YAML, Kustomize, Carvel ytt and Jsonnet templates across a fleet, with Profiles and ClusterProfiles splitting platform admin and tenant admin work. The interesting parts are the deployment ordering guarantees and the per-cluster configuration templating.
Who is it for?
Sveltos suits a platform engineering team that manages a fleet of Kubernetes clusters and wants add-on definitions, per-cluster configuration and rollout order declared in the management cluster rather than copied into each cluster. It is the wrong choice for a single cluster, where a Helm release in the same cluster is simpler, and the wrong choice if you cannot accept a controller with broad cluster-wide credentials and the Kubernetes API surface that implies.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One controller in the management cluster, add-ons everywhere else

Sveltos is a Kubernetes add-on controller that simplifies the deployment and management of add-ons and applications across multiple clusters. It runs in the management cluster and can programmatically deploy and manage add-ons and applications on any cluster in the fleet, including the management cluster itself.

That last clause matters more than it first appears. A fleet controller that can also target its own cluster is not a separate tooling tier, it is one system that can treat the management cluster as just another target, which removes a class of awkward exception handling from a platform team's build.

The formats are broad. The documentation states that Sveltos supports Helm charts, raw YAML, Kustomize, Carvel ytt, and Jsonnet, and the topic list on the repository adds Helm, Kustomize, ytt, jsonnet, gitops and platform-engineering. The examples directory shows how much of that is exercised in practice, with files for calico, cilium, contour, envoy, cert-manager, kyverno, istio, harbor, nats, prometheus-grafana, external-dns, external-secrets-operator, flux, autoscaler, kro, kustomize, kustomize_with_configmap, multiple_helm_charts, oci, secretref, deploy_kubevela and github-runner-scale-set-controller.

The audience is a platform team with more clusters than they have people, and the repository's badges point at a company backing it rather than a hobby project: there is a Slack invite, a LinkedIn company page, a book-a-demo link, an enterprise support contact and a list of adopters including Mirantis, Comcast, Renault and Mistral AI.

Templates are instantiated per cluster, with values that can differ

The mechanism that makes Sveltos more than a bulk apply tool is template instantiation.

The documentation explains that Sveltos allows you to represent add-ons and applications as templates, and that before deploying to managed clusters it instantiates those templates. The information needed to instantiate them can be gathered from either the management cluster or the managed clusters themselves.

That is the design decision worth internalising. The same add-on configuration is used across all of your clusters, while still allowing for some variation, such as different add-on configuration values. Sveltos lets you define add-ons and applications in a reusable way and then deploy those definitions to multiple clusters, with minor adjustments as needed.

Gathering the values from the managed cluster is the part that differs from most templating tools. A cluster can report its own region, its node labels, its capacity or its Kubernetes version, and those become inputs to the template. So a Cilium configuration can carry that cluster's own pod CIDR, and an Istio configuration can set a mesh-specific value, without a per-cluster configuration file existing anywhere.

The documentation is clear about the benefit: this can save a lot of time and effort, especially if you manage a large number of clusters. The corresponding cost is that the instantiation rules are now a piece of platform logic you have to understand, and a bug in them propagates to every cluster at once rather than to one.

Profiles for tenants, ClusterProfiles for the platform team

Sveltos offers two objects for managing cluster configurations, and the distinction is about who is allowed to do what.

ClusterProfiles apply across all clusters in any namespace, and the documentation describes them as ideal for platform admins maintaining global consistency and managing settings like networking, security, and resource allocation.

Profiles are limited to a specific namespace, which grants granular control to tenant admins. The isolation point is stated directly: this isolation ensures teams manage, from the management cluster, their managed clusters independently without impacting others.

This is the built-in multi-tenancy that the project description mentions, and it is worth understanding what it does and does not do. What it does is give you a namespace-scoped object that a tenant team can own, so a team adding an add-on to their own clusters does not need cluster-wide credentials or the ability to write a ClusterProfile. What it is not, based on what is documented here, is a general namespace tenancy model for arbitrary Kubernetes resources. The tenancy is specific to the add-on deployment objects.

The topic list on the repository includes multi-tenancy and platform-engineering, and the documentation notes that understanding the distinction between Profiles and ClusterProfiles matters for efficient setup and administration. That is the right framing: the split is a permission boundary on who can install what, and the operational work is deciding which add-ons are fleet-wide and which are tenant-owned.

Deployment order is a guarantee, not a hope

The rollout semantics are the part of Sveltos that a hand-rolled GitOps loop usually gets wrong, and they are stated precisely.

Add-ons within a Profile or ClusterProfile are deployed in the exact order they appear, which the documentation describes as ensuring a predictable and controlled rollout. ClusterProfiles can depend on others, guaranteeing that dependent add-ons only deploy after their dependencies are fully operational.

So there are two ordering mechanisms. Intra-profile ordering is positional, the order in the list. Inter-profile ordering is a dependency graph, and it is a real dependency, not a hint. A network plugin that must be running before the workload that uses it can express that, and the controller will not deploy the workload until the dependency reports as fully operational.

On top of that sits an event-driven framework. The documentation says this framework offers additional flexibility by allowing add-ons and applications to be deployed in response to specific events, enabling dynamic and adaptable deployments based on your needs. This is the mechanism that replaces the imperative pipeline in a CI job: instead of running helm upgrade in a sequence, you declare what should exist and under what conditions.

The mechanism is also where the operational risk sits. Because the ordering guarantees are enforced by the controller rather than by your script, a wrong dependency declaration produces a fleet that is consistently in the wrong state, and the debug path is the controller's status rather than a log line in your CI job.

How the add-on deployment actually selects clusters

The documentation describes the add-on deployment mechanism in two steps, and the vocabulary is worth pinning down because it is what you write in the manifest.

First, from the management cluster, you select one or more clusters with a Kubernetes label selector. Second, you list which add-ons need to be deployed on such clusters.

Two terms carry the definitions. Clusters represents both a CAPI cluster or any other Kubernetes cluster registered with Sveltos, and addons represents either a Helm release, Kubernetes resource YAMLs, or Kustomize resources.

The CAPI integration is the notable part, because it means the fleet can include clusters that the controller itself did not create. The dependency list confirms it at the source level, with sigs.k8s.io/cluster-api and sigs.k8s.io/cluster-api/api both at v1.14.3, alongside controller-runtime at v0.25.2 and the Kubernetes libraries at 0.37.1.

The documentation then gives a worked example: require that any CAPI Cluster with the label env: prod has a Kyverno helm chart at version v3.0.1 deployed, plus the Kubernetes resources contained in the referenced Secret. That is the shape of a real spec, a label selector on the cluster and a set of add-ons with a source and a version.

The licence is MIT in the package metadata, and the image labels in the Dockerfile record the same Apache-2.0 terms, so the project is Apache-2.0 with a permissive licence that includes an explicit patent grant.

A distroless controller image and a Makefile that targets several architectures

The build is a standard kubebuilder-style controller, and the Dockerfile is worth reading because it is short and says what the project values.

The builder stage is pinned:

dockerfile
FROM golang:1.27.1 AS builder

ARG BUILDOS
ARG TARGETARCH

The go.mod file matches, with module path github.com/projectsveltos/addon-controller and go 1.27.1. The build copies the api, lib, controllers, pkg and internal directories along with cmd/main.go, then compiles a static binary with CGO disabled and cross-compilation variables:

dockerfile
RUN CGO_ENABLED=0 GOOS=$BUILDOS GOARCH=$TARGETARCH go build -a -o manager cmd/main.go

The runtime image is distroless:

dockerfile
FROM gcr.io/distroless/static:nonroot

USER 65532:65532

ENTRYPOINT ["/manager"]

A static, non-root, distroless image is the right default for a controller that runs with cluster-scoped credentials, since it removes both a shell and a package manager from the attack surface of a process that talks to the Kubernetes API.

The Makefile shows the multi-architecture intent, with ARCH set to amd64 or arm64 depending on the host architecture, a registry and image name defaulting to projectsveltos and addon-controller, and a test target that downloads envtest assets for Kubernetes 1.37.0. There is a Dockerfile_WithGit alongside the main one, and a .devcontainer/ directory, so developing the controller itself runs in a container too. There is also a renovate.json, which means the dependency versions in go.mod are being updated by a bot rather than by hand.

A security posture that goes beyond the usual badges

The badge row tells you more than a typical open-source project bothers to publish.

There is a CI workflow badge, and separately an OpenSSF Scorecard badge, which is the open source security scorecard that evaluates a project against a set of practices such as branch protection, signed releases and dependency review tooling. There is a CodeQL workflow badge, meaning the code is analysed with GitHub's semantic analysis engine on every change. And there is a Docker pulls badge pointing at the image on Docker Hub.

Alongside the code there is a SECURITY.md at the repository root, plus CODE_OF_CONDUCT.md and CONTRIBUTING.md. The scoring and the CodeQL analysis are the substantive ones, since a project that scores well on the scorecard has demonstrably set up the practices that reduce supply chain risk, and CodeQL catches a class of bug that a compiler does not.

The dependency list shows the security posture in practice as well. sigstore/cosign/v3 and sigstore/sigstore are both present, which means the project verifies signatures on the artefacts it pulls, and github.com/google/go-containerregistry, oras.land/oras-go/v2 and opencontainers/image-spec are there for the OCI handling that goes with Helm charts and OCI-sourced add-ons. The examples directory includes an oci.yaml, so that path is exercised rather than aspirational.

Upkeep is strong. The last push was on 2026-10-20, and the releases are v1.16.0 on 2026-10-02, v1.15.0 on 2026-09-12 and v1.14.0 on 2026-08-20. A minor release roughly every three weeks, from a project that is still shipping features, is the pattern of an actively developed controller.

Editorial conclusion

Sveltos suits a platform engineering team that manages a fleet of Kubernetes clusters and wants add-on definitions, per-cluster configuration and rollout order declared in the management cluster rather than copied into each cluster. It is the wrong choice for a single cluster, where a Helm release in the same cluster is simpler, and the wrong choice if you cannot accept a controller with broad cluster-wide credentials and the Kubernetes API surface that implies. Before deploying it, read the examples/ directory, since calico.yaml, istio.yaml, cert-manager.yaml and the kustomize and OCI examples are the fastest way to see whether the templating model fits how your own add-ons are parameterised.

Frequently asked questions

What is the difference between a Profile and a ClusterProfile in Sveltos?

ClusterProfiles apply across all clusters in any namespace and are described as ideal for platform admins maintaining global consistency. Profiles are limited to a specific namespace, which grants granular control to tenant admins so teams manage their managed clusters independently without impacting others. The description also notes Sveltos has built-in support for multi-tenancy.

Which add-on formats does the Sveltos add-on controller support?

The documentation states that Sveltos supports a variety of add-on formats, including Helm charts, raw YAML, Kustomize, Carvel ytt, and Jsonnet. It runs in the management cluster and can deploy to any cluster in the fleet, including the management cluster itself, and supports ClusterAPI powered clusters.

How does Sveltos control the order in which add-ons are deployed?

Add-ons within a Profile or ClusterProfile are deployed in the exact order they appear, which the documentation describes as ensuring a predictable and controlled rollout. ClusterProfiles can also depend on others, guaranteeing that dependent add-ons only deploy after their dependencies are fully operational, and an event-driven framework allows deployment in response to specific events.

Official sources

  1. License: Apache-2.0
  2. projectsveltos/addon-controller on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/projectsveltos-addon-controller.svg)](https://hysenlabs.com/projects/projectsveltos-addon-controller)

Was this useful?