Zum Inhalt springen

Linkerd Cheat Sheet

Overview

Linkerd is an ultralight, security-first service mesh for Kubernetes that adds observability, reliability, and security to applications without requiring code changes. It uses a lightweight Rust-based proxy (linkerd2-proxy) as a sidecar that handles all TCP traffic in and out of each pod, providing automatic mTLS, latency-aware load balancing, and fine-grained traffic metrics.

Linkerd is a CNCF graduated project known for its simplicity, minimal resource footprint, and operational ease compared to heavier service meshes. It provides zero-config mutual TLS, golden metrics (success rate, latency, throughput), traffic splitting for canary deployments, retries, timeouts, and multi-cluster communication.

Installation

CLI Installation

# Install Linkerd CLI
curl -fsL https://run.linkerd.io/install | sh

# Add to PATH
export PATH=$HOME/.linkerd2/bin:$PATH

# Verify CLI
linkerd version

# macOS alternative
brew install linkerd

Install on Kubernetes

# Pre-flight check
linkerd check --pre

# Install CRDs
linkerd install --crds | kubectl apply -f -

# Install control plane
linkerd install | kubectl apply -f -

# Verify installation
linkerd check

# Install Viz extension (dashboard + metrics)
linkerd viz install | kubectl apply -f -

# Verify viz
linkerd viz check

# Open dashboard
linkerd viz dashboard

Install with Helm

helm repo add linkerd https://helm.linkerd.io/stable
helm repo update

# Install CRDs
helm install linkerd-crds linkerd/linkerd-crds \
  --namespace linkerd --create-namespace

# Generate trust anchor and issuer certificates
step certificate create root.linkerd.cluster.local ca.crt ca.key --profile root-ca --no-password --insecure
step certificate create identity.linkerd.cluster.local issuer.crt issuer.key --profile intermediate-ca --not-after 8760h --no-password --insecure --ca ca.crt --ca-key ca.key

# Install control plane
helm install linkerd-control-plane linkerd/linkerd-control-plane \
  --namespace linkerd \
  --set identityTrustAnchorsPEM="$(cat ca.crt)" \
  --set identity.issuer.tls.crtPEM="$(cat issuer.crt)" \
  --set identity.issuer.tls.keyPEM="$(cat issuer.key)"

# Install Viz
helm install linkerd-viz linkerd/linkerd-viz \
  --namespace linkerd-viz --create-namespace

Injecting the Sidecar Proxy

# Inject into a deployment
kubectl get deploy my-app -o yaml | linkerd inject - | kubectl apply -f -

# Inject entire namespace
kubectl annotate namespace my-namespace linkerd.io/inject=enabled

# Inject during deployment
cat deployment.yaml | linkerd inject - | kubectl apply -f -

# Verify injection
linkerd check --proxy -n my-namespace
# Namespace annotation for auto-injection
apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace
  annotations:
    linkerd.io/inject: enabled

CLI Commands

CommandDescription
linkerd checkValidate installation health
linkerd viz dashboardOpen web dashboard
linkerd viz stat deploy -n <ns>Show deployment metrics
linkerd viz top deploy/<name>Real-time request table
linkerd viz tap deploy/<name>Live traffic stream
linkerd viz routes deploy/<name>Per-route metrics
linkerd viz edges deploy -n <ns>Show service connections
linkerd inject <file>Add sidecar proxy to manifests
linkerd uninject <file>Remove sidecar from manifests
linkerd diagnostics proxy-metrics -n <ns> <pod>Raw proxy metrics

Observability

Golden Metrics

# Deployment stats (success rate, RPS, latency)
linkerd viz stat deploy -n my-namespace

# Per-route metrics
linkerd viz routes deploy/my-app -n my-namespace

# Live traffic tap
linkerd viz tap deploy/my-app -n my-namespace

# Top requests in real-time
linkerd viz top deploy/my-app -n my-namespace

# Service-to-service edges
linkerd viz edges deploy -n my-namespace

Prometheus Metrics

# Linkerd proxy exposes metrics at :4191/metrics on each pod
# Key metrics:
# request_total — total request count by status/direction
# response_latency_ms — response latency histogram
# tcp_open_total — open TCP connections
# tcp_open_connections — current open connections
# tcp_read_bytes_total — bytes received
# tcp_write_bytes_total — bytes sent

Traffic Management

Traffic Splitting (Canary)

apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
  name: my-app-canary
  namespace: my-namespace
spec:
  service: my-app
  backends:
    - service: my-app-stable
      weight: 900
    - service: my-app-canary
      weight: 100

Service Profiles (Retries, Timeouts, Routes)

apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  name: my-api.my-namespace.svc.cluster.local
  namespace: my-namespace
spec:
  routes:
    - name: GET /api/users
      condition:
        method: GET
        pathRegex: /api/users
      responseClasses:
        - condition:
            status:
              min: 500
              max: 599
          isFailure: true
      isRetryable: true
    - name: POST /api/orders
      condition:
        method: POST
        pathRegex: /api/orders
      timeout: 10s
  retryBudget:
    retryRatio: 0.2
    minRetriesPerSecond: 10
    ttl: 10s
# Generate service profile from OpenAPI spec
linkerd viz profile --open-api swagger.json my-api -n my-namespace | kubectl apply -f -

# Generate from live traffic
linkerd viz profile --tap deploy/my-api --tap-duration 30s my-api -n my-namespace

mTLS (Mutual TLS)

# Check mTLS status
linkerd viz edges deploy -n my-namespace

# Verify TLS on live traffic
linkerd viz tap deploy/my-app -n my-namespace --to deploy/my-backend | grep tls=true

# Check identity certificates
linkerd identity -n my-namespace
# Skip outbound mTLS for external services
apiVersion: v1
kind: Pod
metadata:
  annotations:
    config.linkerd.io/skip-outbound-ports: "3306,6379"

Configuration

Proxy Configuration (Annotations)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    metadata:
      annotations:
        # Resource limits
        config.linkerd.io/proxy-cpu-request: "100m"
        config.linkerd.io/proxy-memory-request: "64Mi"
        config.linkerd.io/proxy-cpu-limit: "500m"
        config.linkerd.io/proxy-memory-limit: "128Mi"
        # Timeouts
        config.linkerd.io/proxy-outbound-connect-timeout: "5000ms"
        # Skip ports
        config.linkerd.io/skip-inbound-ports: "4222"
        config.linkerd.io/skip-outbound-ports: "3306"
        # Opaque ports (no protocol detection)
        config.linkerd.io/opaque-ports: "3306,6379,27017"

Advanced Usage

Multi-Cluster

# Install multi-cluster extension
linkerd multicluster install | kubectl apply -f -

# Link clusters
linkerd multicluster link --cluster-name target-cluster | kubectl apply -f -

# Check gateway
linkerd multicluster gateways

# Export a service
kubectl label svc/my-api mirror.linkerd.io/exported=true

Authorization Policies

apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
  name: my-api
  namespace: my-namespace
spec:
  podSelector:
    matchLabels:
      app: my-api
  port: 8080
  proxyProtocol: HTTP/2
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
  name: allow-frontend
  namespace: my-namespace
spec:
  targetRef:
    group: policy.linkerd.io
    kind: Server
    name: my-api
  requiredAuthenticationRefs:
    - name: frontend-identity
      kind: MeshTLSAuthentication
      group: policy.linkerd.io

Troubleshooting

IssueSolution
linkerd check failsReview specific check failures; ensure CRDs and control plane are healthy
Sidecar not injectedVerify namespace annotation; check linkerd.io/inject is enabled
High latency after meshCheck proxy resource limits; increase CPU/memory for proxy
mTLS not establishedVerify both pods have sidecars; check identity certificates
Traffic split not workingVerify backend services exist; check TrafficSplit resource status
Dashboard shows no dataVerify Viz extension is installed; check Prometheus connectivity
Proxy crash loopCheck resource limits; review proxy logs with kubectl logs -c linkerd-proxy
Skip port not workingVerify annotation is on pod template, not deployment metadata