Linkerd Reference¶
Scope
Look-up facts for Linkerd 2.x: versions and release artifacts, compatibility matrices, ports, control plane components, certificate defaults, CRDs, annotations, published benchmark numbers, and notable advisories. For why things work this way, see the Explanation. For step-by-step tasks, see the How-to Guides. Facts were checked against the linkerd/website docs (2-edge tree) and linkerd/linkerd2 Helm charts on 2026-09-25.
Versions and Release Artifacts¶
Linkerd announces major versions (2.15, 2.16, …). Each version maps to one edge release tag in the open-source repo. Since February 2024 (Linkerd 2.15), the open-source project no longer publishes stable release artifacts. Vendors publish them instead; the only listed distribution is Buoyant Enterprise for Linkerd (BEL).
| Version | Announced | Corresponding edge release | Headline changes |
|---|---|---|---|
| 2.20 | 2026-06-23 | edge-26.6.3 |
Rate-limit-aware load balancing and circuit breaking (experimental), destination controller memory cut by up to ~85%, inbound metrics near parity with outbound, native sidecars on by default, Kubernetes up to 1.35, Gateway API up to 1.5.1 |
| 2.19 | 2025-10-31 | edge-25.10.7 |
Post-quantum key exchange (ML-KEM-768 hybrid) by default, proxy crypto moved from ring to aws-lc, native sidecars promoted to beta, connections to undefined ClusterIP Service ports blocked |
| 2.18 | 2025-04-23 | edge-25.4.4 |
Protocol declaration through Service appProtocol, GitOps-friendly declarative multicluster Link resources, Gateway API 1.2.1 (last release to install Gateway API CRDs by default), experimental Windows proxy build |
| 2.17 | 2024-12-05 | edge-24.11.8 |
Egress visibility and control (EgressNetwork), local rate limiting (HTTPLocalRateLimitPolicy), federated services, OpenTelemetry tracing |
| 2.16 | 2024-08-13 | edge-24.8.2 |
Retries, timeouts and per-route metrics on Gateway API HTTPRoute/GRPCRoute, IPv6, policy audit mode, /shutdown endpoint disabled by default |
| 2.15 | 2024-02-21 | edge-24.2.4 |
Mesh expansion (non-Kubernetes workloads), SPIFFE identities, native sidecar support (alpha), end of open-source stable artifacts |
Source: linkerd.io/data/versions.yaml and the release announcement posts in linkerd/website.
| Artifact | Latest (as of 2026-09-25) | Producer | Versioning | Notes |
|---|---|---|---|---|
| Edge release | edge-26.9.3 (2026-09-16, proxy v2.369.0) |
Linkerd project (open source) | edge-YY.M.N (year, month, count in month) |
Weekly or near-weekly. Considered production-ready unless marked "not recommended" in its release notes. Not semantically versioned. |
| Version tag | version-2.20 |
Linkerd project | version-2.X |
Git tag that marks the edge release for a major version. |
| Stable release | BEL 2.20.2 (release date TBD, not verified) |
Buoyant (Buoyant Enterprise for Linkerd) | Semantic versioning | Point releases with backports. BEL 2.20.0 shipped without FIPS. BEL 2.20.1 added FIPS support. |
Install scripts default to edge
Both https://run.linkerd.io/install and https://run.linkerd.io/install-edge install the latest edge CLI unless LINKERD2_VERSION is set (checked in linkerd/website run.linkerd.io/public/).
Kubernetes Compatibility¶
| Linkerd version | Minimum Kubernetes | Maximum Kubernetes |
|---|---|---|
| 2.14 | 1.21 | 1.28 |
| 2.15 | 1.22 | 1.29 |
| 2.16 | 1.22 | 1.29 |
| 2.17 | 1.22 | 1.31 |
| 2.18 | 1.22 | 1.32 |
| 2.19 | 1.22 | 1.35 |
| 2.20 | 1.31 | 1.35 |
The linkerd-control-plane chart on main declares kubeVersion: ">=1.31.0-0". Edge releases support the Kubernetes versions that are easy to get on major clouds at release time. BEL 2.20.2 adds official support for Kubernetes 1.36 (Buoyant release notes, not independently verified).
Gateway API Compatibility¶
| Linkerd versions | Gateway API versions | HTTPRoute version | GRPCRoute version |
|---|---|---|---|
| 2.15 to 2.17 | 0.7 to 1.1.1 | v1beta1 |
v1alpha2 |
| 2.18 to 2.19 | 1.1.1 to 1.2.1 | v1 |
v1 |
| 2.20 | 1.2.1 to 1.5.1 | v1 |
v1 |
The linkerd-crds chart defaults to installGatewayAPI: false, so on current releases you install Gateway API CRDs yourself. Linkerd 2.14 was the first mesh to pass Gateway API Mesh profile conformance (per the 2.18 announcement).
Ports¶
| Port | Component | Purpose |
|---|---|---|
| 4140 | linkerd-proxy | Outbound listener. iptables redirects the app's outgoing TCP here. |
| 4143 | linkerd-proxy | Inbound listener. iptables redirects incoming TCP here. |
| 4190 | linkerd-proxy | Control port (for example the tap API). |
| 4191 | linkerd-proxy | Admin port: Prometheus /metrics, readiness and liveness. |
| 8086 | destination | Destination gRPC API used by proxies. |
| 8090 | destination (policy container) | Policy gRPC API used by proxies. |
| 8080 | identity | Identity (CSR signing) gRPC API. |
| 8443 | proxy-injector, sp-validator | Admission webhooks (exposed on Service port 443). |
| 9443 | destination (policy container) | Policy validating webhook (policy-https). |
| 9990 / 9995 / 9996 / 9997 | identity / proxy-injector / destination / sp-validator | Component admin (metrics, health). |
The proxy runs as UID 2102. linkerd-init skips packets owned by that UID so that proxy traffic is not redirected back into the proxy. On private GKE clusters, the docs say to open tcp:8443, tcp:8089 and tcp:9443 from the API server to nodes for the injector, policy validator and viz tap webhooks.
Control Plane Components¶
Deployment (namespace linkerd) |
Containers | Role |
|---|---|---|
linkerd-destination |
destination (Go), sp-validator (Go), policy (Rust policy controller), linkerd-proxy |
Service discovery, endpoint and identity metadata, ServiceProfile validation, policy API and policy admission webhook |
linkerd-identity |
identity, linkerd-proxy |
Certificate authority: signs proxy CSRs |
linkerd-proxy-injector |
proxy-injector, linkerd-proxy |
Mutating admission webhook that adds the proxy |
linkerd-heartbeat (CronJob) |
heartbeat |
Daily anonymous usage report. Disable it with disableHeartBeat: true. |
Extensions are installed separately: linkerd-viz (namespace linkerd-viz: dashboard web, metrics-api, tap, tap-injector, optional Prometheus), linkerd-multicluster (linkerd-gateway and service-mirror controllers), linkerd-jaeger, and the deprecated linkerd-smi. linkerd-cni is an optional DaemonSet that replaces linkerd-init.
Identity and Certificate Defaults¶
| Item | Default | Source |
|---|---|---|
| Proxy (leaf) certificate lifetime | 24 h (identity.issuer.issuanceLifetime: 24h0m0s), renewed automatically |
Chart values, mTLS docs |
| Clock skew allowance | 20 s | Chart values |
Trust anchor generated by linkerd install |
Expires after 365 days, rotated manually | mTLS docs |
Issuer certificate and key generated by linkerd install |
Expire after one year. Rotate manually or with cert-manager. | mTLS docs |
| Proxy identity name | <serviceaccount>.<namespace>.serviceaccount.identity.linkerd.cluster.local |
Policy reference |
| Proxy private key | Generated at startup and kept in a tmpfs emptyDir. It never leaves the pod. |
mTLS docs |
| TLS for meshed traffic | TLS 1.3, hybrid ML-KEM-768 + X25519 key exchange, AES_128_GCM cipher suite (docs). The 2.19 blog says AES_256_GCM support was added. | mTLS docs, 2.19 announcement |
| Non-Kubernetes workloads | SPIFFE IDs issued by SPIRE (since 2.15) | 2.15 announcement |
Default Inbound Policies¶
The cluster-wide value comes from proxy.defaultInboundPolicy. You can override it with the config.linkerd.io/default-inbound-policy annotation on a namespace or pod. The value is fixed when the pod starts.
| Value | Allows |
|---|---|
all-unauthenticated |
All traffic (default) |
all-authenticated |
Meshed clients from this cluster or linked clusters |
cluster-authenticated |
Meshed clients in the same cluster |
cluster-unauthenticated |
Meshed and non-meshed clients in the same cluster |
deny |
Nothing, unless a policy CRD allows it |
audit |
Everything, but requests that would be denied are flagged in logs and metrics |
When policy denies HTTP traffic, the proxy returns 403. It refuses other denied traffic at the TCP level.
Custom Resources¶
| Kind | API group / version | Purpose | Status |
|---|---|---|---|
Server |
policy.linkerd.io/v1beta3 |
Policy target: one port on a set of pods. accessPolicy is deny (default) or audit. |
Current |
AuthorizationPolicy |
policy.linkerd.io/v1alpha1 |
Maps authentications to a Server, HTTPRoute, GRPCRoute or Namespace |
Current (preferred) |
MeshTLSAuthentication |
policy.linkerd.io/v1alpha1 |
Allowed mesh identities or ServiceAccounts | Current |
NetworkAuthentication |
policy.linkerd.io/v1alpha1 |
Allowed client CIDRs | Current |
ServerAuthorization |
policy.linkerd.io/v1beta1 |
Older per-Server authorization |
Superseded by AuthorizationPolicy |
HTTPLocalRateLimitPolicy |
policy.linkerd.io/v1alpha1 |
Per-Server local rate limits (total, per client, overrides) |
Since 2.17 |
EgressNetwork |
policy.linkerd.io/v1alpha1 |
Classifies traffic leaving the cluster. trafficPolicy: Allow or Deny. |
Since 2.17 |
HTTPRoute (Linkerd) |
policy.linkerd.io |
Linkerd's pre-standard HTTPRoute | Supported, but new work targets Gateway API |
HTTPRoute, GRPCRoute |
gateway.networking.k8s.io/v1 |
Routing, retries, timeouts, per-route metrics and policy | Current |
TLSRoute, TCPRoute |
gateway.networking.k8s.io |
Egress routing for TLS or TCP traffic | Current (Gateway API channel dependent) |
ServiceProfile |
linkerd.io/v1alpha2 |
Legacy per-route metrics, retries, timeouts | Frozen since 2.16. It blocks HTTPRoute retries and circuit breaking for that Service. |
ExternalWorkload |
workload.linkerd.io/v1beta1 |
Registers a non-Kubernetes workload (mesh expansion) | Since 2.15 |
Link |
multicluster.linkerd.io/v1alpha3 |
Connection to a remote cluster for service mirroring | Declarative since 2.18 |
TrafficSplit |
SMI (linkerd-smi extension) |
Old traffic splitting | Deprecated. Use Gateway API HTTPRoute weights. |
Common Annotations and Labels¶
| Key | Where | Effect |
|---|---|---|
linkerd.io/inject (enabled, disabled, ingress) |
Namespace, workload, pod | Turns proxy injection on or off, or sets ingress mode |
config.linkerd.io/proxy-enable-native-sidecar: "false" |
Namespace, workload | Opts out of native sidecar injection (the default since 2.20). The Helm equivalent is proxy.nativeSidecar: false. |
config.linkerd.io/opaque-ports |
Service, pod, namespace | Skips protocol detection and treats the ports as opaque TCP. The value replaces the default list. |
config.linkerd.io/skip-inbound-ports, skip-outbound-ports |
Pod, namespace | Bypasses the proxy entirely. No mTLS, no metrics. |
config.linkerd.io/default-inbound-policy |
Namespace, pod | Overrides the default inbound policy |
config.linkerd.io/proxy-cpu-request, proxy-cpu-limit, proxy-memory-request, proxy-memory-limit |
Workload | Proxy resources |
config.linkerd.io/proxy-metrics-hostname-labels: "true" |
Pod, namespace | Adds a hostname label to outbound metrics (useful for egress) |
retry.linkerd.io/http, retry.linkerd.io/grpc, retry.linkerd.io/limit, retry.linkerd.io/timeout |
HTTPRoute, GRPCRoute, Service | Retries. The default limit is 1 retry per failure. |
timeout.linkerd.io/request, timeout.linkerd.io/response |
HTTPRoute, GRPCRoute, Service | Timeouts. Since 2.16, requests that time out can be retried. |
balancer.linkerd.io/failure-accrual (consecutive, unified) |
Service | Enables circuit breaking. unified counts 429 and RESOURCE_EXHAUSTED. |
balancer.linkerd.io/failure-accrual-consecutive-max-failures |
Service | Default 7 |
balancer.linkerd.io/failure-accrual-consecutive-min-penalty / -max-penalty / -jitter-ratio |
Service | Defaults 1s / 1m / 0.5 |
balancer.alpha.linkerd.io/penalize-failures: "true" |
Service | "Load Biaser": rate-limited responses count as high latency (experimental, 2.20). The default penalty is 5s. |
mirror.linkerd.io/exported: "true" |
Service (target cluster) | Mirrors the Service to linked clusters as <svc>-<cluster> |
mirror.linkerd.io/federated: member |
Service (each cluster) | Adds the Service to the federated service <svc>-federated |
Default opaque ports (chart proxy.opaquePorts): 25, 587, 3306, 4444, 5432, 6379, 9300, 11211.
Published Benchmark Numbers¶
Vendor-run benchmarks
These are the only sourced numbers. Buoyant ran them with the Kinvolk benchmark harness. They are old (Linkerd 2.10.2 vs Istio 1.10.0, 2021) and do not cover Istio ambient mode. Treat them as relative, not absolute, and run your own tests.
| Metric (2,000 RPS, bare metal, Kubernetes 1.19) | Linkerd 2.10.2 | Istio 1.10.0 (minimal) |
|---|---|---|
| Max memory of one data plane proxy (avg of runs) | 17.8 MB | 154.6 MB |
| Max proxy CPU time | 10 ms | 88 ms |
| Control plane memory | 324 MB | 837 MB |
| Control plane CPU time | 71 ms | 3.7 s |
| Median latency at 20 RPS (baseline 6 ms) | 17 ms | 26 ms |
Source: Benchmarking Linkerd and Istio (2021-05-27). A later third-party study by LiveWyer (May 2024) also reported lower latency and resource use than Istio and Cilium. Its setup is described in the LiveWyer post. The 2.20 announcement says destination controller memory drops "in some cases by almost 85%". No absolute number was published.
Figures that appeared in earlier versions of these notes ("~10 MB per proxy", "control plane ~300 MB", per-mesh-size resource tables, "10,000+ pods" scaling limits) had no source. They were removed. Use the table above or your own measurements.
Notable Security Advisories¶
| ID | Affected | Fix / mitigation |
|---|---|---|
| CVE-2024-40632 | Proxies whose app is already vulnerable to SSRF could have the proxy /shutdown endpoint called |
Since 2.16 the /shutdown endpoint is disabled by default |
Other advisories: TBD. They are not listed here. Check the linkerd2 security advisories for current entries.
Sources¶
- Releases and Versions and
linkerd.io/data/versions.yamlin linkerd/website - Supported Kubernetes Versions
- Gateway API support
- IPTables Reference
- Automatic mTLS
- Authorization Policy reference
- Circuit Breaking
- Retries and Timeouts
- linkerd-control-plane chart values
- Release edge-26.9.3
- BEL release notes