The Linkerd maintainers have developed a rich CLI that allows you to easily install Linkerd CRDs, control plane components, and manage extensions directly from the command line.
Prerequisites
macOS/Linux/Windows with a Unix‑style shell
k3d (v5+) for local Kubernetes clusters
kubectl (v1.25+)
Tutorial
1. Create a Local Kubernetes Cluster
Use k3d and the cluster.yaml to spin up a lightweight Kubernetes cluster:
To install the CLI, execute the following command, which downloads and runs the installer script locally:
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install-edge | sh
Once installed, don’t forget to add the executable to your PATH environment variable:
export PATH=$HOME/.linkerd2/bin:$PATH
If you inspect the installer script, you’ll see that it uses the uname command to identify the OS and Architecture and then use the environment variables to download the Linkerd release from GitHub into a temporary directory:
OS=$(uname -s)
arch=$(uname -m)
...
tmpdir=$(mktemp -d /tmp/linkerd2.XXXXXX)
srcfile="linkerd2-cli-${LINKERD2_VERSION}-${OS}"
if [ -n "${cli_arch}" ]; then
srcfile="${srcfile}-${cli_arch}"
fi
dstfile="${INSTALLROOT}/bin/linkerd-${LINKERD2_VERSION}"
url="https://github.com/linkerd/linkerd2/releases/download/${LINKERD2_VERSION}/${srcfile}"
3. Explore the CLI
The CLI has a lot of functionality, and the maintainers are constantly working to enhance it. You can list all available commands by running linkerd help:
linkerd help
linkerd manages the Linkerd service mesh.
Usage:
linkerd [command]
Available Commands:
authz List authorizations for a resource
check Check the Linkerd installation for potential problems
completion Output shell completion code for the specified shell (bash, zsh or fish)
diagnostics Commands used to diagnose Linkerd components
help Help about any command
identity Display the certificate(s) of one or more selected pod(s)
inject Add the Linkerd proxy to a Kubernetes config
install Output Kubernetes configs to install Linkerd
install-cni Output Kubernetes configs to install Linkerd CNI
jaeger jaeger manages the jaeger extension of Linkerd service mesh
multicluster Manages the multicluster setup for Linkerd
profile Output service profile config for Kubernetes
prune Output extraneous Kubernetes resources in the linkerd control plane
uninject Remove the Linkerd proxy from a Kubernetes config
uninstall Output Kubernetes resources to uninstall Linkerd control plane
upgrade Output Kubernetes configs to upgrade an existing Linkerd control plane
version Print the client and server version information
viz viz manages the linkerd-viz extension of Linkerd service mesh
Each of these commands has its own subcommands. You can view them by running linkerd <command> --help. for example:
linkerd authz --help
List authorizations for a resource.
Usage:
linkerd authz [flags] resource
Flags:
-h, --help help for authz
-n, --namespace string Namespace of resource
Global Flags:
--api-addr string Override kubeconfig and communicate directly with the control plane at host:port (mostly for testing)
--as string Username to impersonate for Kubernetes operations
--as-group stringArray Group to impersonate for Kubernetes operations
--cni-namespace string Namespace in which the Linkerd CNI plugin is installed (default "linkerd-cni")
--context string Name of the kubeconfig context to use
--kubeconfig string Path to the kubeconfig file to use for CLI requests
-L, --linkerd-namespace string Namespace in which Linkerd is installed ($LINKERD_NAMESPACE) (default "linkerd")
--verbose Turn on debug logging
4. Install Linkerd on Your Cluster
To install Linkerd, you must first install the CRDs required by the control plane, starting with the API Gateway CRDs, then the Linkerd CRDs, and finally the control plane itself. The linkerd install command output the YAML manifest but do not apply it directly. You will need to pipe the output to kubectl apply.
Note: Prior to 2.18, Linkerd provided its own version of the API Gateway, but it was limited by dependencies tied to version 0.7, which posed an issue when third-party tools like Kong Gateway required a different version. To solve this, the maintainers decoupled them so that, starting with 2.18, Linkerd supports Gateway API versions from 1.0.0 onward and will require users to install it separatly. Running API Gateway 1.2.0 on a Linkerd version prior to 2.18 will break the control plane, since the policy controller watches for a specific version of the gRPCRoute Gateway API, which is not provided in 1.2.0.
If we check the API Resouces we will see both API Gateway and Linkerd resources.
kubectl get crds -A
NAME CREATED AT
addons.k3s.cattle.io 2025-05-20T04:54:40Z
authorizationpolicies.policy.linkerd.io 2025-05-20T05:18:06Z
egressnetworks.policy.linkerd.io 2025-05-20T05:18:07Z
externalworkloads.workload.linkerd.io 2025-05-20T05:18:07Z
gatewayclasses.gateway.networking.k8s.io 2025-05-20T05:16:36Z
gateways.gateway.networking.k8s.io 2025-05-20T05:16:36Z
grpcroutes.gateway.networking.k8s.io 2025-05-20T05:16:36Z
httplocalratelimitpolicies.policy.linkerd.io 2025-05-20T05:18:07Z
httproutes.gateway.networking.k8s.io 2025-05-20T05:16:36Z
httproutes.policy.linkerd.io 2025-05-20T05:18:07Z
meshtlsauthentications.policy.linkerd.io 2025-05-20T05:18:07Z
networkauthentications.policy.linkerd.io 2025-05-20T05:18:07Z
referencegrants.gateway.networking.k8s.io 2025-05-20T05:16:36Z
serverauthorizations.policy.linkerd.io 2025-05-20T05:18:07Z
servers.policy.linkerd.io 2025-05-20T05:18:07Z
serviceprofiles.linkerd.io 2025-05-20T05:18:07Z
One important thing to highlight is that each CRD might serve multiple versions of the same API, which are not immeditly visible in the table. However, if we describe the CRD resource, you will see those multiple versions.
kubectl describe crd servers.policy.linkerd.io
Name: servers.policy.linkerd.io
Namespace:
Labels: helm.sh/chart=linkerd-crds-0.0.0-undefined
linkerd.io/control-plane-ns=linkerd
Annotations: linkerd.io/created-by: linkerd/cli edge-25.5.3
API Version: apiextensions.k8s.io/v1
Kind: CustomResourceDefinition
Metadata:
Creation Timestamp: 2025-05-20T05:18:07Z
Generation: 1
Resource Version: 961
UID: 7b046714-27b4-4d19-8292-6651025ff071
Spec:
Conversion:
Strategy: None
Group: policy.linkerd.io
Names:
Kind: Server
List Kind: ServerList
Plural: servers
Short Names:
srv
Singular: server
Scope: Namespaced
Versions:
Deprecated: true
Deprecation Warning: policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta1 Server
Name: v1alpha1
Schema:
openAPIV3Schema:
...
Served: true
Storage: false
...
Deprecated: true
Deprecation Warning: policy.linkerd.io/v1beta1 Server is deprecated; use policy.linkerd.io/v1beta3 Server
Name: v1beta1
Schema:
openAPIV3Schema:
...
Served: true
Storage: false
...
Name: v1beta2
Schema:
openAPIV3Schema:
...
Served: true
Storage: false
Finally, if you check the deployments and pods running in the linkerd namespace, you will see the linkerd-destination, linkerd-identity, and linkerd-proxy-injector running:
kubectl get deploy -n linkerd
NAME READY UP-TO-DATE AVAILABLE AGE
linkerd-destination 1/1 1 1 28m
linkerd-identity 1/1 1 1 28m
linkerd-proxy-injector 1/1 1 1 28m
kubectl get pods -n linkerd
NAME READY STATUS RESTARTS AGE
linkerd-destination-75f4bc85cd-fswvp 4/4 Running 0 28m
linkerd-identity-9bf7d8b86-zmkb2 2/2 Running 0 28m
linkerd-proxy-injector-5d5687794c-4kmhs 2/2 Running 0 28m
During the course, we will dig more into the various commands. But for this first module, we will stop here.