đź”­Thinking About Linkerd? Let's Get Hands-On! A Guide to Linkerd's Core Features

We'll walk through installing Linkerd on a minikube cluster and get hands-on with its key features to truly understand what a service mesh is all about.

Hello, and welcome to your Aiden's Lab Notebook.

Following up on our last post covering the core concepts and features of Linkerd, this time, we're going to roll up our sleeves and get hands-on with installing and using Linkerd.

To keep this exercise focused, we'll use Minikube for our Kubernetes cluster setup. Since we've covered Minikube in previous posts, I won't go into extra detail here.

Before we dive in, let's take a closer look at Linkerd's main components to make our hands-on session more effective.

A Closer Look at Linkerd's Main Components

Linkerd's Control Plane acts as the brain of the Service Mesh and consists of these core components:

  • controller: Provides the public API.

  • destination: Manages service discovery and routing information.

  • identity: Issues and manages certificates for mTLS.

  • proxy-injector: Automatically injects the sidecar proxy when Pods are created.

And Linkerd's Data Plane is made up of linkerd-proxy, an ultra-lightweight sidecar proxy deployed alongside each application's Pod.

The Linkerd proxy transparently intercepts all TCP traffic (mainly HTTP, gRPC, etc.) going into and out of its Pod. With this intercepted traffic, it performs functions like mTLS encryption, load balancing, retries, timeouts, and metrics collection.

The Linkerd CLI is the tool that allows you, from your local machine, to communicate with the Linkerd Control Plane and manage the Service Mesh.

From the CLI, you can perform various tasks like installing Linkerd, checking its status, viewing resource statistics, monitoring real-time traffic, and injecting proxies. It's an essential tool for operating and debugging Linkerd.

Finally, Linkerd Viz is an extension that allows you to visually monitor and analyze the health and performance of your Linkerd Service Mesh.

Through its web-based dashboard, you can monitor real-time traffic, success rates, latency, and more. It also provides a Prometheus-compatible metrics API, enabling integration with external monitoring systems.

Preparing Our Lab: Installing the Linkerd CLI

I'm running this lab in a WSL environment. First, I'll start a Minikube cluster named k8s-test in my terminal.

Next, I'll run the Linkerd CLI installation command below.

curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install-edge | sh

The Linkerd installation script will then be downloaded and executed, as shown below.

Run the following command to add it to your environment variables.

export PATH=$HOME/.linkerd2/bin:$PATH

Once that's done, you can check if the Linkerd CLI is installed with the linkerd version command.

Since Linkerd's Control Plane hasn't been deployed to our Minikube cluster yet, the Server version is unavailable. After we deploy the Control Plane later, we'll check again, and the Server version will be updated.

To use Linkerd, the Gateway API CRD must be installed on your Kubernetes cluster. A CRD (Custom Resource Definition) allows you to extend the cluster's functionality by adding new resource types beyond the default ones (like Deployment, StatefulSet, etc.).

The Gateway API is a CRD that defines resources related to network traffic. If it's not already installed, you can install it on your cluster with the following command:

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml

This will install the CRDs that make up the Gateway API.

Next, running the linkerd check --pre command in your terminal will verify if your cluster meets the prerequisites for using Linkerd. This command helps you identify potential environmental issues in advance, from the Kubernetes API status and version to the Linkerd CLI version.

Now that all prerequisites are met, let's deploy Linkerd's Control Plane to our cluster.

Deploying the Linkerd Control Plane on Minikube

To deploy Linkerd's Control Plane, you first need to install the CRDs required for it to operate, using the command below.

linkerd install --crds | kubectl apply -f -

Next, let's install the Linkerd Control Plane itself. The following command will automatically install the components that make up the Control Plane.

linkerd install | kubectl apply -f -

If your Minikube is running on Docker...


When you try to install the Linkerd Control Plane, the installation might fail with a message stating that the proxy-init container must run as the root user.
In that case, use the command linkerd install --set proxyInit.runAsRoot=true | kubectl apply -f - to install Linkerd.

Since my Minikube is indeed running on Docker, I used the following command to install the Linkerd Control Plane:

You can now see that all the necessary resources for Linkerd have been deployed to the linkerd Namespace. (kubectl -n linkerd get all)

Next, running the linkerd check command will confirm that all necessary resources for the Linkerd Control Plane are installed and running correctly.

Now, let's install the viz extension to enhance Linkerd's observability features.

Installing Linkerd viz gives you access to a web dashboard, on-demand tap functionality, a Prometheus-compatible metrics API, and more. It's useful for visually understanding and analyzing the state of your Service Mesh.

Run the Linkerd viz extension installation command in your terminal:

linkerd viz install | kubectl apply -f -

All the necessary resources for the Linkerd viz extension will be automatically installed.

The Linkerd viz extension is deployed in the linkerd-viz Namespace.

If you run the linkerd viz dashboard command in your terminal, you'll see a message that the Linkerd viz dashboard has opened. This sets up port-forwarding between your local machine and the Linkerd dashboard Service, making the dashboard accessible.

Open the URL from the message in your web browser, and...

You can now see the Linkerd viz web dashboard! The metrics for success rate, RPS, and P99 for traffic displayed by Namespace show that Linkerd is now operating normally.

Keep in mind that you need to keep the terminal where you ran linkerd viz dashboard open to maintain access to the dashboard.

We have now completed the Linkerd setup on our Minikube cluster! 🎉

Next, to try out Linkerd's core features, we'll deploy two demo Deployments. Adding a Deployment to the Linkerd Service Mesh is also very simple!

Deploying a Sample App and Adding It to the Service Mesh

To observe traffic using the Linkerd Service Mesh we've just configured, the Service generating that traffic needs to be part of the mesh, right? Linkerd provides two main ways to do this:

  1. Inject the Linkerd proxy into already-deployed Kubernetes resources using the linkerd inject command.

  2. Add a Linkerd-aware annotation to a specific Namespace.

Since the terminal we've been using is keeping the linkerd viz dashboard process running, please open a separate terminal to continue with the lab.

And to deploy the Kubernetes resources for our Linkerd lab separately, let's first create a Namespace called linkerd-demo.

1. Using the linkerd inject command

To try the linkerd inject command, let's first deploy an Nginx Deployment without the Linkerd proxy. Save the following Deployment and Service manifest as a YAML file and apply it to your cluster.

# 1. 'Server' role Nginx Deployment to be observed by Linkerd
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world-server
  namespace: linkerd-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-world-server
  template:
    metadata:
      labels:
        app: hello-world-server
    spec:
      containers:
      - name: hello-world
        image: nginx:alpine
        ports:
        - containerPort: 80

---
# 2. Service to call the 'server' Nginx Deployment from within the cluster
apiVersion: v1
kind: Service
metadata:
  name: hello-world-server
  namespace: linkerd-demo
spec:
  selector:
    app: hello-world-server
  ports:
  - name: http
    port: 80
    targetPort: 80

Now, if you go back to the Linkerd viz dashboard and click on the linkerd-demo Namespace we created...

Although the hello-world-server Deployment we just deployed is listed, you'll notice that no metrics are being displayed yet. This is because the Linkerd proxy hasn't been injected into this Deployment, so Linkerd can't receive traffic metrics for it.

The Meshed count you see in the image shows the number of resources currently included in the Service Mesh. Right now, it shows '0/1' because no resources are meshed yet.

The linkerd inject command is what allows you to add the Linkerd proxy container directly to the Pod configuration of Kubernetes resources that were deployed before Linkerd was in place.

So, how can we inject the Linkerd proxy into the currently deployed Deployment and redeploy it? You can use the command below.

kubectl -n linkerd-demo get deploy -o yaml | linkerd inject - | kubectl apply -f -

This command runs through the following flow:

  1. Fetches the manifests of all Deployments in the linkerd-demo Namespace in YAML format.

  2. Injects the Linkerd proxy-related annotations into the Pod configuration of the fetched manifests.

  3. Redeploys the injected manifests back to the cluster.

Running this command will show a message indicating that the injection and configuration have been updated.

And if you look at the Deployment's configuration with the describe command...

You can see that an annotation indicating that Linkerd's injection is enabled has been added to the Pod configuration, as highlighted in the red box. Now, let's check the Linkerd web dashboard again.

The Meshed count has been updated to 1/1, and the metrics are now displaying correctly!

As you can see, the linkerd inject command makes it easy and fast to bring even pre-existing Kubernetes resources into Linkerd's Service Mesh.

2. Adding a Linkerd-aware Annotation to a Namespace

But what if you want Pods deployed to a specific Namespace to be included in the Linkerd Service Mesh as soon as they're created? This is a very common scenario.

In this case, all you need to do is add Linkerd's annotation to the desired Namespace. Since this is straightforward, let's jump right into it.

First, let's check the configuration of our existing Namespace linkerd-demo.

Since we didn't add any other settings when we created this Namespace, it only has the default values. The kubectl supports an annotate command to add annotations (annotate) to resources, so let's add Linkerd's annotation with the following command:

kubectl annotate namespace linkerd-demo linkerd.io/inject=enabled

If you check the Namespace configuration again, you'll see that the same annotation added in the first injection method is now present. Now, any new Pod added to the linkerd-demo Namespace will automatically get the Linkerd proxy sidecar container. That was quick, right?

Now, let's deploy a new Deployment to this Namespace. This Deployment, named traffic-generator, sends HTTP traffic to our hello-world-server every 2 seconds. We'll take a look at this later with Linkerd's traffic observation features.

# 'Client' Deployment that consistently generates traffic to the 'Server'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: traffic-generator
  namespace: linkerd-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: traffic-generator
  template:
    metadata:
      labels:
        app: traffic-generator
    spec:
      containers:
      - name: traffic-curl
        image: curlimages/curl:latest
        # Sends an HTTP request to the hello-world-server service every 2 seconds.
        command: ["sh", "-c", "while true; do echo '--> Sending request to hello-world-server'; curl -s http://hello-world-server > /dev/null; echo 'Request sent.'; sleep 2; done"]

I saved the above YAML file as client.yaml and applied it to the cluster with the kubectl apply command.

And if we check the Linkerd web dashboard again...

The Pod of the newly deployed Deployment is now in a Meshed state, and its traffic metrics are also being displayed correctly! From now on, any new Pod created in the linkerd-demo Namespace will automatically be incorporated into Linkerd's Service Mesh.

So far, we've learned about two ways to bring Pods into Linkerd's Service Mesh. These are very simple methods that reflect Linkerd's design philosophies of 'Keep it simple' and 'Just work'.

Now that our Deployments are properly integrated into the Linkerd Service Mesh, let's actually try out Linkerd's core features.

Getting Hands-On with Linkerd's Core Features

Most of Linkerd's core features can be accessed from the Linkerd web dashboard. However, there are times when you need to check specific things directly from the terminal with a command. To wrap up this lab, let's go over three essential Linkerd commands together.

1. Check Current Traffic Stats with linkerd viz stat

linkerd viz stat is a tool that provides a summary of real-time traffic statistics for resources within the Linkerd Service Mesh. By using it as shown below, you can check the current requests per second (RPS), success rate (SR), and latency (P99) for all Deployments in the linkerd-demo Namespace.

linkerd viz stat deploy -n linkerd-demo

2. Observe Real-Time Request and Response Streams with linkerd viz tap

The linkerd viz tap command is a tool that captures and displays a real-time stream of actual requests and responses passing through a specific K8s resource (Deployment, Pod, Service, etc.). This is useful for troubleshooting or traffic analysis, as it allows developers and operators to directly inspect the headers, body, status codes, and latency of individual requests.

You can view the real-time request and response stream for all Deployments in the linkerd-demo Namespace as follows:

linkerd viz tap deploy -n linkerd-demo

3. Check mTLS Encrypted Connection Status with linkerd viz edges

As we mentioned, Linkerd automatically encrypts all TCP communication between services included in the Service Mesh with mTLS. This mTLS connection status can be visually confirmed in the Linkerd dashboard's topology view or in the details of each service.

You can also use a command like linkerd viz edges deploy -n {Namespace_name} in the terminal to immediately check which services are communicating securely with mTLS. For example, running the command below will show the mTLS connection status for all Deployments in the linkerd-demo Namespace.

linkerd viz edges deploy -n linkerd-demo

Wrapping Up

We've covered everything from installing Linkerd and adding a Deployment to the Service Mesh to using three of Linkerd's core commands. Are you getting a better feel for what Linkerd is all about?

Of course, to successfully adopt Linkerd in a real production environment, there are more considerations, such as planning for the resource requirements of the Control and Data Planes and configuring Control Plane replication for high availability.

However, the experience of installing and operating a Service Mesh like Linkerd firsthand builds practical skills needed to solve complex communication problems in a microservice architecture and to improve a service's observability, reliability, and security.

This experience is more than just learning a single tool; it's a crucial foundation that deepens your overall understanding of system operations in a cloud-native environment.

I truly hope this series has been a great first step for those who wanted to learn more about Service Mesh or Linkerd.

I'll see you in the next article with another interesting topic. Thank you!

References

✨Enjoyed this issue?

How about this newsletter? I’d love to hear your thought about this issue in the below form!

👉 Feedback Form

Your input will be help improve Aiden’s Lab Notebook and make it more useful for you.

Thanks again for reading this notebook from Aiden’s Lab :)