Install and Configure Linkerd on a Kubernetes Cluster
Linkerd is a lightweight, open-source service mesh for Kubernetes that delivers observability, security, and traffic control. It follows a sidecar proxy pattern in which small proxies handle pod-to-pod communication, while a centralized control plane manages configuration and routing.
This step-by-step guide shows how to install Linkerd on a Kubernetes cluster. You will deploy a sample app, set up Ingress for external access, and enable traffic management capabilities.
Prerequisites
Before you start, ensure you have the following:
- An active Kubernetes cluster.
- A domain with an A record pointing to the cluster’s load balancer IP (for example, linkerd.example.com).
- Access to an Ubuntu-based server or local machine as your workstation for managing the Kubernetes cluster and running the Linkerd CLI.
- Kubectl installed and configured for your Kubernetes cluster.
- Helm installed on your workstation.
Install the Linkerd CLI
Install the Linkerd command-line interface on your workstation to operate your service mesh.
Update the system package index
$ sudo apt update
Download and install the Linkerd CLI
$ curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install-edge | sh
Add Linkerd to your PATH
$ export PATH=$PATH:$HOME/.linkerd2/bin
Make the PATH change permanent
$ echo 'export PATH=$PATH:$HOME/.linkerd2/bin' >> ~/.bashrc
$ source ~/.bashrc
Verify the CLI installation
$ linkerd version --client
Output:
Client version: edge-25.10.3
The server version appears unavailable because the control plane has not yet been installed.
Validate the Kubernetes Cluster
Confirm your cluster satisfies Linkerd’s requirements before proceeding.
Run pre-installation checks
$ linkerd check --pre
All checks should pass with the message Status check results are √. Resolve any failures before continuing.
Install Linkerd Control Plane
Deploy Linkerd’s core components to your cluster.
Install the Gateway API CRDs
$ kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml
Install Linkerd CRDs
$ linkerd install --crds | kubectl apply -f -
Install the control plane
$ linkerd install | kubectl apply -f -
Verify the installation
$ linkerd check
Check control plane pods
$ kubectl get pods -n linkerd
Output:
NAME READY STATUS RESTARTS AGE linkerd-destination-7b4657cfd8-btqdv 4/4 Running 0 4m40s linkerd-identity-5584896d84-6pmdm 2/2 Running 0 4m40s linkerd-proxy-injector-995fcbf47-dv6qr 2/2 Running 0 4m40s
Install Linkerd Viz Extension
The Viz extension adds observability features and a web dashboard.
Install the viz extension
$ linkerd viz install | kubectl apply -f -
Verify the viz installation
$ linkerd viz check
Expose Linkerd Dashboard
Securely expose the Linkerd dashboard through Kubernetes Ingress with TLS encryption.
Install Nginx Ingress Controller
Deploy Nginx Ingress Controller to handle external traffic.
Add the Nginx Ingress Helm repository
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
Update Helm
$ helm repo update
Install Nginx Ingress Controller
$ helm install ingress-nginx ingress-nginx/ingress-nginx \
--create-namespace --namespace ingress-nginx
Wait for the LoadBalancer to get an external IP
$ kubectl get service -n ingress-nginx ingress-nginx-controller
Sample output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx-controller LoadBalancer 10.99.177.190 192.0.20.11 80:31460/TCP,443:32364/TCP 3m51s
Note the value of the EXTERNAL-IP field. Point your domain’s A record to this IP address.
Verify Nginx Ingress controller pods
$ kubectl get pods -n ingress-nginx
Create Ingress for Linkerd Dashboard
Create an Ingress resource to expose the Linkerd dashboard externally.
Update the ingress-nginx-controller ConfigMap so that the latest version of cert-manager can verify your domain. Without this update, a strict Nginx validation setting could block cert-manager’s domain verification, preventing TLS certificate issuance.
$ kubectl patch configmap ingress-nginx-controller -n ingress-nginx --patch '{"data":{"strict-validate-path-type":"false"}}'
Create the Ingress Manifest File
$ nano linkerd-dashboard-ingress.yaml
Add the following configuration, replacing linkerd.example.com with your own domain.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
namespace: linkerd-viz
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/upstream-vhost: web.linkerd-viz.svc.cluster.local:8084
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: web-ingress-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
spec:
ingressClassName: nginx
tls:
- hosts:
- linkerd.example.com
secretName: linkerd-dashboard-tls
rules:
- host: linkerd.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 8084
Save the file and close the editor. This configuration routes external requests from your domain to the Linkerd dashboard running in the linkerd-viz namespace. It enforces basic authentication, sets proxy timeouts, and ensures requests reach the correct backend service.
Apply the Ingress Manifest
$ kubectl apply -f linkerd-dashboard-ingress.yaml
Verify the Ingress Resource
$ kubectl get ingress -n linkerd-viz
Verify the TLS Certificate
$ kubectl get certificate -n linkerd-viz
Wait until the certificate status shows READY = True.
Access the Dashboard
Access your secure Linkerd dashboard by visiting your configured domain in a browser.
https://linkerd.example.com
Log in using the username and password you created earlier. Explore the dashboard to review cluster metrics, service mesh topology, and traffic flow.
Deploy a Sample Application
Deploy the Emojivoto application to test Linkerd’s features and verify service mesh integration.
Deploy the Emojivoto Application
$ curl -sL https://run.linkerd.io/emojivoto.yml | kubectl apply -f -
Verify the Deployment
$ kubectl get pods -n emojivoto
Add the Application to the Mesh
$ kubectl get -n emojivoto deploy -o yaml | linkerd inject - | kubectl apply -f -
View the Meshed Application
$ linkerd viz -n emojivoto stat deploy
Configure Traffic Splitting
Implement canary deployments using an HTTPRoute to distribute traffic between application versions.
Create a Second Version of the Web Deployment
$ kubectl get deploy web -n emojivoto -o yaml | \
sed 's/name: web/name: web-v2/' | \
kubectl apply -f -
Create a Service for the New Version
$ cat <
Add the New Deployment to the Mesh
$ kubectl get deploy web-v2 -n emojivoto -o yaml | \
linkerd inject - | \
kubectl apply -f -
Create a Manifest for Traffic Splitting
$ nano traffic-split.yaml
Add the following configuration:
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: web-route
namespace: emojivoto
spec:
parentRefs:
- name: web-svc
kind: Service
group: core
port: 80
rules:
- backendRefs:
- name: web-svc
port: 80
weight: 80
- name: web-v2
port: 80
weight: 20
Apply the Manifest
$ kubectl apply -f traffic-split.yaml
Verify Traffic Distribution
$ linkerd viz -n emojivoto stat --from deploy/vote-bot deploy
Conclusion
You have successfully installed Linkerd on a Kubernetes cluster, securely exposed the dashboard using Nginx Ingress with TLS and authentication, and deployed a sample application with traffic splitting. For more details, refer to the official Linkerd documentation.

