The Linkerd Trust Rotator Operator automates the zero-downtime rotation of Linkerd trust anchors (root CA entities) and the propagation of new certificates across both control and data planes. It ensures seamless certificate renewal without manual restarts or service disruption.
The operator continuously inspects the Linkerd trust bundles, detects changes, and coordinates the rotation process in a controlled, verifiable manner.
In standard Linkerd setups, the trust anchor (root CA) must be rotated periodically to maintain cluster security. Manual rotation requires careful coordination between multiple Secrets, ConfigMaps, and workload restarts.
The Linkerd Trust Rotator Operator replaces this manual procedure with an automated, deterministic process that:
- Verifies the integrity of trust bundles.
- Synchronizes
trust-anchorandprevious-trust-anchorSecrets. - Orchestrates a phased restart of control-plane and data-plane workloads.
- Validates connectivity and proxy health through automated linkerd check jobs.
The operator is designed for environments where continuous availability and minimal human intervention are required.
- Automated CA rotation: Detects trust anchor divergence and initiates rotation automatically.
- Zero-downtime rollout: Sequentially restarts workloads with annotation-based selection and resumable progress tracking.
- Safe verification: Runs
linkerd check --proxyjobs during rollout to confirm successful proxy reloads. - Configurable protection policy: Supports delay windows, retry limits, and re-trigger after cleanup.
- Status observability: Provides detailed
.statusphase, progress, retries, and trust-bundle fingerprints.
- cert-manager: v1.14 or newer – provides CA and issuer management
- trust-manager: v0.18 or newer – distributes public trust bundles to ConfigMaps
The operator is configured via the LinkerdTrustRotation custom resource.
The specification fields are:
| Section | Description |
|---|---|
| linkerd | Defines trust-anchor resources, ConfigMap, and namespace. |
| trigger | Controls when the rotation starts (on ConfigMap or Secret change). |
| rollout | Selects workloads and strategies for restarts. |
| protection | Defines safety windows, retry limits, and validation jobs. |
| dryRun | Enables simulation mode without applying changes. |
See the sample for more details.
The rotation process consists of several controlled phases:
- Inspection: Load and parse trust bundle from
linkerd-identity-trust-rootsConfigMap. - Secret validation: Verify existence of current and previous trust-anchor Secrets; bootstrap previous if missing.
- Control-plane restart: Sequentially restart all Linkerd control-plane Deployments.
- Data-plane rollout: Restart workloads (Deployments, StatefulSets, DaemonSets, and CRs) annotated with
linkerd.io/inject=enabled. - Verification: Launch
linkerd checkjobs viaServiceAccount linkerd-checkto validate proxy readiness. - Cleanup and hold: Optionally re-trigger rollout after cleanup of old secrets and apply a safety delay.
Each phase updates the CR status, allowing full observability and safe resume on controller restart.
The operator follows a modular, layered architecture:
┌──────────────────────────────────────────┐
│ Reconciler │
│ Watches LinkerdTrustRotation CRs │
│ and orchestrates the full lifecycle │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Secret Manager │
│ - Loads and validates trust-anchor │
│ - Bootstraps previous secret if missing │
│ - Computes SHA256 fingerprints │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ ConfigMap Manager │
│ - Loads Linkerd trust-roots bundle │
│ - Detects overlap (bundle state) │
│ - Triggers rotation condition │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Rollout Manager │
│ - Restarts control-plane first │
│ - Then restarts data-plane workloads │
│ - Supports resumable progress, retries │
│ - Validates results via `linkerd check` │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Status Manager │
│ - Tracks .status.phase, trust info, │
│ rollout cursor, retries, progress │
│ - Patches CR status atomically │
└──────────────────────────────────────────┘
The operator updates .status with structured progress and diagnostic information.
| Field | Description |
|---|---|
| phase | Current phase of rotation (e.g., Inspecting, RollingDataPlane, Succeeded). |
| trust.bundleState | single or overlap – number of CAs in trust bundle. |
| trust.currentFP / previousFP | SHA-256 fingerprints of trust-anchor Secrets. |
| progress.dataPlanePercent | Percentage of workloads updated and ready. |
| retries.count / lastError | Retry counter and last encountered error. |
| cursor.planHash / next / total | Internal rollout plan tracking for resumable execution. |
See the status field of the CRD for
more details.
The operator spawns ephemeral Kubernetes Jobs running linkerd check during and after rotation.
These Jobs use a dedicated ServiceAccount with restricted permissions.
See linkerd_check.yaml for more details.
- go version v1.24.0+
- docker version 17.03+.
- kubectl version v1.11.3+.
- Access to a Kubernetes v1.11.3+ cluster.
Build and push your image to the location specified by IMG:
make docker-build docker-push IMG=<some-registry>/linkerd-trust-rotator:tagNOTE: This image ought to be published in the personal registry you specified. And it is required to have access to pull the image from the working environment. Make sure you have the proper permission to the registry if the above commands don’t work.
Install the CRDs into the cluster:
make installDeploy the Manager to the cluster with the image specified by IMG:
make deploy IMG=<some-registry>/linkerd-trust-rotator:tagNOTE: If you encounter RBAC errors, you may need to grant yourself cluster-admin privileges or be logged in as admin.
Create instances of your solution You can apply the samples (examples) from the config/sample:
kubectl apply -k config/samples/NOTE: Ensure that the samples has default values to test it out.
Delete the instances (CRs) from the cluster:
kubectl delete -k config/samples/Delete the APIs(CRDs) from the cluster:
make uninstallUnDeploy the controller from the cluster:
make undeployFollowing the options to release and provide this solution to the users.
- Build the installer for the image built and published in the registry:
make build-installer IMG=<some-registry>/linkerd-trust-rotator:tagNOTE: The makefile target mentioned above generates an 'install.yaml' file in the dist directory. This file contains all the resources built with Kustomize, which are necessary to install this project without its dependencies.
- Using the installer
Users can just run 'kubectl apply -f ' to install the project, i.e.:
kubectl apply -f https://raw.githubusercontent.com/<org>/linkerd-trust-rotator/<tag or branch>/dist/install.yaml- Build the chart using the optional helm plugin
kubebuilder edit --plugins=helm/v1-alpha- See that a chart was generated under 'dist/chart', and users can obtain this solution from there.
NOTE: If you change the project, you need to update the Helm Chart using the same command above to sync the latest changes. Furthermore, if you create webhooks, you need to use the above command with the '--force' flag and manually ensure that any custom configuration previously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml' is manually re-applied afterwards.
NOTE: Run make help for more information on all potential make targets
More information can be found via the Kubebuilder Documentation
Copyright 2025 Edenlab.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.