Linkerd Guide

Service Mesh Hub with Linkerd

While not offering as many features, Linkerd provides a lean, performant service mesh alternative to Istio.

As part of its multi-mesh vision, Service Mesh Hub can configure Linkerd in place of (or alongside) Istio via the same API

In this guide, we will:

Prerequisites

There are three pre-requisites to following these guides:

  1. Install kubectl
  2. Install meshctl
    • curl -sL https://run.solo.io/meshctl/install | sh && export PATH=$PATH:$HOME/.service-mesh-hub/bin
  3. Install linkerd:
    • curl -sL https://run.linkerd.io/install | sh && export PATH=$PATH:$HOME/.linkerd2/bin

Setup - Installing Linkerd

First, we'll install Linkerd to our cluster using the linkerd CLI:

# check the cluster is compatible with Linkerd
linkerd check --pre
kubernetes-api
--------------
√ can initialize the client
√ can query the Kubernetes API

kubernetes-version
------------------
√ is running the minimum Kubernetes API version
√ is running the minimum kubectl version

pre-kubernetes-setup
--------------------
√ control plane namespace does not already exist
√ can create non-namespaced resources
√ can create ServiceAccounts
√ can create Services
√ can create Deployments
√ can create CronJobs
√ can create ConfigMaps
√ can create Secrets
√ can read Secrets
√ no clock skew detected

pre-kubernetes-capability
-------------------------
√ has NET_ADMIN capability
√ has NET_RAW capability

linkerd-version
---------------
√ can determine the latest version
√ cli is up-to-date

Status check results are √

# install
linkerd install | kubectl apply -f -

That should be all it takes! We can verify the installation is complete:

linkerd check
kubernetes-api
--------------
√ can initialize the client
√ can query the Kubernetes API

kubernetes-version
------------------
√ is running the minimum Kubernetes API version
√ is running the minimum kubectl version

linkerd-existence
-----------------
√ 'linkerd-config' config map exists
√ heartbeat ServiceAccount exist
√ control plane replica sets are ready
√ no unschedulable pods
√ controller pod is running
√ can initialize the client
√ can query the control plane API

linkerd-config
--------------
√ control plane Namespace exists
√ control plane ClusterRoles exist
√ control plane ClusterRoleBindings exist
√ control plane ServiceAccounts exist
√ control plane CustomResourceDefinitions exist
√ control plane MutatingWebhookConfigurations exist
√ control plane ValidatingWebhookConfigurations exist
√ control plane PodSecurityPolicies exist

linkerd-identity
----------------
√ certificate config is valid
√ trust roots are using supported crypto algorithm
√ trust roots are within their validity period
√ trust roots are valid for at least 60 days
√ issuer cert is using supported crypto algorithm
√ issuer cert is within its validity period
√ issuer cert is valid for at least 60 days
√ issuer cert is issued by the trust root

linkerd-api
-----------
√ control plane pods are ready
√ control plane self-check
√ [kubernetes] control plane can talk to Kubernetes
√ [prometheus] control plane can talk to Prometheus
√ tap api service is running

linkerd-version
---------------
√ can determine the latest version
√ cli is up-to-date

control-plane-version
---------------------
√ control plane is up-to-date
√ control plane and cli versions match

Status check results are √

Setup - Installing Service Mesh Hub

Next, we'll install Service Mesh Hub to our cluster using the meschtl CLI:

meshctl install
Service Mesh Hub has been installed to namespace service-mesh-hub

Verify with meshctl check:

meshctl check
✅ Kubernetes API
-----------------
✅ Kubernetes API server is reachable
✅ running the minimum supported Kubernetes version (required: >=1.13)


✅ Service Mesh Hub Management Plane
------------------------------------
✅ installation namespace exists
✅ components are running


✅ Service Mesh Hub check found no errors

Finally we'll need to register the current cluster as a managed cluster:

meshctl cluster register \
  --remote-cluster-name linkerd-cluster \
  --remote-context $(kubectl config current-context)
Successfully wrote service account to remote cluster...
Successfully wrote kube config secret to master cluster...
Successfully set up CSR agent...

Cluster linkerd-cluster is now registered in your Service Mesh Hub installation

Discovery - Mesh CR

Service Mesh Hub defines a Mesh CRD which is generated by the mesh-discovery component. Mesh CRs represent detected installations of service mesh control planes.

Once we've installed the Hub, Linkerd, and registered our cluster, we should see the Mesh has been created. We can verify this with meshctl or kubectl:


meshctl get meshes

Linkerd:
+---------------------------------+-----------------+-----------+--------------+
|              NAME               |     CLUSTER     | NAMESPACE |   VERSION    |
+---------------------------------+-----------------+-----------+--------------+
| linkerd-linkerd-linkerd-cluster | linkerd-cluster | linkerd   | stable-2.7.0 |
+---------------------------------+-----------------+-----------+--------------+

kubectl get mesh -n service-mesh-hub

NAME                              AGE
linkerd-linkerd-linkerd-cluster   7m29s

Once we've verified mesh-discovery has picked up our Linkerd installation, let's move on to deploying our service.

Deploying the Bookinfo App

In this tutorial we'll be using the same Bookinfo application as used in Istio, slightly modified to work with Linkerd. Copy-paste the following into a file linkerd-bookinfo.yaml:

## Original bookinfo manifest


##################################################################################################
# Details service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: details
  labels:
    app: details
    service: details
spec:
  ports:
    - port: 9080
      name: http
  selector:
    app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-details
  labels:
    account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: details-v1
  labels:
    app: details
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: details
      version: v1
  template:
    metadata:
      labels:
        app: details
        version: v1
    spec:
      serviceAccountName: bookinfo-details
      containers:
        - name: details
          image: docker.io/istio/examples-bookinfo-details-v1:1.15.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9080
---
##################################################################################################
# Ratings service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: ratings
  labels:
    app: ratings
    service: ratings
spec:
  ports:
    - port: 9080
      name: http
  selector:
    app: ratings
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-ratings
  labels:
    account: ratings
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ratings-v1
  labels:
    app: ratings
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ratings
      version: v1
  template:
    metadata:
      labels:
        app: ratings
        version: v1
    spec:
      serviceAccountName: bookinfo-ratings
      containers:
        - name: ratings
          image: docker.io/istio/examples-bookinfo-ratings-v1:1.15.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9080
---
##################################################################################################
# Reviews service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: reviews
  labels:
    app: reviews
    service: reviews
spec:
  ports:
    - port: 9080
      name: http
  selector:
    app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-reviews
  labels:
    account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v1
  labels:
    app: reviews
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v1
  template:
    metadata:
      labels:
        app: reviews
        version: v1
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
        - name: reviews
          image: docker.io/istio/examples-bookinfo-reviews-v1:1.15.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v2
  labels:
    app: reviews
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v2
  template:
    metadata:
      labels:
        app: reviews
        version: v2
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
        - name: reviews
          image: docker.io/istio/examples-bookinfo-reviews-v2:1.15.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v3
  labels:
    app: reviews
    version: v3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v3
  template:
    metadata:
      labels:
        app: reviews
        version: v3
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
        - name: reviews
          image: docker.io/istio/examples-bookinfo-reviews-v3:1.15.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9080
---
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: productpage
  labels:
    app: productpage
    service: productpage
spec:
  ports:
    - port: 9080
      name: http
  selector:
    app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-productpage
  labels:
    account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: productpage-v1
  labels:
    app: productpage
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: productpage
      version: v1
  template:
    metadata:
      labels:
        app: productpage
        version: v1
    spec:
      serviceAccountName: bookinfo-productpage
      containers:
        - name: productpage
          image: docker.io/istio/examples-bookinfo-productpage-v1:1.15.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9080
---

---

## TrafficShift Destinations

apiVersion: v1
kind: Service
metadata:
  name: reviews-v2
spec:
  selector:
    app: reviews
    version: v2
  ports:
    - protocol: TCP
      port: 9080
      targetPort: 9080

---

apiVersion: v1
kind: Service
metadata:
  name: reviews-v3
spec:
  selector:
    app: reviews
    version: v3
  ports:
    - protocol: TCP
      port: 9080
      targetPort: 9080

Now we'll inject these resources with the Linkerd sidecar and deploy them to our cluster:

kubectl create ns bookinfo; \
 linkerd inject linkerd-bookinfo.yaml | kubectl apply -f - -n bookinfo
namespace/bookinfo created

service "details" skipped
serviceaccount "bookinfo-details" skipped
deployment "details-v1" injected
service "ratings" skipped
serviceaccount "bookinfo-ratings" skipped
deployment "ratings-v1" injected
service "reviews" skipped
serviceaccount "bookinfo-reviews" skipped
deployment "reviews-v1" injected
deployment "reviews-v2" injected
deployment "reviews-v3" injected
service "productpage" skipped
serviceaccount "bookinfo-productpage" skipped
deployment "productpage-v1" injected
document missing "kind" field, skipped
service "reviews-v2" skipped
service "reviews-v3" skipped

service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
service/reviews-v2 created
service/reviews-v3 created

Once the injected application is deployed, we should be able to see a corresponding MeshService CR created by mesh-discovery:


meshctl get services


Kubernetes Mesh Services:
+---------------------------------+--------------------------------+------------------------------------------------------+
|              MESH               |        SERVICE + PORTS         |                   LABELS + SUBSETS                   |
+---------------------------------+--------------------------------+------------------------------------------------------+
| linkerd-linkerd-linkerd-cluster | Name: details                  | Service Labels:                                      |
|                                 | Namespace: bookinfo            |   app: details                                       |
|                                 | Cluster: linkerd-cluster       |                                                      |
|                                 |                                |   service: details                                   |
|                                 | Ports:                         | Workload Selector Labels:                            |
|                                 | - Name: http                   |   app: details                                       |
|                                 |   Port: 9080                   |                                                      |
|                                 |   Protocol: TCP                |                                                      |
+---------------------------------+--------------------------------+------------------------------------------------------+
| linkerd-linkerd-linkerd-cluster | Name: productpage              | Service Labels:                                      |
|                                 | Namespace: bookinfo            |   app: productpage                                   |
|                                 | Cluster: linkerd-cluster       |                                                      |
|                                 |                                |   service: productpage                               |
|                                 | Ports:                         | Workload Selector Labels:                            |
|                                 | - Name: http                   |   app: productpage                                   |
|                                 |   Port: 9080                   |                                                      |
|                                 |   Protocol: TCP                |                                                      |
+---------------------------------+--------------------------------+------------------------------------------------------+
| linkerd-linkerd-linkerd-cluster | Name: ratings                  | Service Labels:                                      |
|                                 | Namespace: bookinfo            |   app: ratings                                       |
|                                 | Cluster: linkerd-cluster       |                                                      |
|                                 |                                |   service: ratings                                   |
|                                 | Ports:                         | Workload Selector Labels:                            |
|                                 | - Name: http                   |   app: ratings                                       |
|                                 |   Port: 9080                   |                                                      |
|                                 |   Protocol: TCP                |                                                      |
+---------------------------------+--------------------------------+------------------------------------------------------+
| linkerd-linkerd-linkerd-cluster | Name: reviews                  | Service Labels:                                      |
|                                 | Namespace: bookinfo            |   app: reviews                                       |
|                                 | Cluster: linkerd-cluster       |                                                      |
|                                 |                                |   service: reviews                                   |
|                                 | Ports:                         | Workload Selector Labels:                            |
|                                 | - Name: http                   |   app: reviews                                       |
|                                 |   Port: 9080                   |                                                      |
|                                 |   Protocol: TCP                | Subsets:                                             |
|                                 |                                |   linkerd.io/proxy-deployment:                       |
|                                 |                                |   - reviews-v1                                       |
|                                 |                                |   - reviews-v2                                       |
|                                 |                                |   - reviews-v3                                       |
|                                 |                                |   version:                                           |
|                                 |                                |   - v1                                               |
|                                 |                                |   - v2                                               |
|                                 |                                |   - v3                                               |
+---------------------------------+--------------------------------+------------------------------------------------------+
| linkerd-linkerd-linkerd-cluster | Name: reviews-v2               | Workload Selector Labels:                            |
|                                 | Namespace: bookinfo            |   app: reviews                                       |
|                                 | Cluster: linkerd-cluster       |   version: v2                                        |
|                                 |                                |                                                      |
|                                 | Ports:                         |                                                      |
|                                 | - Name:                        |                                                      |
|                                 |   Port: 9080                   |                                                      |
|                                 |   Protocol: TCP                |                                                      |
+---------------------------------+--------------------------------+------------------------------------------------------+
| linkerd-linkerd-linkerd-cluster | Name: reviews-v3               | Workload Selector Labels:                            |
|                                 | Namespace: bookinfo            |   app: reviews                                       |
|                                 | Cluster: linkerd-cluster       |   version: v3                                        |
|                                 |                                |                                                      |
|                                 | Ports:                         |                                                      |
|                                 | - Name:                        |                                                      |
|                                 |   Port: 9080                   |                                                      |
|                                 |   Protocol: TCP                |                                                      |
+---------------------------------+--------------------------------+------------------------------------------------------+

+---------------------------------+-----------------+-----------+--------------+

kubectl get meshservice -n service-mesh-hub

NAME                                             AGE
details-bookinfo-linkerd-cluster                 15m
productpage-bookinfo-linkerd-cluster             15m
ratings-bookinfo-linkerd-cluster                 15m
reviews-bookinfo-linkerd-cluster                 15m
reviews-v2-bookinfo-linkerd-cluster              15m
reviews-v3-bookinfo-linkerd-cluster              15m

Finally, we should be able to reach the ProductPage UI using kubectl port-forward:

kubectl port-forward -n bookinfo deployment/productpage-v1 9080 # in one terminal
open http://localhost:9080/productpage # in another terminal

We should see the Product Page UI. If we refresh the page, the stars in the Book Reviews section should change, as the Bookinfo app load balances across 3 different versions of the “reviews” service:

Next We'll set up a Traffic Shifting rule which will force all traffic to the “red stars” version of the reviews service.

Configuring a Traffic Policy

Let's create a TrafficPolicy CR to instruct Service Mesh Hub to direct all traffic to the reviews-v3 version of the reviews service:


meshctl create trafficpolicy # run interactively
 meshctl create trafficpolicy --namespace bookinfo


? Specify source workloads labels in the format (key1=value1, key2=value2), omit to permit workloads of with any labels 
? Specify source workloads namespaces as comma-delimited list, omit to permit workloads of any namespace 
? Select the destination Services, omit to select all  [Use arrows to move, space to select, type to filter]
> [x]  reviews-bookinfo-linkerd-cluster.service-mesh-hub.linkerd-cluster


cat <<EOF | kubectl apply -f -
apiVersion: networking.zephyr.solo.io/v1alpha1
kind: TrafficPolicy
metadata:
  name: reviews-v3-shift
  namespace: bookinfo
spec:
  destinationSelector:
    matcher:
      labels:
        app: reviews
  httpRequestMatchers:
  - prefix: /
  trafficShift:
    destinations:
    - destination:
        name: reviews-v3
        namespace: bookinfo
        cluster: linkerd-cluster
      port: 9080
      weight: 1
EOF

When we refresh the Productpage UI, we should now only see red stars. Try refreshing a few times to make sure 100% of traffic is sent to reviews-v3:

Great! We've successfully discovered and configured our Linkerd mesh with Service Mesh Hub!

Next Steps

Traffic Shifting is not the only option available for configuring mesh traffic. We recommend checking out the reference documentation for a full description of what's possible with Service Mesh Hub.