Controller Architecture

March 13, 2026 ยท View on GitHub

The controller binary runs the Kubernetes controller-manager-based workflows for Radius. It watches cluster resources, reconciles them, and drives Radius APIs where Kubernetes-native automation is required.

The controller owns reconciliation and webhook behavior. It is not the primary home of resource-type authoring or UCP routing logic.

Entry Points

Quick Reference

TopicStart Here
Startupcmd/controller/cmd/root.go
Manager setuppkg/controller/service.go
Reconciler logicpkg/controller/reconciler
CRD typespkg/controller/api
Test FocusPackages
Reconcile and webhook behavior./pkg/controller/reconciler/...
Broad safety check./pkg/controller/...

Core Packages

PackageResponsibility
pkg/controller/service.gocontroller manager bootstrap
pkg/controller/reconcilerreconcilers and webhook wiring
pkg/controller/apiCRD-backed Kubernetes API types
pkg/sdkclients used to call back into Radius APIs

How It Works

The root command builds shared host options, creates the logger, and starts a single controller.Service through shared hosting.

Inside pkg/controller/service.go, the service creates a controller-runtime manager, registers API schemes, configures metrics and health probes, then registers reconcilers for recipe, deployment, deployment template, deployment resource, and Flux-oriented behavior.

Some reconcilers call back into Radius APIs using SDK clients configured with the current UCP connection. That is the main architectural bridge between the controller and the rest of the control plane.

Invariants And Constraints

  • Reconciler logic should stay idempotent.
  • Cluster watch logic should stay in reconcilers, not in provider HTTP layers.
  • Radius API calls from reconcilers should use the configured UCP connection.
  • Manager registration is the single place to confirm which controllers are part of the binary.

Change This Safely

Packages That Usually Move Together

  • pkg/controller/service.go and pkg/controller/reconciler when adding or removing controllers
  • pkg/controller/api and reconcilers when CRD shape or status handling changes
  • SDK client usage and reconciler tests when Radius API calls change

Suggested Test Scope

  • go test ./pkg/controller/...
  • Pay particular attention to reconciler and webhook tests in pkg/controller/reconciler/...

Package Dependency View

graph TD
  Root[cmd/controller/cmd]
  Host[hosting.Host + hostoptions]
  Service[pkg/controller/service.go]
  API[pkg/controller/api]
  Reconcilers[pkg/controller/reconciler]
  SDK[pkg/sdk + pkg/sdk/clients]
  CLIHelpers[pkg/cli/bicep + pkg/cli/filesystem]
  K8S[controller-runtime + client-go + Kubernetes API schemes]
  Flux[fluxcd source-controller API]
  Trace[pkg/components/trace]

  Root --> Host
  Root --> Service
  Root --> Trace
  Service --> API
  Service --> Reconcilers
  Service --> SDK
  Service --> CLIHelpers
  Service --> K8S
  Service --> Flux
  Reconcilers --> API
  Reconcilers --> SDK
  Reconcilers --> CLIHelpers
  Reconcilers --> K8S
  Reconcilers --> Flux

The important static seam is root -> service -> manager/reconcilers. The service package owns manager assembly and registration, while the reconciler packages own the real cluster automation logic.

Representative Flow

sequenceDiagram
  participant K8S as Kubernetes API
  participant Rec as DeploymentTemplateReconciler
  participant Radius as Radius client / UCP
  participant Deploy as ResourceDeploymentsClient
  participant Status as DeploymentTemplate status
  participant Out as DeploymentResource objects

  K8S->>Rec: reconcile DeploymentTemplate
  Rec->>Status: check existing operation state
  alt operation in progress
    Rec->>Deploy: continue poll with resume token
    Deploy-->>Rec: done or still running
    Rec->>Status: update phase, outputs, operation state
    Rec->>Out: create/delete DeploymentResource objects
  else update path
    Rec->>Status: ensure finalizer + observed generation
    Rec->>Deploy: create deployment if desired state changed
    Deploy-->>Rec: poller + resume token
    Rec->>Status: mark Updating and store token
  else delete path
    Rec->>Out: delete owned DeploymentResources
    Rec->>Status: remove finalizer when safe
  end

The representative controller flow is the DeploymentTemplateReconciler state machine. It shows the controller's real role in the system: reconcile cluster state, use Radius deployment APIs as the backend executor, and project outputs back into Kubernetes resources.