Vultr DocsLatest Content

How to Install and Use Linkerd on Vultr Kubernetes Engine (VKE)

Updated on 29 October, 2025
Install Linkerd on Vultr Kubernetes Engine (VKE) to enable observability, security, and traffic management with Ingress and TLS.
How to Install and Use Linkerd on Vultr Kubernetes Engine (VKE) header image

Linkerd is a lightweight, open-source service mesh for Kubernetes that provides observability, security, and traffic management features. It uses a sidecar proxy model where lightweight proxies handle pod-to-pod communication while a control plane manages configuration and routing.

This guide explains how to install Linkerd on a Vultr Kubernetes Engine (VKE) cluster. You will deploy a sample application, configure Ingress for external access, and implement traffic management features.

Prerequisites

Before you begin, you need to:

Install the Linkerd CLI

Install the Linkerd command-line interface on your workstation to manage your service mesh deployment.

  1. Update the system package index.

    console
    $ sudo apt update
    
  2. Download and install the Linkerd CLI.

    console
    $ curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install-edge | sh
    
  3. Add Linkerd to your PATH.

    console
    $ export PATH=$PATH:$HOME/.linkerd2/bin
    
  4. Make the PATH change permanent.

    console
    $ echo 'export PATH=$PATH:$HOME/.linkerd2/bin' >> ~/.bashrc
    $ source ~/.bashrc
    
  5. Verify the CLI installation.

    console
    $ linkerd version --client
    

    Output:

    Client version: edge-25.10.3

    The server version shows as unavailable because the control plane is not yet installed.

Validate the Kubernetes Cluster

Ensure your cluster meets Linkerd's requirements before installation.

  1. Run pre-installation checks.

    console
    $ linkerd check --pre
    

    All checks should pass with Status check results are √. If any checks fail, resolve the issues before proceeding.

Install Linkerd Control Plane

Deploy Linkerd's core components to your cluster.

  1. Install the Gateway API CRDs.

    console
    $ kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml
    
  2. Install Linkerd CRDs.

    console
    $ linkerd install --crds | kubectl apply -f -
    
  3. Install the control plane.

    console
    $ linkerd install | kubectl apply -f -
    
  4. Verify the installation.

    console
    $ linkerd check
    
  5. Check control plane pods.

    console
    $ 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 provides observability features and the web dashboard.

  1. Install the viz extension.

    console
    $ linkerd viz install | kubectl apply -f -
    
  2. Verify the viz installation.

    console
    $ linkerd viz check
    

Expose Linkerd Dashboard

You can expose the Linkerd dashboard securely via Kubernetes Ingress. In this section, expose the Linkerd dashboard securely using TLS encryption.

Install Nginx Ingress Controller

Deploy Nginx Ingress Controller to handle external traffic routing.

  1. Add the Nginx Ingress Helm repository.

    console
    $ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    
  2. Update Helm.

    console
    $ helm repo update
    
  3. Install Nginx Ingress Controller.

    console
    $ helm install ingress-nginx ingress-nginx/ingress-nginx \
        --create-namespace --namespace ingress-nginx
    
  4. Wait for the LoadBalancer to get an external IP.

    console
    $ 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 EXTERNAL-IP address value. This is where you should point your domain's A record.

  5. Verify the Nginx Ingress controller pods are running.

    console
    $ kubectl get pods -n ingress-nginx
    

Configure Dashboard Authentication

Create basic authentication credentials for securing dashboard access.

  1. Install htpasswd utility.

    console
    $ sudo apt install apache2-utils -y
    
  2. Generate authentication credentials. Replace admin with your preferred username.

    console
    $ htpasswd -c auth admin
    

    Enter a strong password when prompted.

  3. Create a Kubernetes secret with the credentials.

    console
    $ kubectl create secret generic web-ingress-auth \
        --from-file=auth \
        --namespace=linkerd-viz
    
  4. Remove the local auth file.

    console
    $ rm auth
    

Install cert-manager

Using cert-manager, you can secure your dashboard with HTTPS using Let's Encrypt TLS certificates.

  1. Add the Jetstack repository to Helm.

    console
    $ helm repo add jetstack https://charts.jetstack.io
    
  2. Update Helm.

    console
    $ helm repo update
    
  3. Install cert-manager and all required CRDs in your Kubernetes cluster.

    console
    $ helm install cert-manager jetstack/cert-manager \
      --namespace cert-manager --create-namespace \
      --set crds.enabled=true
    
  4. Check cert-manager resources and wait till they become ready.

    console
    $ kubectl get all -n cert-manager
    
  5. Create a ClusterIssuer for Let's Encrypt.

    console
    $ nano letsencrypt-issuer.yaml
    
  6. Add the following content. Replace admin@example.com with your email.

    yaml
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-prod
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        email: admin@example.com
        privateKeySecretRef:
          name: letsencrypt-prod
        solvers:
        - http01:
            ingress:
              class: nginx
    

    Save and close the file.

  7. Apply the ClusterIssuer.

    console
    $ kubectl apply -f letsencrypt-issuer.yaml
    

Create Ingress for Linkerd Dashboard

Create an Ingress resource to expose the Linkerd dashboard externally.

  1. Update the ingress-nginx-controller ConfigMap so the latest version of cert-manager can verify your domain. Without this change, a strict Nginx setting may block cert-manager’s automatic domain check, stopping it from issuing TLS certificates.

    console
    $ kubectl patch configmap ingress-nginx-controller -n ingress-nginx --patch '{"data":{"strict-validate-path-type":"false"}}'
    
  2. Create an Ingress manifest file.

    console
    $ nano linkerd-dashboard-ingress.yaml
    
  3. Add the following content. Replace linkerd.example.com with your domain.

    yaml
    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 and close the file.

    This Ingress routes external traffic from your domain to the Linkerd dashboard service running in the linkerd-viz namespace. It enforces basic authentication, sets proxy timeouts, and ensures the request is sent to the correct backend service on port 8084.

  4. Apply the Ingress manifest.

    console
    $ kubectl apply -f linkerd-dashboard-ingress.yaml
    
  5. Verify the Ingress was created.

    console
    $ kubectl get ingress -n linkerd-viz
    
  6. Verify the TLS certificate creation.

    console
    $ kubectl get certificate -n linkerd-viz
    

    Wait until the certificate shows READY as True.

Access the Dashboard

Access your secured Linkerd dashboard through the configured domain.

  1. Open a web browser and navigate to your domain.

    https://linkerd.example.com
  2. Enter the username and password you created earlier.

  3. Explore the dashboard to view cluster metrics, service mesh topology, and traffic flow.

Deploy a Sample Application

Test Linkerd's features with the Emojivoto sample application.

  1. Deploy the Emojivoto application.

    console
    $ curl -sL https://run.linkerd.io/emojivoto.yml | kubectl apply -f -
    
  2. Verify the deployment.

    console
    $ kubectl get pods -n emojivoto
    
  3. Add the application to the mesh.

    console
    $ kubectl get -n emojivoto deploy -o yaml | linkerd inject - | kubectl apply -f -
    
  4. View the meshed application in the dashboard or via CLI.

    console
    $ linkerd viz -n emojivoto stat deploy
    

Configure Traffic Splitting

Implement canary deployments using traffic splitting.

  1. Create a second version of the web deployment.

    console
    $ kubectl get deploy web -n emojivoto -o yaml | \
        sed 's/name: web/name: web-v2/' | \
        kubectl apply -f -
    

    This command copies the existing web Deployment, renames the copy to web-v2, and applies it to create a new Deployment.

  2. Create a service for the new version.

    console
    $ cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: web-v2
      namespace: emojivoto
    spec:
      ports:
      - name: http
        port: 80
        targetPort: 80
      selector:
        app: web
        version: v2
    EOF
    

    This Service exposes the web-v2 pods on port 80 inside the emojivoto namespace. It routes traffic to pods labeled app: web, version: v2.

  3. Add the new deployment to the mesh.

    console
    $ kubectl get deploy web-v2 -n emojivoto -o yaml | \
        linkerd inject - | \
        kubectl apply -f -
    

    This command injects the Linkerd proxy into the web-v2 Deployment and updates the cluster so new pods run with the proxy.

  4. Create a traffic split manifest.

    console
    $ nano traffic-split.yaml
    
  5. Add the following content to the file:

    yaml
    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
    

    Save and close the file.

    This TrafficSplit sends 80% of requests to the original web-svc service and 20% to the new web-v2 service.

  6. Apply the traffic split.

    console
    $ kubectl apply -f traffic-split.yaml
    
  7. Verify traffic distribution in the dashboard or via CLI.

    console
    $ linkerd viz -n emojivoto stat --from deploy/vote-bot deploy
    

Conclusion

You have successfully installed Linkerd on a VKE cluster, exposed the dashboard securely through Nginx Ingress with TLS encryption and authentication, and deployed a sample application with traffic splitting capabilities. For more information about advanced Linkerd features, visit the official Linkerd documentation.

Comments