Service Mesh Basics with Istio and Linkerd in Kubernetes

Service Mesh Basics with Istio and Linkerd in Kubernetes

Learn how a thin layer of proxies can add encryption, retries, traffic control, and rich metrics to every conversation between your services, without changing a line of application code, and when that trade is worth making.

Imagine a big company where hundreds of employees phone each other all day. Some calls drop, some are slow, and nobody knows who is calling whom. Now imagine the company hires a personal assistant for every employee. Each assistant answers the phone, checks the caller’s identity, redials when a call fails, and writes every call in a logbook. The employees just talk as usual, but the whole company becomes safer, more reliable, and easy to understand.

A service mesh is that team of assistants for your applications. Every service gets a small helper program that handles its network conversations, and a central office tells all the helpers how to behave. This tutorial explains the idea from the ground up, shows how the two best-known meshes, Istio and Linkerd, work inside Kubernetes, and gives you the honest trade-offs, patterns, and warnings that real teams rely on.

1Why Microservices Need Help Talking

A service mesh solves a problem that only appears once you have many small services. To understand it, we first need to see that problem clearly.

From one big program to many small ones

Older applications were often built as a single large program, called a monolith. All the features lived in one place and talked to each other through ordinary function calls inside the same program. Those calls are fast and almost never fail.

Modern teams often split an application into many small programs called microservices. One service handles logins, another handles payments, another handles search. They run separately, often in different containers, and they talk to each other over the network. A container is a sealed package holding a program and everything it needs, and Kubernetes is the system that runs and manages all those containers across many computers.

The network is not reliable

Network calls are very different from function calls. They can be slow, they can fail halfway, and they can be intercepted. When one service calls another, many things can go wrong: the other service may be starting up, overloaded, or simply gone. Someone on the network could also read or change the message if it is not encrypted.

Every team that builds microservices must therefore deal with the same list of chores. Calls should be retried when they fail, but not forever. Slow calls need time limits. Traffic should be encrypted. Each service should prove who it is. And operators need to see which service is calling which, and how healthy each conversation is.

Simple Analogy

Think of a city where every shop delivers goods to other shops using its own vans, its own maps, and its own locks. Some shops forget to lock the van, some take wrong turns, and nobody keeps a record. The city would be far better off with a shared, professional courier service that every shop uses, which handles routes, locks, and receipts in the same way for everyone.

The old way: put it in a library

Before service meshes, teams solved these chores by adding code libraries to every application. A library might handle retries, another might handle encryption, another might collect metrics. This works, but it has serious costs. Every language needs its own version of every library. Every update requires rebuilding and redeploying each application. And if one team forgets to add the library, or configures it differently, the whole system has a hole in it.

Chore 1

Retries and Timeouts

Try again when a call fails, but give up after a sensible time so slow services do not drag everyone down.

Chore 2

Encryption

Scramble traffic between services so a spy on the network learns nothing useful.

Chore 3

Identity

Let each service prove who it is, so a service can refuse calls from strangers.

Chore 4

Load Balancing

Spread requests across several copies of a service, and steer away from slow or broken ones.

Chore 5

Traffic Control

Send a small share of requests to a new version, or route special requests to a special place.

Chore 6

Observability

Record how many calls happen, how many fail, and how long they take, for every pair of services.

i
The key insight

All six chores are about the conversation between services, not about the business logic inside them. That is why they can be moved out of the application and into a shared layer that treats every service the same way.

2Service Mesh: The Core Idea

A service mesh moves the networking chores out of your code and into a layer of small proxies that sit beside every service.

The idea in plain words

A service mesh is a dedicated layer of infrastructure that manages communication between services. It works by placing a small network program, called a proxy, next to each service. A proxy is a middleman that receives a message on behalf of someone else and passes it along. In a mesh, all traffic going into or out of a service passes through its proxy first.

Because every message flows through a proxy, the proxy can do useful work on it: encrypt it, retry it, time it, count it, or refuse it. The application itself knows nothing about this. It sends a plain request as if it were talking directly to the other service, and the proxies take care of everything else.

Simple Analogy

Picture every office in a building having its own receptionist. Staff hand outgoing letters to the receptionist, who puts them in a secure envelope, notes the time, and sends them off. Incoming letters are opened by the receptionist, who checks the sender’s identity before handing the contents to the staff. The staff just write and read letters, and the receptionists give the whole building a consistent, secure post system.

The two halves of a mesh

Every service mesh has two parts. The proxies that carry traffic are called the data plane, because the data flows through them. The central program that tells all the proxies what to do is called the control plane. The control plane does not carry any user traffic. It only sends instructions, such as which services exist, which rules to apply, and which security certificates to use. We look at both in detail in Chapter 4.

0
application code changes needed for the basic features
2
parts: a data plane of proxies and a control plane of managers
100%
of meshed traffic passes through a proxy

The vocabulary you will use

Term 1

Proxy

A small program that receives traffic for a service and forwards it, adding features on the way.

Term 2

Sidecar

A proxy container placed in the same pod as the application, sharing its network, like a sidecar attached to a motorbike.

Term 3

Data Plane

The collection of all proxies that carry real traffic between services.

Term 4

Control Plane

The central manager that configures the proxies, hands out identities, and tracks which services exist.

Term 5

mTLS

Mutual TLS, a way of encrypting traffic where both sides prove their identity to each other, not just one.

Term 6

East-West Traffic

Traffic between services inside the cluster. It is called east-west because diagrams draw it sideways.

Term 7

North-South Traffic

Traffic entering or leaving the cluster from the outside world, such as a user’s browser request.

Term 8

Golden Signals

Four basic health measures for a service: latency, traffic, errors, and saturation.

“A service mesh takes the boring, repeated work of talking safely and reliably, and does it once, for everyone.”
i
Istio and Linkerd

Istio and Linkerd are the two best-known service meshes for Kubernetes. Both follow the idea above, and both are open source projects that have reached the top maturity level of the Cloud Native Computing Foundation. They differ in size, features, and philosophy, which we compare in Chapter 11.

3Kubernetes Building Blocks You Need First

A mesh is built on top of ordinary Kubernetes objects. Knowing them makes the rest of the tutorial feel natural.

Block 1

Pod

The smallest unit Kubernetes runs. A pod holds one or more containers that share a network address and are started together.

Block 2

Service

A stable name and address in front of a changing group of pods, so callers do not need to know individual pod addresses.

Block 3

kube-proxy

The component on each node that forwards traffic sent to a Service to one of its pods, working at the connection level.

Block 4

Namespace

A named room inside the cluster used to group resources. Meshes are often switched on one namespace at a time.

Block 5

Label and Annotation

Small tags on objects. A label on a namespace is the usual way to tell a mesh “please manage the pods here”.

Block 6

Admission Webhook

A checkpoint that can change objects as they enter the cluster. Meshes use one to add proxies to new pods automatically.

Block 7

Custom Resource

A new kind of Kubernetes object added by a project. Meshes use them to hold rules such as routes and security policies.

Block 8

ServiceAccount

The identity a pod uses inside Kubernetes. Meshes build each service’s cryptographic identity from it.

Block 9

Ingress and Gateway

The front door that lets outside traffic into the cluster and routes it to the right Service.

Block 10

Init Container

A short-lived container that runs before the main containers, often used to prepare the network settings of a pod.

What Kubernetes already does for traffic

Kubernetes already gives you basic networking. A Service provides a stable address, and kube-proxy spreads connections across the pods behind it. This is enough for many simple applications, but it works at the level of connections, not individual requests. It does not understand HTTP, does not encrypt anything by itself, and cannot retry, time out, or split traffic by percentage.

This gap is exactly what a mesh fills. The mesh does not replace Kubernetes networking. It builds a smarter layer on top of it, using the pods, Services, and labels that already exist.

Simple Analogy

Kubernetes networking is like a postal system that delivers a sealed parcel to the right building. It does not read the parcel, guarantee that it is tracked, or try again if the parcel is lost. A service mesh is like adding a premium courier on top, which tracks each parcel, checks the recipient’s identity, and resends if needed.

!
Common misconception

Many people believe that a service mesh replaces Ingress, network policies, or Kubernetes Services. It does not. The mesh works together with them, and often uses them as its starting information about which services exist.

Why per-request matters

Modern services often use long-lived connections, especially with the gRPC protocol, which sends many requests over one connection. Because kube-proxy balances connections rather than requests, all the requests on one long connection may end up at a single pod, while other pods sit idle. A mesh proxy understands each request separately, so it can spread them evenly across all pods.

4The Data Plane and the Control Plane

Every mesh is split into workers that handle traffic and managers that give instructions. Keeping these two roles apart is the secret of its design.

The data plane: the proxies

The data plane is made of the proxies that sit beside your services. They are the busy workers. Every request goes through them, so they must be fast, small, and reliable. Each proxy knows how to find other services, balance load, encrypt and decrypt traffic, apply retries and timeouts, and record metrics.

Istio uses a well-known open source proxy called Envoy. Envoy is powerful and highly configurable, which is why many other tools use it too. Linkerd takes a different route and uses its own tiny proxy, written in the Rust language and built only for Linkerd. It does fewer things, but it is designed to be lean and simple.

The control plane: the managers

The control plane is the brain. It does not touch user traffic. Instead, it watches the cluster, learns which services and pods exist, and pushes that knowledge, along with your rules, to every proxy. It also acts as a certificate authority, meaning it issues the digital identity documents that let services prove who they are.

Because the control plane is separate, a short outage in it does not stop traffic. The proxies already have their instructions and keep working. They just cannot receive new instructions until the control plane returns.

flowchart LR
    CP["Control plane: gives config, identities, and service lists"] -->|"instructions"| PA["Proxy beside Service A"]
    CP -->|"instructions"| PB["Proxy beside Service B"]
    AA["Service A"] --- PA
    PA -->|"encrypted traffic"| PB
    PB --- BB["Service B"]
        
FIG 1 — Control plane instructs the proxies, and the proxies carry the traffic

Read the figure from the top. The control plane sends instructions to each proxy, shown by the arrows leaving it. The services themselves, drawn as A and B, only talk to their own proxy, shown by the plain lines. The real traffic goes from proxy to proxy along the encrypted arrow. The control plane never appears on that path.

Simple Analogy

Consider an airport. The control tower does not carry passengers. It sends instructions to pilots about routes, timing, and safety. The aircraft are the ones that actually carry people. If the tower loses radio for a moment, planes already in the air continue on their assigned paths, though no new instructions arrive until contact returns.

1

Discover

The control plane watches Kubernetes for Services, pods, and their addresses, so it always has a current map of the cluster.

2

Configure

It combines that map with your rules and sends each proxy the exact instructions it needs.

3

Identify

It issues each proxy a short-lived certificate so that services can prove who they are to each other.

4

Update

When pods come and go or rules change, it sends fresh instructions so the proxies stay correct.

i
Failure behaviour

Proxies keep their last known configuration when the control plane is unavailable. Existing traffic continues normally. The real risk is a long outage, because certificates expire and new pods cannot get their identity or configuration.

5How the Proxy Gets Into Your Pod

The magic of a mesh is that developers do nothing. This chapter reveals the trick behind that.

Automatic injection

When you want a namespace to be part of the mesh, you mark it with a label or annotation. From then on, whenever a new pod is created in that namespace, Kubernetes sends the pod definition through an admission webhook belonging to the mesh. The webhook quietly adds the proxy container to the pod before the pod is saved. This is called sidecar injection.

Developers write their normal deployment as usual. They never mention the proxy. The mesh adds it automatically, which is why teams can adopt a mesh gradually, one namespace at a time. Pods that already exist do not change until they are restarted, so enabling injection usually needs a rolling restart of the applications.

flowchart TD
    A["Namespace is labelled for the mesh"] --> B["A new pod is requested"]
    B --> C["API server calls the mesh admission webhook"]
    C --> D["Webhook adds the proxy container and network setup"]
    D --> E["Pod is scheduled and started with its proxy"]
    E --> F["Proxy contacts the control plane for identity and settings"]
        
FIG 2 — How a proxy is added to a pod without changing the application

Catching the traffic

Adding a proxy is only half of the trick. The application must be forced to send its traffic through that proxy, even though the application does not know the proxy exists. The mesh does this by changing the pod’s network rules so that all outgoing traffic is redirected to the proxy, and all incoming traffic arrives at the proxy first.

This redirection is usually set up by a short init container that runs before the application starts. It needs elevated network permissions to do its job, which some organisations dislike. As an alternative, both Istio and Linkerd offer a network plugin approach that does the redirection at the node level, so pods do not need those permissions.

Simple Analogy

Imagine that when a new employee joins, the company automatically assigns them a receptionist and changes the office phone system so every call, in and out, goes through that receptionist. The employee does nothing and notices nothing, apart from the fact that calls suddenly become safer and better tracked.

Startup, shutdown, and other lifecycle wrinkles

Because the proxy and the application are separate containers, their starting order matters. If the application starts first and immediately makes a call, the proxy may not be ready yet, and the call fails. Meshes offer settings to hold the application until the proxy is ready. Newer Kubernetes versions also support sidecar containers as a first-class idea, which have a clear start and stop order relative to the main container.

The same issue appears at shutdown. If the proxy stops before the application has finished its last requests, those requests fail. It is also a classic problem with batch jobs, where the job finishes but the proxy keeps running, so the pod never completes. Good mesh setups handle both cases explicitly.

!
Common mistake

Turning on injection and forgetting that existing pods must be restarted. The namespace looks meshed, but old pods are running without proxies, so the traffic between old and new pods behaves differently than you expect.

i
Opting out is possible

You can exclude a specific pod, port, or namespace from the mesh. This is useful for special workloads, such as those using unusual protocols, or for a database that should not have traffic captured.

6Architecture: Istio and Linkerd Side by Side

Both meshes follow the same two-part design, but they package the parts differently. Knowing the pieces helps you read logs and diagrams later.

Istio’s parts

Istio’s control plane is delivered mainly as a single program called istiod. It watches Kubernetes, converts your rules into proxy configuration, sends that configuration to every Envoy proxy, and acts as the certificate authority that issues identities. Older versions split these jobs across several programs, which were merged into one to make Istio simpler to run.

Istio’s data plane is a set of Envoy proxies, one per pod in the classic sidecar mode. Istio also provides gateways, which are Envoy proxies running at the edge of the mesh, handling traffic entering and leaving the cluster. Istio’s rules are written as Kubernetes custom resources, such as routes, destination settings, gateways, and security policies.

Linkerd’s parts

Linkerd’s control plane is made of a few small components. One keeps track of destinations, meaning where each service’s pods are. One acts as the identity authority, issuing certificates. One is the injector, which adds the proxy to new pods. Extension components add features such as a metrics dashboard.

Linkerd’s data plane is its purpose-built Rust proxy, added to every meshed pod. Linkerd deliberately keeps its configuration small. It leans on the newer Kubernetes Gateway API for routing rules and on a small set of its own resources for security policy.

Istio 1

istiod

The single control plane program: discovery, configuration, and certificate authority in one.

Istio 2

Envoy Sidecar

The feature-rich proxy added beside each application container.

Istio 3

Ingress and Egress Gateways

Edge proxies that control traffic entering and leaving the mesh.

Istio 4

Traffic and Security Resources

Kubernetes objects describing routes, destinations, encryption modes, and access rules.

Linkerd 1

Destination Service

Tells proxies where each service’s pods are and how to reach them.

Linkerd 2

Identity Service

Issues short-lived certificates to every proxy and acts as the mesh’s certificate authority.

Linkerd 3

Proxy Injector

The admission webhook that adds the Rust proxy to pods in meshed namespaces.

Linkerd 4

Micro-Proxy

A lightweight proxy designed to do a small number of things quickly and predictably.

Simple Analogy

Istio is like a large, fully equipped hotel chain with a service for every request, from concierge to conference rooms, and a big operations office to run it all. Linkerd is like a small, well-run guesthouse that offers the essentials extremely well, with less to learn and less to maintain. Both give you a bed for the night, but they suit different guests.

i
Where certificates come from

In both meshes, the control plane holds a root of trust and issues short-lived certificates to proxies. Many production setups plug in their own certificate authority, so the mesh’s trust chain is anchored in something the organisation already controls.

7Internal Working: The Life of a Request

Let us follow a single request from one service to another and see exactly what each proxy does along the way.

Step by step through the mesh

Suppose a checkout service wants to call a payment service. The checkout application sends an ordinary request to the payment service’s name, as it always did. It has no idea a mesh exists. What happens next is a chain of events inside two proxies, shown in the diagram below.

sequenceDiagram
    participant C as Checkout App
    participant CP as Checkout Proxy
    participant SP as Payment Proxy
    participant S as Payment App
    C->>CP: Plain request to the payment service name
    CP->>CP: Pick a healthy pod, apply retry and timeout rules
    CP->>SP: Encrypted request using mutual TLS
    SP->>SP: Verify caller identity and check access rules
    SP->>S: Plain request on the local connection
    S-->>SP: Response
    SP-->>CP: Encrypted response
    CP-->>C: Response, metrics recorded on both sides
        
FIG 3 — A request travelling through the client proxy and the server proxy
1

The application sends a plain request

The checkout code asks for the payment service by name. The pod’s network rules quietly redirect this outgoing call to the local proxy.

2

The client proxy decides where to go

It already knows, from the control plane, the list of healthy payment pods. It picks one using a balancing method, and applies any routing, timeout, or retry rules that apply.

3

The connection is secured

The two proxies set up an encrypted connection, and each shows its certificate to the other. Both sides now know exactly who they are talking to.

4

The server proxy checks the rules

It reads the caller’s identity from the certificate and checks whether that caller is allowed to reach this service. If not, the request stops here.

5

The payment application answers

The server proxy hands the plain request to the application, which does its work and sends a response back the same way.

6

Both proxies record the result

Each proxy counts the request, measures how long it took, and notes whether it succeeded, feeding the dashboards you will meet in Chapter 10.

Simple Analogy

It is like two offices exchanging a confidential letter through their receptionists. The sender’s receptionist looks up the right recipient, seals the letter, and shows an official badge. The recipient’s receptionist checks the badge, checks the guest list, and only then opens the envelope and hands the letter over. Both keep a record of the exchange.

How proxies know where to send traffic

Proxies do not search for services on their own. The control plane watches Kubernetes for Services and their pods, and continually sends each proxy the current list of addresses for every service. When a pod starts, stops, or becomes unhealthy, the change flows to the proxies within moments. This means the proxy always has a fresh map and never needs to ask a central directory on each request.

Smarter load balancing

Because a mesh proxy understands individual requests, it can balance them far better than the default. Instead of sending each connection to a random pod, it can favour the pod that has been answering fastest. Linkerd, for example, uses a latency-aware method that weighs recent response times. This steers work away from slow or struggling pods before they cause problems.

!
Two hops means extra time

Every request now passes through two proxies, one on each side. Each hop adds a small delay, usually a few milliseconds or less, and uses some memory and processor time. For most applications this is invisible, but for extremely latency-sensitive systems it must be measured, not assumed.

8Traffic Management

Because every request passes through a proxy, you can shape traffic with rules instead of code. Here are the main tools.

Retries

If a call fails because of a brief problem, the proxy sends it again, possibly to a different pod. This hides short glitches from users. Retries must be limited, and should only be used for requests that are safe to repeat.

Timeouts

A timeout sets how long a proxy waits before giving up on a call. Without timeouts, one slow service can leave callers waiting for ever, and the slowness spreads through the whole system.

Circuit breaking

When a service keeps failing, the proxy temporarily stops sending it traffic, giving it time to recover instead of hammering it further. Istio offers this through outlier detection and connection limits, and recent Linkerd releases also offer forms of circuit breaking.

Traffic splitting

You can send a chosen percentage of requests to one version of a service and the rest to another. This is the basis of canary releases, where a new version first receives a small share of real traffic.

Header-based routing

Rules can look at request headers and send special requests, such as those from testers, to a special version, while everyone else goes to the normal one.

Traffic mirroring

The proxy copies live requests to a second version and discards its answers. You can test a new version with real traffic without any user being affected.

Fault injection

Istio can deliberately add delays or errors to a small share of requests, so teams can test how their systems behave when things go wrong, before real failures happen.

flowchart LR
    U["Caller"] --> P["Caller proxy applies the route rule"]
    P -->|"90 percent"| V1["Checkout version 1"]
    P -->|"10 percent"| V2["Checkout version 2"]
        
FIG 4 — A weighted route sending ten percent of requests to a new version

The figure shows a canary release. The caller’s proxy applies a rule that sends ninety percent of requests to version one and ten percent to version two. To roll forward, you change the numbers. To roll back, you set the new version to zero. No pods are added or removed, and no application changes are needed. This is far finer control than Kubernetes offers on its own, where traffic share is tied to the number of pods.

Simple Analogy

Think of a road with a traffic officer at a junction. The officer can wave nine cars down the old road for every one sent down the new road, hold cars back if the new road jams, or send a decoy car down the new road just to see how it copes. The drivers simply follow the officer’s signals.

!
Beware of retry storms

If every layer of a system retries three times, one failed call can become dozens of calls hitting an already struggling service, which makes the failure worse. Set retries in one place, cap the total number, and use retry budgets where available.

i
Idempotency matters

A request is idempotent if repeating it has the same effect as doing it once, such as reading a record. Retrying a payment request that might already have succeeded could charge a customer twice. Only retry operations that are safe to repeat.

9Security: Identity, mTLS, and Authorization

For many teams, security is the main reason to adopt a mesh. The mesh can encrypt every internal call and decide who may make it.

Identity: proving who you are

In a mesh, every service gets a cryptographic identity. This is a certificate, a digital document that says “this proxy belongs to this service account in this namespace”, signed by the mesh’s certificate authority. The identity is tied to the Kubernetes ServiceAccount of the pod, so it reflects something real rather than a name someone typed in.

Certificates are short-lived, typically valid for about a day, and are rotated automatically by the control plane. If one is stolen, it becomes useless quickly. Nobody needs to copy files, set reminders, or restart applications to renew them.

mTLS: encryption where both sides prove themselves

You may know that ordinary secure web browsing uses TLS, where the website proves its identity to the browser. Mutual TLS, or mTLS, goes one step further: both sides present certificates. The client proxy proves who it is to the server, and the server proxy proves who it is to the client. Everything sent between them is encrypted.

The result is that traffic between meshed services cannot be read or altered by someone on the network, and neither side can pretend to be someone else. All of this happens between the proxies, so the applications need no certificate code at all.

Simple Analogy

Imagine two diplomats meeting in a corridor. Each shows an official passport, and each checks the other’s passport against a trusted register before speaking. Once both are satisfied, they talk in a sealed room where nobody else can listen. That is mTLS: shown identity on both sides, then private conversation.

Authorization: deciding who may call whom

Knowing who is calling is only useful if you act on it. Authorization policies let you say things like “only the checkout service may call the payment service”, or “only requests using this method on this path are allowed”. The server proxy checks each request against these rules and rejects anything that does not match.

A strong starting position is to deny everything by default and then allow only the specific calls that are needed. This limits the damage if any one service is compromised, because the attacker can only reach what that service was already permitted to call. This idea is often called zero trust.

ModeWhat it doesWhen to use it
Permissive mTLSAccepts both encrypted and plain trafficDuring migration, while some pods are not yet meshed
Strict mTLSAccepts only encrypted, authenticated trafficOnce every caller is meshed
Allow by defaultAny authenticated caller may call anythingEarly adoption, with a plan to tighten
Deny by defaultOnly explicitly allowed calls succeedTarget state for sensitive systems

Hardening the mesh itself

Control 1

Protect the Control Plane

The control plane issues identities and pushes rules, so restrict who can reach and change it, and keep it patched.

Control 2

Restrict Who Edits Mesh Rules

Use Kubernetes access control on the mesh’s custom resources, because a bad rule can open or block traffic everywhere.

Control 3

Use Your Own Root of Trust

Anchor the mesh’s certificates in a certificate authority your organisation already manages and protects.

Control 4

Control Outbound Traffic

Decide which external addresses services may reach, so a compromised service cannot freely send data out.

Control 5

Keep Network Policies Too

Kubernetes network policies still block traffic at the network level, protecting anything that bypasses or lacks a proxy.

Control 6

Move Beyond Permissive Mode

Permissive mode is a stepping stone. Leaving it on for ever means unencrypted traffic is still accepted.

!
A mesh is not a complete security solution

The mesh protects traffic between meshed services. It does not fix vulnerable application code, protect data at rest, or secure pods that were never added to the mesh. Treat it as one strong layer, combined with the others.

10Observability: Metrics, Logs, and Traces

Because every proxy sees every request, a mesh gives you detailed visibility into your system almost for free.

Simple Analogy

Imagine a road network where every junction has a counter that records how many cars pass, how long they wait, and how many break down. Suddenly you can see the traffic jams, the slow roads, and the dangerous corners without sending anyone out to look. The proxies are those junction counters for your services.

Metrics: the golden signals for every service

Each proxy records, for every service pair, the four golden signals. These are enough to describe the health of almost any service, and the mesh provides them uniformly, whatever language the application uses.

Signal 1

Latency

How long requests take, best viewed as percentiles such as the slowest one percent, not only an average.

Signal 2

Traffic

How many requests arrive per second, per service and per route.

Signal 3

Errors

What fraction of requests fail, including failures caused by timeouts and refused connections.

Signal 4

Saturation

How close resources such as connections and processors are to their limits.

These metrics are exposed in a format that Prometheus, a popular monitoring system, can collect. They can then be drawn as charts in Grafana. Istio has a companion tool called Kiali that draws a live map of which services talk to which, and Linkerd ships a lightweight dashboard that shows success rates and latency for each service and each route.

Logs and access records

Proxies can write an access record for every request, showing who called whom, the method, the path, the response code, and the time taken. These records are very useful when investigating an incident, but they are also very numerous. Most teams turn them on selectively, for specific services or only for failed requests, to control storage cost.

Distributed traces

A trace follows a single user action across many services, showing the time spent in each step. Proxies can create trace records for each hop, but they cannot connect the hops on their own. To link the incoming request to the outgoing calls that it caused, the application must copy certain tracing headers from the request it received into the requests it sends.

!
Traces still need a little application help

Many teams are surprised to learn that a mesh does not give complete traces without any code change. The applications must propagate the tracing headers. Without that, each hop appears as a separate, unconnected trace.

i
Start with metrics

The most valuable and least costly benefit is the uniform metrics. Adopt those first, learn to read them, and add access logs and traces where a real question demands them.

11Istio Versus Linkerd

Both are excellent and mature. The right choice depends on how much you need, and how much complexity you can carry.

AspectIstioLinkerd
ProxyEnvoy, general-purpose and very configurablePurpose-built Rust micro-proxy
PhilosophyBroad feature set and many optionsSimplicity and a small footprint
Learning curveSteeper, many resources and settingsGentler, fewer concepts
Resource useHigher, though it varies by setupGenerally lighter, though results vary by workload
mTLS out of the boxAutomatic, with permissive mode by defaultAutomatic for meshed pods by default
Traffic featuresVery rich: gateways, fault injection, mirroring, many match rulesFocused set, leaning on the Gateway API
Non-Kubernetes workloadsBroader options for virtual machines and external servicesMore limited
Sidecar-free optionAmbient modeSidecar-based design
Community statusGraduated project of the Cloud Native Computing FoundationGraduated project of the Cloud Native Computing Foundation

How to choose

If your needs are mainly automatic encryption, good metrics, and reliable request handling, Linkerd’s smaller design often gets you there faster and with less to operate. If you need advanced traffic control, edge gateways, extensive policy options, or integration with workloads outside Kubernetes, Istio’s wider toolbox may be worth its extra complexity.

Whichever you pick, judge by your team’s real needs rather than by feature lists. A mesh with a hundred features that nobody understands is worse than a mesh with ten features that everyone can debug at night.

Simple Analogy

Choosing between them is like choosing between a professional camera with many dials and a good compact camera that mostly works out of the box. The first gives you power and control if you have time to learn it. The second gets excellent everyday photos with very little fuss.

!
Check distribution terms

Project governance and release arrangements can change over time. For example, how Linkerd’s stable releases are distributed has changed in recent years. Before committing, check the current release and licensing arrangements of whichever mesh you choose, and confirm they suit your organisation.

12Beyond Sidecars: Ambient and Other Models

The sidecar model is popular but not perfect. Newer designs try to keep the benefits while removing some of the costs.

Why people look beyond sidecars

Adding a proxy to every pod has costs. Each proxy uses memory and processor time, so a cluster with thousands of pods pays that price thousands of times. Pods must be restarted to receive proxy updates. Startup and shutdown ordering causes subtle problems. And the proxy lives inside the application’s own pod, which some security teams dislike.

Istio ambient mode

Istio’s ambient mode removes the per-pod sidecar. Instead, a small shared agent on each node, called ztunnel, handles the basic jobs: encrypting traffic with mTLS and enforcing simple identity-based rules. When an application needs richer features, such as detailed routing by path or header, an optional proxy called a waypoint is added for a namespace or a service. Apps that need only encryption and identity pay a much smaller cost.

Kernel-level approaches

Some networking projects, such as Cilium, use a Linux kernel technology called eBPF to handle much of the work inside the operating system, with shared per-node proxies for the more complex web-level features. These designs also avoid a proxy in every pod, and blur the line between the network layer of the cluster and the mesh.

ModelWhere the proxy runsStrengthTrade-off
SidecarInside every podStrong per-pod isolation and mature toolingHigher resource cost and lifecycle wrinkles
AmbientShared per node, plus optional waypointsLower cost, no pod restarts to joinNewer model, different debugging habits
Kernel-levelIn the operating system, with shared proxies for advanced featuresVery efficient for basic needsDepends on kernel features and network layer choices
Library in the appInside application codeNo extra network hopPer-language work and inconsistent adoption
Simple Analogy

The sidecar model gives every office its own receptionist. The ambient model gives each floor one shared reception desk for the basics, and adds a specialist assistant only for offices that need extra help. It costs less, but the specialist arrangements need a little more planning.

i
The concepts stay the same

Whichever model you use, the ideas in this tutorial hold: a data plane carries traffic, a control plane manages it, identities are issued to workloads, and rules describe how traffic behaves. Learning the sidecar model first is a good foundation for any of the others.

13The Adoption Lifecycle and Running the Mesh

A mesh is not installed once and forgotten. It has a lifecycle, from careful first steps to regular upgrades, and each stage has its own traps.

A safe path to adoption

The safest way to adopt a mesh is slowly. Start with a small, low-risk namespace, watch what happens, and expand only when you understand the results. Turning on everything for every team on the first day is the most common way to turn a promising tool into a painful outage.

flowchart TD
    A["Install the control plane"] --> B["Mesh one low-risk namespace"]
    B --> C["Observe metrics with permissive mTLS"]
    C --> D["Enable strict mTLS"]
    D --> E["Add authorization policies"]
    E --> F["Add traffic rules: timeouts, retries, canaries"]
    F --> G["Expand to more namespaces"]
    G --> H["Upgrade and review regularly"]
        
FIG 5 — A gradual path from first install to full use of the mesh
1

Prepare the cluster

Check the cluster’s version and capacity, decide how certificates will be managed, and choose the mesh, keeping your team’s skills in mind.

2

Install and verify

Install the control plane, run the project’s own health checks, and confirm that everything reports healthy before adding any application.

3

Mesh a pilot namespace

Label one non-critical namespace, restart its pods so they receive proxies, and confirm that they still work exactly as before.

4

Measure the cost

Record the extra memory, processor use, and latency the proxies add. Use real numbers to plan the rest of the rollout.

5

Tighten security

Move from permissive to strict mTLS once every caller is meshed, and then introduce authorization rules, starting with the most sensitive services.

6

Use traffic features deliberately

Add timeouts first, then careful retries, then canary routing for services that release often. Add each feature only when a real need exists.

7

Expand and standardise

Roll out to more namespaces using a repeatable template, and write down the conventions so teams do not invent their own.

8

Upgrade on a schedule

Plan regular upgrades of the control plane and the proxies. Falling far behind is risky, because security fixes and compatibility depend on staying current.

Simple Analogy

Adopting a mesh is like installing a new phone system in a company. You would not swap every desk phone overnight. You would first try it in one team, learn the quirks, and then move department by department, keeping the old system available until each move has proved itself.

Monitoring the mesh itself

Check 1

Control Plane Health

Watch that the control plane pods are running, restarting rarely, and answering requests quickly.

Check 2

Configuration Sync

Confirm that every proxy has received the latest configuration. A proxy that is out of date behaves by old rules.

Check 3

Certificate Expiry

Watch the expiry dates of the root and intermediate certificates. An expired root can stop all encrypted traffic at once.

Check 4

Proxy Resource Use

Track the memory and processor use of proxies, because they scale with the number of services and the traffic they see.

Check 5

Version Skew

Check which pods run older proxies than the control plane. Large differences are a warning to restart and upgrade.

Check 6

Unmeshed Pods

Look for pods in meshed namespaces that lack a proxy, since they quietly bypass encryption and policy.

!
The expiring root certificate

Teams sometimes install a mesh with a default root certificate that has a fixed lifetime and then forget it. When it expires, proxies can no longer trust each other and traffic stops. Put the expiry date on a calendar and automate rotation before it matters.

14Advantages, Disadvantages, and Trade-offs

A mesh gives a lot, and it costs a lot. An honest comparison helps you decide whether it is right for you, and when.

Advantages

  • Encrypts and authenticates service-to-service traffic without changing application code.
  • Provides uniform metrics for every service, whatever language it is written in.
  • Adds retries, timeouts, and smarter load balancing in one shared place.
  • Allows fine-grained traffic control, such as canaries and mirroring.
  • Gives central, consistent policy instead of scattered library settings.
  • Helps teams see and understand how their services really depend on each other.

Disadvantages / Trade-offs

  • Adds a whole new system to install, secure, monitor, and upgrade.
  • Uses extra memory and processor time, multiplied by the number of pods.
  • Adds a small delay to every request through the extra hops.
  • Makes debugging harder, because traffic problems may now be in the proxy layer.
  • Has a learning curve that touches networking, security, and Kubernetes at once.
  • Creates a shared dependency: a bad mesh configuration can affect many services at once.

Thinking about cost honestly

The cost of a mesh has three parts. The first is machine cost: the proxies use resources, and in a cluster with thousands of pods that becomes real money. The second is people cost: someone must learn, run, and upgrade the mesh, which takes real time. The third is complexity cost: every incident now has one more place where the cause might hide.

These costs are worth paying when the benefits are large. A company with hundreds of services and strict security requirements gains far more than it spends. A team with five services and a simple architecture may gain almost nothing. The key is to ask which specific problems you have today, and whether a mesh is the smallest tool that solves them.

When a mesh may not be the answer

Your needSimpler alternativeWhen a mesh becomes worth it
Basic encryption between a few servicesEncryption inside the application, or network-level encryptionWhen the number of services grows and consistency becomes hard
Canary releases for one serviceA progressive delivery tool or ingress weightsWhen many services need the same fine-grained control
Metrics for requestsApplication metrics librariesWhen you have many languages and uneven coverage
Blocking unwanted network pathsKubernetes network policiesWhen you need identity-aware, request-level rules
Retries and timeoutsA well-chosen client libraryWhen you cannot change every application
i
Ask what problem you are solving

The best mesh adoption stories start with a specific pain, such as a compliance requirement for encryption everywhere, or a need for consistent metrics across many teams. The worst start with the sentence “everyone else has one”.

15Design Patterns and Anti-patterns

Some habits make a mesh calm and useful. Others turn it into an expensive source of surprise.

Patterns that work well

Pattern 1

Namespace-by-Namespace Rollout

Bring services into the mesh in small groups, learning and adjusting after each step.

Pattern 2

Default Deny with Explicit Allow

Start from denying all calls and open only those paths a service truly needs.

Pattern 3

Timeouts Everywhere, Retries Sparingly

Give every call a time limit, and add retries only to safe requests and only in one layer.

Pattern 4

Canary Routing for Releases

Send a small share of traffic to a new version and increase it as the metrics stay healthy.

Pattern 5

Gateway at the Edge

Handle outside traffic with a gateway that shares the mesh’s policies, so inside and outside rules line up.

Pattern 6

Mesh as a Platform Product

Treat the mesh as a product run by a platform team, with clear defaults, templates, and documentation for app teams.

Anti-patterns to avoid

ANTI-PATTERN-01 Avoid
Problem

The mesh is switched on for every namespace at once, on the first day, with every feature enabled.

Why It’s Harmful

Problems in proxies, startup order, unusual protocols, or resource limits appear everywhere at the same time, and nobody knows which change caused which failure.

Correct Approach

Adopt step by step, starting with one low-risk namespace, and add security and traffic features in stages.

ANTI-PATTERN-02 Avoid
Problem

Retries are configured in the application, in the client library, and in the mesh, each with its own count.

Why It’s Harmful

The retries multiply. A single failure can turn into dozens of requests, overloading a service that was already struggling and turning a small problem into an outage.

Correct Approach

Decide where retries live, usually in one layer, and cap the total number of attempts across the whole call chain.

ANTI-PATTERN-03 Avoid
Problem

The mesh stays in permissive mode for ever, and the team assumes traffic is encrypted.

Why It’s Harmful

Permissive mode accepts plain traffic as well. Some calls may be unencrypted and unauthenticated without anyone noticing, giving a false sense of security.

Correct Approach

Use permissive mode only during migration, verify which traffic is still plain, and then switch to strict mode.

ANTI-PATTERN-04 Avoid
Problem

Proxies run without resource requests and limits, and nobody plans for their memory and processor use.

Why It’s Harmful

Proxies can be starved under load, which slows the application, or can consume more than expected and crowd out other pods. Cluster capacity planning becomes wrong across the board.

Correct Approach

Measure real proxy usage, set sensible requests and limits, and include the proxy cost in capacity planning.

16Best Practices and Common Mistakes

A short field guide collected from teams that run meshes in production, and from the mistakes newcomers make.

Best practices

  • Start with a clear problem — name the specific need, such as encryption or metrics, before installing anything.
  • Pilot in a small namespace — learn how the mesh behaves with real workloads before widening the rollout.
  • Measure the overhead — record proxy resource use and latency so decisions rest on numbers.
  • Use your own certificate authority — anchor trust in a system your organisation controls and rotates.
  • Move to strict mTLS — treat permissive mode as temporary and confirm that no plain traffic remains.
  • Set timeouts on every route — no call should be allowed to wait for ever.
  • Limit and coordinate retries — one layer, a small cap, and only for safe requests.
  • Handle startup and shutdown order — make sure applications wait for their proxy and finish their work before it stops.
  • Propagate tracing headers — update applications so traces link across services.
  • Keep network policies — they still protect anything that bypasses the mesh.
  • Upgrade regularly — plan control plane and proxy upgrades, and test them on non-critical namespaces first.
  • Document conventions — publish defaults and templates so teams do not each invent their own rules.

Common mistakes

!
Mistake 1: Forgetting to restart pods

Labelling a namespace does not change running pods. Until they are restarted, they run without proxies, and your policies and encryption do not apply to them.

!
Mistake 2: Proxying everything, including things that should be left alone

Some traffic, such as certain database protocols or health checks from outside the mesh, can behave badly when captured. Exclude those ports or workloads on purpose, and test them explicitly.

!
Mistake 3: Blaming the mesh, or never blaming it

When a call fails, the cause might be the application, the network, or the proxy. Teams that always blame the mesh waste time, and teams that never suspect it miss real configuration errors. Learn to read the proxy’s own logs and metrics side by side with the application’s.

i
Practise failure

Run a game day where you deliberately break the control plane, expire a certificate in a test cluster, or misconfigure a route. Learning how the mesh fails on a calm afternoon is far cheaper than learning at midnight in production.

17Real-World and Industry Examples

Service meshes appear wherever many services must talk safely, and each industry leans on a different part of the toolbox.

Where the ideas came from

The Envoy proxy, which powers Istio, originated at the ride-sharing company Lyft to solve exactly the problems this tutorial describes. Istio was started by a group of large technology companies, and Linkerd was one of the earliest projects to use the phrase service mesh. Both grew from practical needs in companies running many services.

Regulated industries and encryption everywhere

Banks and healthcare organisations often must show that internal traffic is encrypted and that only approved services can reach sensitive data. A mesh with strict mTLS and authorization policies gives them a consistent, auditable way to prove it, without asking every application team to implement security themselves.

E-commerce during busy seasons

Online retailers use retries, timeouts, and circuit breaking so that one slow service, such as recommendations, does not drag down checkout. Canary routing lets them release changes carefully before a major sales event.

Gradual migration from a monolith

Companies breaking a large application into services use traffic rules to move one feature at a time. A route sends a small share of requests for that feature to the new service, and the share grows as confidence grows, with an instant way back if problems appear.

Platforms serving many internal teams

Platform teams offer the mesh as a shared service. Application teams get encryption, metrics, and safe defaults automatically, and the platform team keeps the mesh upgraded and secure, creating a common baseline across the whole organisation.

Systems built around gRPC

Applications that use gRPC often struggle with uneven load, since one long connection can carry many requests to a single pod. A mesh balances each request separately, which can smooth out load and improve response times without changing the applications.

Multi-cluster and multi-region setups

Both meshes can connect services across several clusters, so a service in one cluster can call a service in another using the same identity and policy model. This helps with resilience, regional deployments, and migrations between clusters.

18Frequently Asked Questions

Quick answers to the questions that come up most often when teams first meet a service mesh.

Q1Do I need to change my application code to use a mesh?

Not for the basic features such as encryption, metrics, and load balancing. The proxies handle them. For full distributed tracing, applications do need to pass along tracing headers.

Q2Is a service mesh the same as an API gateway?

No. A gateway mainly handles traffic entering the system from outside, while a mesh mainly handles traffic between services inside. Meshes often include their own gateways so that both work together.

Q3Does a mesh replace Kubernetes Services or Ingress?

No. It builds on them. Services and pods provide the basic map of the cluster, and the mesh adds smarter behaviour on top.

Q4How much overhead does a mesh add?

Each proxy uses some memory and processor time, and each request passes through two extra hops that add a small delay. The exact numbers depend on the mesh, the traffic, and the features used, so measure in your own environment.

Q5What happens if the control plane goes down?

Existing traffic keeps flowing, because proxies keep their last configuration. New pods cannot get identities or settings, and certificates cannot be renewed, so a long outage becomes a real problem.

Q6Is mTLS turned on automatically?

Both meshes enable mTLS between meshed pods automatically. Istio often starts in a permissive mode that also accepts plain traffic, so you should move to strict mode when your services are ready.

Q7Can I use both Istio and Linkerd together?

Running two meshes over the same pods is generally a bad idea, because both try to capture the same traffic. Choose one for each set of workloads.

Q8Do I need a mesh if I only have a handful of services?

Usually not. With a few services, simpler tools such as network policies, a good client library, and application metrics are often enough. A mesh pays off as the number of services and teams grows.

Q9Why do my batch jobs never finish after adding the mesh?

The proxy container keeps running after the job’s own container exits, so the pod never completes. Meshes and newer Kubernetes sidecar support offer ways to stop the proxy when the main work is done.

Q10Can a mesh handle traffic that is not HTTP?

Yes, to a degree. Proxies can encrypt and balance plain TCP traffic, and can report basic metrics. Rich features such as path routing and per-request retries apply mainly to protocols the proxy understands, such as HTTP and gRPC.

Q11How do I remove a mesh if I change my mind?

Remove injection labels from namespaces, restart pods so they lose their proxies, and then uninstall the control plane. Doing it namespace by namespace, in the reverse order of adoption, keeps the risk low.

Q12Is the sidecar model going away?

Not soon. Sidecars remain widely used and well supported. Alternatives such as ambient mode are growing, and many teams will use a mix depending on their needs.

19Summary and Key Takeaways

A service mesh moves the repeated work of service-to-service communication out of your applications and into a shared layer of proxies, managed by a central control plane. In return for a modest cost in resources and complexity, you gain encryption, identity, smarter load balancing, fine traffic control, and detailed metrics, all without rewriting your code. Istio offers a very wide toolbox, and Linkerd offers a smaller, simpler design, and newer models such as ambient mode try to reduce the cost of the sidecar approach.

The mesh is a powerful tool, not a magic one. It needs careful adoption, regular upgrades, and honest measurement. It works best when it solves a problem you actually have, and when it is run as a well-documented platform rather than a surprise. Teams that follow those habits find that the mesh quietly makes their systems safer and easier to understand.

Key Takeaways

  • A mesh is proxies plus a manager — a data plane of proxies carries the traffic, and a control plane configures them and issues identities.
  • Injection is automatic, restarts are not — proxies are added to new pods by a webhook, and existing pods must be restarted to receive them.
  • Security is the strongest reason to adopt — automatic mTLS and authorization policies protect internal traffic, but only if you move beyond permissive mode.
  • Traffic rules replace code — timeouts, careful retries, canary splits, and mirroring are all configuration, with retry storms as the main danger.
  • Metrics come almost free — golden signals for every service pair are available immediately, while full traces still need applications to pass headers along.
  • Choose by need, not by hype — Istio suits broad, advanced needs, Linkerd suits simplicity and low overhead, and small systems may not need a mesh at all.
  • Adopt gradually and run it well — pilot in one namespace, measure overhead, watch certificates and versions, and treat the mesh as a platform product.