Exploring LinkerD
A service mesh like Linkerd is a tool for adding observability, security, and reliability features to “cloud native” applications by transparently inserting this functionality at the platform layer rather than the application layer. In this post we will be exploring some of the more impressive features that LinkerD has to offer.
Getting Started
LinkerD has one of the most impressive and simple getting started guides I have ever seen. Rather than trying to replicate or improve it, I am instead going to suggest you start with their official getting started guide.
I will then use this post to cover some of the other features which are not covered in the getting started guide such as tracing, certificate rotation, and routes. Each section will assume that you are starting with a clean cluster and that LinkerD is not yet installed. We will also be making use of the LinkerD Emojivoto app to demonstrate some of the functionality.
Tracing (Jaeger)
During the getting started guide you were introduced to the viz extension for LinkerD. Getting Jaeger running follows similar steps as we will be using the LinkerD-Jaeger extension. This extensions consists of three components: the collector, the Jaeger backend (with the option of using your own backend), and lastly a Jaeger-injector.
The collector will receive the spans from the mesh and your application and send them through to the collector you have configured. The Jaeger-injector configures the LinkerD proxies to emit the spans.
Let’s install LinkerD using the following command:
|
|
Once the LinkerD installation is done we will also install the viz extension, but we will be setting an additional option so that we can access Jaeger within the LinkerD dashboard:
|
|
Run the following command to install the LinkerD-jaeger extension:
|
|
Now that all the LinkerD components are installed and running, we can install the Emojivoto application with the following command:
|
|
By default Emojivoto does not emit spans. It requires that the OC_AGENT_HOST environment variable is set. Run the following command to patch the deployment and add the required environment variable:
|
|
For this demonstration we will also install an Ingress controller so that we can see the trace from the moment the request enters the cluster. Run the following commands to install ingress-nginx and create an ingress rule for the Emojivoto app:
|
|
Now we are finally ready to see what tracing can do for us. Get the IP of the ingress controller with the following command:
|
|
The Emojivoto app does come with a load generator, but if you want to see some spans originating from the
ingress, use the IP you just retrieved and go vote on some emojis. Once you are ready to explore Jaeger run
linkerd jaeger dashboard
and you should see something like this:
To view the details of a request select the nginx service on the left and then click “Find Traces”. Once you click on a trace you should see something more like this:
This trace will show you exactly where your request went and how long it took on each step. You will notice that there are also a lot of “linkerd-proxy” entries. These are the LinkerD proxy sidecars sitting in the application pods. From this view you can even drill in a little bit more and view span details:
The last thing to show is the LinkerD-jaeger integration with the viz dashboard. Open the dashboard
with linkerd viz dashboard
. Once open, change the namespace to emojivoto
and browse the deployments.
You should see the Jaeger logo next to the Grafana logo on each row:
Clicking on this icon will open the Jaeger dashboard to a filtered view for the selected deployment.
Service Profiles (Routes)
Service profiles provide LinkerD with additional information about a service. It is configured via a Kubernetes custom resource definition (CRD). Once you have configured a service profile for a service, LinkerD can provide per-route metrics and you are able to configure additional per-route features such as retries and timeouts.
Creating Service Profiles
Let’s start by installing LinkerD adn the viz extension:
|
|
We will again be making use the Emojivoto app for our demo. Run the following command to install Emojivoto and inject LinkerD:
|
|
Once the application is up and running, open the LinkerD viz dashboard with linkerd viz dashboard
.
Change the namespace to emojivoto, select pods, click on any pod and swap over to
Route Metrics. Right now you should see something like this:
As you can see there is not a lot of details here. To get more out of this view we need to create our service profiles. There are a few ways to go about this. We can either automatically create the service profile from network traffic to the service, automatically generate the service profile from Protobuf or OpenAPI specifications, or the much less impressive and fun way by manually creating them from a template. The last option will not be covered in this post.
From Traffic
To create a service profile from observed traffic run the following command:
|
|
This will generate a service profile from the traffic observed over a 10 second period. The risk of this approach is that not all available routes will receive traffic over the specified period and your service profile will be incomplete.
This method is a great starting point if you do not have Protobuf or OpenAPI specifications, but rather use the below method if you do have access to the specifications.
From OpenAPI/Protobuf Specification
LinkerD provides some handy commands to automatically convert an OpenAPI or Protobuf specification to a complete service profile. The commands to convert the specifications are as follows:
|
|
Emojivoto makes use of GRPC and we can download the .proto files from the official GitHub repo. To configure the service profiles from these files run the following commands:
|
|
Now when you visit the Route Metrics of a deployment in the LinkerD dashboard you should see something more like this:
Retries
Now that we have service profiles we can do some cool things. The first of which is automatic
retries. Edit the voting-svc.emojivoto.svc.cluster.local
service profile and change the
*VoteDoughnut route to match the following:
|
|
That’s it. Now you have automatic retries on that route. You can confirm this by running the following command:
|
|
If it is working as expected you should notice that the results of EFFECTIVE_RPS and ACTUAL_RPS are different. The ACTUAL columns include the results of the retries.
By default LinkerD will add at most 20% additional load to the requests to the service, with 10 “free” retries per second. This can be modified by adding a retryBudget to the service profile:
|
|
Timeouts
The second cool thing we can do is tell LinkerD how long it should wait for responses before returning a 504 response. By default this timeout is 10s and it includes retries. To add a timeout, simply edit the service profile like we did for the retries:
|
|
The timeouts will count as failures in the stats that LinkerD provide. It’s also worth noting that the effective request rate could be higher than actual request rate when timeouts are received. This is because LinkerD does not include these timeouts to the actual request rate.
Automatic Certificate Rotation
Before we cover automatic certificate rotation we need to remind ourselves about the LinkerD architecture.
LinkerD offers automatic mTLS between services. This feature uses a trust anchor, and an issuer certificate and private key to automatically rotate the TLS certificates for the data plane proxy every 24 hours. However, the credentials used to issue these certificates are not rotated by default.
In this example we will be using Cert-Manager to rotate the issuer certificate and private key. Make sure that your cluster is blank and that you have not installed LinkerD. We will need to get some things set up before we install LinkerD.
|
|
Now that Cert-Manager is installed and running, and we have our trust anchor we can create an Issuer referencing our trust anchor:
|
|
The final configuration step is to create a Certificate resource which will use the Issuer we just created to issue our new certificates:
|
|
Cert-Manager should now have issued new TLS credentials and stored it in the
secret named linkerd-identity-issuer
. We can now use this secret while installing
LinkerD:
|
|
The additional identity-external-issuer
flag tells LinkerD to use the certs
stored in the linkerd-identity-issuer
secret. And that’s it. You now have
automatic certificate rotation on the control plane.