Trust anchor rotation reference
BEL provides automated trust anchor rotation in
the form of a Kubernetes operator that runs on the cluster and a companion
linkerd-trust CLI extension. See the
trust-rotation configuration guide for
an end-to-end walkthrough, and the BEL CLI reference for the
linkerd trust commands.
Operator behavior and progress are tracked by a single cluster-scoped
TrustAnchorRotation custom resource (API group trust.linkerd.io, version
v1alpha1, short name tar). The operator chart creates one named cluster by
default. You configure the desired behavior through its spec, and the operator
reports observed rotation progress through its status subresource.
cert-manager prerequisite
The trust-rotation operator does not mint certificates itself. It builds on top of cert-manager, which remains responsible for generating and renewing the trust anchor and identity issuer. The operator provides the orchestration layer above cert-manager: it maintains the Linkerd trust bundle, refreshes the Linkerd control plane when the bundle changes, gates phase transitions on observed convergence, and makes the workflow resumable across operator restarts.
A few practical consequences of this division of labor:
cert-manager is a hard prerequisite. Without a working cert-manager installation that issues the trust anchor and identity issuer certificates, the operator has nothing to orchestrate.
trust-manager is no longer required. The trust-rotation operator maintains the
linkerd-identity-trust-rootsConfigMap directly from the cert-manager-managed trust anchor secrets. After the initial bundle has been bootstrapped, trust-manager is not on the path.Renewing certificates remains a cert-manager concern. The operator reacts to externally-initiated certificate changes (such as a
cmctl renewon the trust anchor) by driving the rest of the rotation; it does not trigger issuance directly.
Pairing with the data plane operator
During the PropagatingTrustRoots phase the data plane operator pushes the
accelerated workload-certificate refresh interval into each meshed pod by
injecting the config.linkerd.io/proxy-additional-env annotation. This
shortened interval lets workloads renew their identity certificates passively
during through the issuer switch (RenewingWorkloadCerts phase), removing the
need for one of the data plane restarts in a full rotation: two restarts instead
of three.
Without the data plane operator, the accelerated interval has no consumer. At the issuer-renewal step, meshed workloads then have to either be restarted explicitly, or be left to renew their identity certificates at the proxy’s normal 24-hour interval. Either path eventually moves the cluster onto the new issuer; the restart is just the fast option.
How it works
At a high level, a full rotation moves through three groups of steps. First, bundle expansion: the trust bundle grows to hold both the old and new trust anchors, and that expanded bundle is propagated across the control plane and meshed workloads so every proxy trusts both anchors at once. Second, the issuer switch: the identity issuer is renewed onto the new anchor and workloads renew their certificates onto that new path while the expanded bundle keeps mTLS working throughout. Third, bundle reduction: once every workload has converged on the new issuer, the bundle shrinks back to the single new anchor and the change is propagated again, returning the cluster to a clean steady state.
The operator is driven by a cluster-scoped TrustAnchorRotation custom
resource. Its status subresource exposes a small state machine, surfaced
through the status.phase field, that the operator advances based on what it
sees in the cluster:
Synced: steady state. The trust anchor and identity issuer are aligned and every meshed workload chains to them.
RefreshingControlPlane: the desired trust bundle has changed and the Linkerd control plane has not yet caught up. This phase fires both when the bundle expands at the start of a rotation and when it is reduced at the end.
PropagatingTrustRoots: the control plane is on the expanded bundle and meshed workloads are being restarted to pick it up.
WaitingForIdentityRotation: the expanded bundle has converged everywhere it needs to converge, and the operator is waiting for the user (or cert-manager) to renew the identity issuer. This is the one intentional manual step that remains.
RenewingWorkloadCerts: the issuer has been renewed and the operator is waiting for workloads to renew their identity certificates onto the new issuer path. To keep this window short, the operator publishes an accelerated renewal interval (default 5 minutes) that the data plane honors when paired with the data plane operator (see below).
RemovingOldTrustRoots: the new issuer is in place, workloads have converged, and the bundle is being reduced back to a single root.
The operator never advances unless the preconditions of the next phase are
observable. If a rollout stalls, the rotation simply parks in its current phase
and reports a blocking message in TrustAnchorRotation.status.blockingMessage,
so on-call engineers can see what the operator is waiting on without
reconstructing the system state by hand.
TrustAnchorRotation spec
The spec holds the desired configuration for trust-anchor rotation behavior.
| Field | Description |
|---|---|
workloadCertificateRefreshInterval | Interval to temporarily configure for workload certificate refreshes while the rotation is accelerating certificate renewal. Default 5m. |
TrustAnchorRotation status
The status subresource is populated by the operator and reflects the observed
state of the rotation. It is the surface mirrored by linkerd trust inspect and
by the operator’s Prometheus metrics.
| Field | Description |
|---|---|
phase | Current high-level phase of the rotation workflow (see Phases below). Default Synced. |
blockingMessage | Human-readable message describing why the rotation is currently waiting for convergence, if any. |
activeIssuerFingerprint | Fingerprint of the Linkerd identity issuer certificate currently observed as active. |
previousAnchorFingerprint | Fingerprint of the operator-managed linkerd-previous-anchor copy used to preserve overlap during rotation. |
lastPhaseTransitionTime | Time when the rotation last entered the current phase. |
workloadCertificateRefreshInterval | Effective temporary workload certificate refresh interval currently being enforced, if any. |
trustBundle | Convergence status for trust-bundle propagation across the relevant pods. See Convergence groups. |
workloadCertificates | Convergence status for workload certificate rotation across meshed workloads. See Convergence groups. |
sourceFingerprints | Fingerprints observed for the configured trust-anchor sources. See status.sourceFingerprints. |
conditions | Additional condition records describing notable rotation states. See status.conditions. |
Phases
status.phase advances through a state machine that the operator gates on
observed cluster state. The full set of values:
| Phase | Description |
|---|---|
Synced | Steady state. The trust anchor and identity issuer are aligned and every meshed workload chains to them. |
RefreshingControlPlane | The desired trust bundle has changed and the Linkerd control plane has not yet caught up. Fires both when the bundle expands and when it is reduced. |
PropagatingTrustRoots | The control plane is on the expanded bundle and meshed workloads are being restarted to pick it up. |
WaitingForRemoteClusters | Waiting for remote clusters to converge (multicluster rotations). |
WaitingForIdentityRotation | The expanded bundle has converged and the operator is waiting for the identity issuer to be renewed. |
RenewingWorkloadCerts | The issuer has been renewed and the operator is waiting for workloads to renew their identity certificates. |
RemovingOldTrustRoots | The new issuer is in place, workloads have converged, and the bundle is being reduced back to a single root. |
Convergence groups
Both status.trustBundle and status.workloadCertificates share the same
shape, reporting progress for a group of pods.
| Field | Description |
|---|---|
status | Aggregate convergence state for the group, one of Converging, Converged. |
convergedPods | Number of target pods currently observed to have converged. |
targetPods | Total number of pods included in this convergence group. |
status.sourceFingerprints
Each entry reports the observed fingerprint for one configured trust-anchor source.
| Field | Description |
|---|---|
fingerprint | Fingerprint of the certificate currently loaded from the source. |
kind | Backing resource type providing the certificate material, one of secret, configMap, inline. Default secret. |
name | Name of the referenced Secret or ConfigMap, when applicable. |
namespace | Namespace of the referenced Secret or ConfigMap, when applicable. |
status.conditions
Each entry is a single condition describing a stable observed state transition.
| Field | Description |
|---|---|
type | Condition type identifier. |
status | Whether this condition is currently active, one of True, False. |
reason | Programmatic reason identifier for the current condition state. |
message | Human-readable details for the condition. |
lastTransitionTime | Time when this condition last changed status, reason, or message. |
Example
apiVersion: trust.linkerd.io/v1alpha1
kind: TrustAnchorRotation
metadata:
name: cluster
spec:
workloadCertificateRefreshInterval: 5m
status:
phase: PropagatingTrustRoots
lastPhaseTransitionTime: "2026-06-01T12:00:00Z"
blockingMessage:
"Waiting for 2 pod(s) to converge on the expanded trust bundle"
activeIssuerFingerprint: "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
previousAnchorFingerprint: "0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0"
workloadCertificateRefreshInterval: 5m
trustBundle:
status: Converging
convergedPods: 10
targetPods: 12
workloadCertificates:
status: Converged
convergedPods: 12
targetPods: 12
sourceFingerprints:
- kind: secret
name: linkerd-trust-anchor
namespace: cert-manager
fingerprint: "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
- kind: secret
name: linkerd-previous-anchor
namespace: linkerd
fingerprint: "0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0"
conditions:
- type: OutOfOrderIssuerRotation
status: "False"
reason: IssuerRotationInOrder
message:
"identity issuer rotation is not ahead of trust-bundle convergence"
lastTransitionTime: "2026-06-01T12:00:00Z"
You can watch the operator-managed status in real time (this requires
yq):
watch -d -n 1 'kubectl get trustanchorrotations.trust.linkerd.io cluster \
-o yaml | yq .status'