Elton's Container Show


Elton's Container Show - resources for the YouTube broadcast

View the Project on GitHub sixeyed/ecs

ECS-M2: Service Mesh with Linkerd on Kubernetes

Linkerd is the original service mesh for Kubernetes. It has all the features we looked at last week and it’s easy to get started with. This week we’ll see how to deploy Linkerd and use it to manage the communication in a sample app. We’ll have Linkerd automatically register components into the mesh and use it to control traffic flow, add security and power observability.

Linkerd is a CNCF project with an active community, and a commercially-supported offering. It’s solid and fast, and it’s used by some pretty big companies - like eBay, Strava and Walmart.

Here it is on YouTube - ECS-M2: Service Mesh with Linkerd on Kubernetes


Docker Desktop with Kubernetes enabled - or any other Kubernetes deployment.

Linkerd CLI.

Install the Linkerd CLI:

# Windows:
choco install linkerd2

# Mac:
brew install linkerd

# Linux:
curl -sL https://run.linkerd.io/install | sh

Demo 1 - Deploy Linkerd to Kubernetes

Linkerd deploys the control plane as standard Kubernetes resources.

Verify your Linkerd CLI & Kubernetes cluster:

linkerd version

kubectl get nodes

linkerd check --pre

Generate the deployment manifest:

linkerd install > demo1/linkerd.yaml

That generates linkerd.yaml.

It’s 3.5K lines of YAML - which is why you need the CLI :)

Deploy and verify:

kubectl apply -f demo1/linkerd.yaml

kubectl get ns

kubectl get all -n linkerd

linkerd check

These components are all part of the control plane.

Check the UI:

kubectl get svc linkerd-web -n linkerd

# run this in a new terminal to expose the UI:
linkerd dashboard

Demo 2 - Deploy the Widgetario app

The demo app will run in its own namespace. The initial deployment doesn’t mesh the services.

Deploy without registering to the mesh:

kubectl apply -f demo2/widgetario/

kubectl get all -n widgetario

Try the app at http://localhost:8010

Check the Linkerd UI - none of the components are meshed.

You can configure automatic mesh registration for Pods, Deployments and whole namespaces.

The updated 01-namespace.yaml adds the Linkerd annotation.

Set the namespace for automatic proxy injection:

kubectl get pods -n widgetario

kubectl apply -f demo2/widgetario/update1/

kubectl get pods -n widgetario

Nothing. Automatic injection is via an admission webhooks - it doesn’t fire on existing Pods.

The updated Deployment specs update2/products-api.yaml add the annotation at the Pod level - that’s a rollout so the new Pods will be registered with the mesh.

Try again:

kubectl apply -f demo2/widgetario/update2/

kubectl get pods -n widgetario

The web Pod has an extra debug sidecar, configured in update2/web.yaml

Check the Linkerd dashboard:

Demo 3 - Test security with mTLS

Mutual TLS is applied between meshed services by default. Linkerd manages the TLS certs, applying them in the proxy sidecar.

Check the traffic from the web Pod to the stock API Pod:

# grab the IP of the API Pod:
kubectl get po -n widgetario -l app=stock-api -o wide

kubectl exec deploy/web -n widgetario -it -c linkerd-debug -- sh

curl http://stock-api/stock/1

# insert Pod IP address:
tshark -i any -d tcp.port==80,ssl | grep <pod-ip>

The debug container is super useful in non-production environments

TLS is optional in the current Linkerd (2.9). Meshed services are upgraded to mTLS automatically. Non-meshed services can consume meshed services over plain HTTP.

Verify that a non-meshed Pod can use the stock API:

kubectl apply -f ./demo2/sleep.yaml

kubectl exec pod/sleep -n default -it -- sh

nslookup stock-api.widgetario.svc.cluster.local

wget -qO- stock-api.widgetario.svc.cluster.local/stock/1

Optionally enforcing mTLS is planned for a future release - as is authz, provide Service-to-Service authorization

Demo 4 - Traffic split for backend APIs

Traffic management in Linkerd uses the Traffic Split spec from the Service Mesh Interface.

You can manage traffic for a canary deployment with multiple Kubernetes Services:

products-api-services.yaml defines all those services and 100-0.yaml defines a split which sends all traffic to the existing v1 service.

Deploy the traffic split - the app behaviour is the same:

kubectl apply -f ./demo4/widgetario/products-api-services.yaml

kubectl apply -f ./demo4/widgetario/traffic-split/100-0.yaml

Try the app at http://localhost:8010 - same output, same set of Pods

products-api-v2.yaml deploys a new version of the products API with a price inflation, and 70-30.yaml sends it 30% of traffic.

Deploy the v2 API and shift the traffic:

kubectl apply -f ./demo4/widgetario/products-api-v2.yaml

kubectl apply -f ./demo4/widgetario/traffic-split/70-30.yaml

You get finer-grained traffic management with Service Profiles - a custom resource which changes behaviour for a target Kubernetes Service. Features include per-route monitoring, retries and timeouts.

You can also add Linkerd functionality to incoming external traffic, configuring your ingress controller. Then you can apply profiles and traffic splits to the entrypoint of your app - e.g. the web component in the Widgetario app.

Demo 5 - Observability

The Linkerd UI gives you a useful overview of the mesh, with Grafana dashboards showing the metrics it collects.

You can drill down into more detail using the Linkerd CLI.

Print some of the details about meshed services:

linkerd stat ts/products-api-canary -n widgetario

linkerd edges po -n widgetario

You can also monitor the real-time network communication between components.

Tap the calls from the web app to the stock API:

linkerd tap deploy/web --to deploy/stock-api -n widgetario

Browse & refresh the site to see the wire tap.

You can also integrate Linkerd with Jaeger, see Distributed tracing with Linkerd

Coming next