Service Mesh Data Plane Internals (Envoy and Sidecar Injection) in Kubernetes

Service Mesh Data Plane Internals (Envoy and Sidecar Injection) in Kubernetes

How a tiny proxy gets slipped into every Pod, how it quietly captures all network traffic, and how it adds security, retries, and visibility without changing a single line of your application. A complete, step-by-step guide from the first idea to production tuning.

Imagine a large office building where every employee used to walk to other departments and hand over papers directly. Some employees were careful and kept copies. Some forgot to check who they were talking to. Some retried forever when a door was locked. Then the company hired a personal assistant for every employee. The assistant sits next to the desk, carries every message, checks the identity of the receiver, retries politely when a door is locked, and writes down who sent what to whom. The employee never notices that anything changed, except that things work better.

That assistant is the sidecar proxy of a service mesh. In Kubernetes, the most popular such proxy is Envoy. Each Pod gets its own Envoy, placed next to the application container, and all network traffic into and out of the application passes through it. Because the proxy sees every request, it can encrypt traffic, balance load, retry failures, limit damage, and record detailed numbers, all without the application knowing.

In this guide you will learn how that proxy gets into your Pod through a process called sidecar injection, how network rules quietly redirect traffic to it, how Envoy is organized inside, how it learns its configuration from a control plane, how it proves identity with certificates, what can go wrong at startup and shutdown, and how to run it without wasting resources. Every new word is explained the first time it appears, so you can read from top to bottom with no earlier knowledge.

1The Big Idea: What Is a Service Mesh Data Plane?

A mesh moves the hard parts of networking out of your code and into a layer that every service shares.

A service mesh is a layer of software that manages how services talk to each other. It has two halves. The control plane is the brain: it decides the rules, such as who may talk to whom and how many retries are allowed. The data plane is the muscle: it is the set of proxies that actually carry every request and enforce those rules. This guide is about the muscle.

A proxy is a program that stands in the middle of a conversation. A client talks to the proxy, and the proxy talks to the server on its behalf. Because the proxy is in the middle, it can inspect, change, retry, or refuse requests. In a mesh, there is one proxy per application instance, which is why the pattern is called a sidecar, like the small passenger car attached to the side of a motorcycle.

Everyday analogy

Think of a motorcycle with a sidecar. The rider steers and focuses on the road. The passenger in the sidecar reads the map, handles the radio, and watches the mirrors. Both travel together as one unit, but each has a clear job. The application is the rider, and the Envoy sidecar is the passenger who handles everything related to communication.

1 per Pod
sidecar proxy beside every application
0 changes
to application code needed
100%
of Pod traffic passes through the proxy

Why this design is so popular

Before service meshes, every team had to build networking features into their own code: retry logic, timeouts, encryption, and metrics. Different teams used different languages and libraries, so the behavior was inconsistent. A mesh moves these features into one proxy that behaves the same way for every service, whatever language it is written in. A security team can change a rule once and it takes effect across hundreds of services.

i
Remember this

The control plane decides. The data plane does. Envoy is the doer. When you are confused, ask yourself which half you are looking at.

2Why We Need It: Problems the Data Plane Solves

When one application becomes fifty small services, the network between them becomes the hardest part.

In a monolith, one part of the program calls another with a simple function call. It either works instantly or crashes in a clear way. When the program is split into many microservices, each function call becomes a network call. Networks are unreliable. Messages are delayed, lost, or duplicated. A service can be slow, dead, or half-alive. Suddenly every service needs to answer hard questions: how long should I wait, should I retry, who is this caller, can I trust them, and how do I know what happened?

Reliability

Retries and timeouts

Try again on failure, but only a limited number of times, and give up after a set time so slow services do not freeze their callers.

Reliability

Load balancing

Spread requests across healthy copies of a service, and avoid copies that are struggling.

Reliability

Circuit breaking

Stop sending traffic to a failing service for a while, so it can recover and so callers fail fast.

Security

Mutual TLS

Encrypt traffic and make both sides prove who they are with certificates.

Security

Access policy

Allow only approved services to call each other, based on identity.

Visibility

Metrics, logs, and traces

Record request counts, errors, delays, and the path each request took.

Control

Traffic shifting

Send five percent of traffic to a new version first, and raise it slowly if all looks well.

Control

Fault injection

Deliberately add delays or errors in a test to see whether callers cope.

Library approach versus proxy approach

QuestionLibraries inside each serviceSidecar proxy in each Pod
Language supportOne library per language, always laggingWorks for any language, since it works on the network
How to change a ruleUpdate code, rebuild, redeploy every serviceChange configuration centrally, proxies update live
ConsistencyVaries by team and versionThe same proxy behavior everywhere
CostSmall per-call overheadExtra container and extra network hop per Pod
Risk of mistakesEach team can get retries wrongMistakes are centralized, and easier to fix
Everyday analogy

Instead of training every employee to be an expert in postal rules, the company hires a mailroom that follows one handbook. Employees just drop letters in the tray. The price is the mailroom’s salary and a small delay, and the benefit is that every letter follows the same rules.

i
Production example

Envoy was created at Lyft to solve exactly this problem for a growing set of microservices written in different languages. It was then donated to the Cloud Native Computing Foundation and became the proxy underneath many meshes and gateways. Istio, which was started by Google, IBM, and Lyft, uses Envoy as its data plane.

3Core Vocabulary for the Mesh Data Plane

Twelve short words that you will meet in every service mesh discussion.

Software

Envoy

A high-performance proxy written in C++. It is the engine inside Istio, and also inside many gateways.

Pattern

Sidecar

A helper container placed in the same Pod as the application, sharing its network and lifecycle.

Process

Injection

Automatically adding the sidecar container to a Pod as it is created.

Hook

Admission webhook

A web service Kubernetes calls during Pod creation, which may change or reject the Pod.

Setup

Init container

A short container that runs to completion before the main containers start. Used to prepare traffic rules.

Kernel

iptables

The Linux packet-filtering tool used to redirect traffic from the application to the proxy.

Protocol

xDS

The family of discovery protocols the control plane uses to send configuration to Envoy.

Config

Listener

An Envoy setting that says “accept connections on this address and port.”

Config

Cluster

An Envoy name for a group of upstream endpoints that provide one service.

Config

Endpoint

One real address (IP and port) of a Pod that serves a cluster.

Security

mTLS

Mutual TLS: both client and server present certificates and verify each other.

Identity

SPIFFE ID

A standard name for a workload, such as one made from its trust domain, namespace, and service account.

North-south versus east-west

Two phrases describe the direction of traffic. North-south traffic enters or leaves the cluster, such as a user on the internet calling your website. East-west traffic moves between services inside the cluster, such as the checkout service calling the payment service. Gateways manage the first kind. Sidecars mostly manage the second.

Everyday analogy

Picture a city map. Trucks entering the city from the highway are north-south traffic, and they pass through a toll gate. Delivery vans moving between warehouses inside the city are east-west traffic. A mesh puts a traffic officer at every warehouse door, not only at the city gate.

4Architecture: Control Plane and Data Plane Together

One brain, many proxies, and a steady flow of instructions between them.

flowchart TB
  K8S["Kubernetes API server"] -->|"watch Services, Pods, policies"| ISTIOD
  subgraph CP["Control plane"]
    ISTIOD["istiod - config, certificates, xDS server"]
  end
  subgraph PA["Pod A"]
    AA["App container A"]  EA["Envoy sidecar A"]
  end
  subgraph PB["Pod B"]
    AB["App container B"]  EB["Envoy sidecar B"]
  end
  ISTIOD -->|"xDS config and certificates"| EA
  ISTIOD -->|"xDS config and certificates"| EB
  EA |"mTLS traffic"| EB
    
Figure 1. The control plane sends rules to every sidecar, and the sidecars carry the traffic.

Look at Figure 1. The control plane, named istiod in Istio, watches the Kubernetes API server. It learns which Services and Pods exist, and which rules the operators have written. It then turns all this into proxy configuration and pushes it to every sidecar. When Pod A calls Pod B, the request leaves A’s application, passes through A’s Envoy, crosses the network encrypted, enters B’s Envoy, and only then reaches B’s application. The control plane is not in the path of any request, which is important: if istiod stops for a short time, existing traffic keeps flowing with the last configuration the proxies received.

1

Operators write intent

People create Kubernetes objects, such as traffic rules and security policies, that describe what they want.

2

istiod translates

It combines these rules with the list of live Pods and produces detailed Envoy configuration for each proxy.

3

Proxies receive and apply

Each Envoy gets its own view through a long-lived connection and applies changes live, without restarting.

4

Traffic flows through proxies

Every request is handled by two proxies: one on the sending side and one on the receiving side.

Everyday analogy

An airline head office decides the flight rules and sends the same rulebook updates to every airport. The head office does not fly the planes. If the head office phone line goes down for an hour, the airports keep operating under the last rulebook they received. Control plane and data plane have the same relationship.

i
Production example

Istio is a graduated project of the Cloud Native Computing Foundation, as are Envoy and Linkerd. Linkerd uses a different, very small proxy written in Rust, instead of Envoy, but follows the same split between a control plane and sidecar data plane proxies.

5Sidecar Injection: How the Proxy Gets Into Your Pod

You write a Pod with one container. By the time Kubernetes stores it, it has more. Here is how.

Nobody wants to edit hundreds of deployment files to add a proxy to each one. Instead, Kubernetes has a feature called an admission webhook. When you create any object, the API server passes it through a series of checks before saving it. A mutating admission webhook is allowed to change the object during this journey. The mesh registers one such webhook for Pods. Whenever a new Pod is created in a chosen namespace, the API server sends the Pod to the webhook, and the webhook replies with a patch that adds the proxy.

sequenceDiagram
  participant U as User or Deployment controller
  participant API as API Server
  participant WH as Injection webhook in istiod
  participant S as Scheduler
  participant K as Kubelet
  U->>API: Create Pod with one app container
  API->>WH: Admission review request
  WH-->>API: Patch adds init container and sidecar
  API->>API: Validate and store the patched Pod
  API-->>S: Watch event for unscheduled Pod
  S->>API: Bind Pod to node
  API-->>K: Watch event for Pod on this node
  K->>K: Run init container to set traffic rules
  K->>K: Start Envoy sidecar and app container
    
Figure 2. The webhook rewrites the Pod before it is ever stored or scheduled.
1

A Pod is requested

Usually a Deployment’s ReplicaSet creates it. The Pod has only the application container.

2

The API server calls the webhook

After authentication and authorization, the API server finds the registered mutating webhook that matches Pods in this namespace, and sends it the Pod description.

3

The webhook builds a patch

It uses a template stored in the mesh configuration, fills in values such as the application’s ports and the mesh settings, and returns a list of changes to apply.

4

The API server stores the patched Pod

The stored Pod now contains the extra containers and volumes. From this point, the scheduler and the kubelet see only the complete Pod, and treat it like any other.

5

The kubelet starts it

The init container runs first and sets up traffic redirection. Then the sidecar and the application containers start.

Deciding which Pods get a sidecar

Injection is controlled by labels and annotations, which are small tags on Kubernetes objects. The common pattern is to label a whole namespace so that every new Pod inside it is injected. Individual Pods can opt out, or opt in, with a Pod-level annotation. For safe upgrades, Istio uses revision labels: you install a new version of the control plane next to the old one, and move namespaces over one at a time by changing the label.

MechanismScopeUse it for
Namespace label to enable injectionEvery new Pod in the namespaceStandard onboarding of a team’s services
Revision label on the namespaceChooses which control plane version injectsCanary upgrades of the mesh
Pod annotation to disable injectionOne Pod templateJobs, tools, or special workloads that must not have a proxy
Manual injection by command line toolOne file at a timeDebugging, or clusters that cannot use webhooks
Everyday analogy

Think of a security desk at a building entrance. Every visitor must go through it, and the guard clips a badge on each person. Visitors do not need to ask for a badge, and the guard does not change who they are. The admission webhook is that guard, and the sidecar is the badge, clipped on automatically.

!
Common trap

Injection happens only when a Pod is created. If you label a namespace after its Pods are already running, nothing changes for them. You must restart (roll out) the workloads for the new Pods to be injected. Likewise, upgrading the mesh does not upgrade the sidecars in running Pods until they are restarted.

i
Production example

Linkerd uses the same idea: an annotation on a namespace or Pod asks its webhook to add the Linkerd proxy. Companies that adopt a mesh usually start with one or two namespaces, watch for problems, and widen injection step by step.

6What Injection Adds to the Pod

A look at the extra parts, one by one.

Init

Init container

Runs once, with special network permissions, to install the traffic redirection rules inside the Pod’s network space. Then it exits.

Sidecar

Proxy container

Runs the pilot-agent program, which starts and supervises Envoy for the lifetime of the Pod.

Volumes

Shared volumes

Small shared folders for certificates, bootstrap configuration, and a local socket the proxy uses to talk to its helper.

Env

Environment variables

Values that tell the proxy its Pod name, namespace, service account, and the address of the control plane.

Token

Projected service account token

A short-lived token that proves the Pod’s identity to the control plane when it asks for a certificate.

Ports

Extra ports

Ports for health checks and metrics, used by the platform rather than by your application.

Two programs in one container

The proxy container does not simply run Envoy. It runs a small helper called pilot-agent, which in turn starts Envoy. The agent has several jobs. It creates the first, minimal configuration that Envoy needs to start. It asks the control plane for a certificate for the Pod and passes it to Envoy. It forwards configuration updates. It answers health checks. It restarts Envoy if it crashes. This division of labor keeps Envoy focused on moving traffic and leaves housekeeping to the agent.

Everyday analogy

A food stall has a cook and a helper. The cook cooks. The helper fetches ingredients, keeps the license papers up to date, and calls the cook back if the cook is away. Envoy is the cook, and pilot-agent is the helper.

Resource cost per Pod

Every sidecar uses memory and CPU. The default resource requests in Istio are around one tenth of a CPU core and 128 mebibytes of memory per proxy, though real use depends on traffic and on how large the mesh is. Multiply this by hundreds or thousands of Pods and the cost is real. Later chapters show how to reduce it. Treat the sidecar as a small tax on every Pod, in exchange for the features it brings.

i
Good to know

Because the Pod’s resource requests now include the sidecar, the scheduler counts the proxy when it finds room for the Pod. A cluster that was comfortably full before injection can suddenly run out of space after a mesh is turned on everywhere.

7Traffic Interception: How Requests Are Silently Redirected

The application believes it is talking directly to another service. The kernel quietly sends the bytes through the proxy instead.

The Pod shares one network space, called a network namespace, among all its containers. This means the application and the sidecar see the same network interfaces and the same local addresses. The init container uses this fact. It installs rules with a Linux tool called iptables, which sits inside the kernel and can rewrite where a packet is going. The rules say: any outgoing connection from this Pod, except those made by the proxy itself, should be redirected to the proxy’s outbound port. Any incoming connection to this Pod should be redirected to the proxy’s inbound port.

flowchart LR
  subgraph PA["Client Pod network namespace"]
    APP1["App sends request to a service"] --> IPT1["iptables redirect"]
    IPT1 --> OUT["Envoy outbound listener 15001"]
  end
  subgraph PB["Server Pod network namespace"]
    IPT2["iptables redirect"] --> IN["Envoy inbound listener 15006"]
    IN --> APP2["App receives request on its own port"]
  end
  OUT -->|"mTLS over the network"| IPT2
    
Figure 3. Traffic is captured on the way out of the client Pod and on the way into the server Pod.
1

The app makes an ordinary connection

It connects to a service name, and the connection is sent toward the service address. The app has no idea about the proxy.

2

iptables redirects the connection

A rule in the outgoing path of the network namespace rewrites the destination so that the connection goes to the proxy’s outbound listener on port 15001, on the same machine.

3

Envoy recovers the original destination

The kernel remembers where the connection was originally headed. Envoy asks for this information, so it still knows the intended service and port.

4

Envoy applies the rules

It picks the right route, chooses a healthy endpoint, wraps the request in mTLS, and sends it. Its own outgoing connection is marked so it is not redirected again.

5

The receiving side captures it too

On arrival, another iptables rule sends the incoming connection to the inbound listener on port 15006. That Envoy checks the certificate and the policy, decrypts the traffic, and hands it to the local application over a plain local connection.

Well-known ports of the sidecar

PortPurpose
15001Outbound capture: all traffic leaving the application
15006Inbound capture: all traffic arriving for the application
15000Envoy admin interface, reachable only inside the Pod
15021Health check endpoint for readiness of the sidecar
15020Merged metrics and agent endpoints
15090Envoy’s own Prometheus metrics
15053Local DNS proxy of the agent, when enabled
Everyday analogy

Imagine all the mail in a building is dropped in the mailroom by default. Residents write the address they want, but a door sign on every flat says “all outgoing letters are collected by the mailroom.” The mailroom reads the original address, stamps the letter, and sends it on. A letter the mailroom itself sends carries a special mark so it does not get collected again, which would cause an endless loop.

Avoiding the loop

If the proxy’s own outbound connections were captured, they would be redirected back to the proxy, forever. To prevent this, the rules look at the user ID of the process making the connection. The proxy runs as a special user (ID 1337 in Istio), and connections from that user are left alone. This also explains an odd rule of thumb: never run your own application as that user ID, or its traffic will bypass the mesh.

!
Common trap

The init container needs special Linux permissions to change network rules. Strict security policies, such as the restricted Pod Security Standard, reject it. The usual answer is a different design where a node-level plugin installs the rules instead (a CNI plugin), which you will meet in Chapter 14.

i
Production example

Istio lets owners exclude certain ports or IP ranges from interception through annotations. Platform teams often exclude traffic to a metadata service or a very high-volume database, where the proxy adds cost but little value. The trade-off is that excluded traffic loses mesh features such as mTLS and metrics.

8Inside Envoy: Threads, Listeners, Filter Chains, and Clusters

Envoy is built like an assembly line. A connection enters at one end and passes through stations until it reaches the destination.

flowchart LR
  L["Listener accepts connection"] --> LF["Listener filters - detect protocol"]
  LF --> FC["Filter chain match"]
  FC --> TLS["TLS termination"]
  TLS --> HCM["HTTP connection manager"]
  HCM --> HF["HTTP filters - auth, stats, fault, router"]
  HF --> RT["Route table - match host and path"]
  RT --> CL["Cluster - upstream service"]
  CL --> LB["Load balancer picks endpoint"]
  LB --> UP["Upstream connection pool"]
    
Figure 4. The path of one request through the stations inside Envoy.

Threading model

Envoy uses a small number of threads and never blocks. One main thread handles configuration updates and housekeeping. Several worker threads handle traffic. When a new connection arrives, it is given to one worker thread, and that worker handles the connection for its whole life. Each worker runs an event loop: it waits for things to happen on many connections and reacts quickly. Because a connection never moves between threads, workers rarely need locks, which is a main reason Envoy is fast. Istio limits the number of workers per sidecar to a small number by default, to avoid wasting CPU in small Pods.

Everyday analogy

Think of a few very efficient waiters in a restaurant. Each waiter looks after a fixed set of tables from start to finish and never waits idly at one table. Because tables are never shared, the waiters do not bump into each other. The manager in the back office handles supplies and rule changes.

The main building blocks

Entry

Listener

Accepts connections on an address and port. A sidecar has an outbound capture listener, an inbound capture listener, and several others for specific ports.

Choose

Filter chain

A list of stations chosen based on details of the connection, such as the destination port, the protocol, or whether TLS is used.

Process

Network and HTTP filters

Small plug-in stages that inspect, change, or decide about traffic. The router is the last HTTP filter and forwards the request.

Decide

Route

Matches a request on host, path, headers, and picks which cluster to send it to. This is where traffic shifting and retries are set.

Group

Cluster

A named group of endpoints for one upstream service, with settings for load balancing, connection limits, and health.

Target

Endpoint

One real Pod address in a cluster. Envoy keeps connection pools to each, to reuse connections.

Protocol awareness

Envoy understands many protocols, including HTTP/1.1, HTTP/2, gRPC, and plain TCP. For HTTP and gRPC, it reads each request, so it can route by path and report per-request metrics. For other protocols, it treats the connection as a stream of bytes and offers connection-level features only. This matters in practice: if a port is mistakenly treated as plain TCP, you lose request-level routing and metrics for that service. Naming Kubernetes service ports by protocol is therefore a small but valuable habit.

i
Production example

The same Envoy design powers edge gateways and ingress controllers as well as sidecars. Projects such as Contour, Emissary, and several implementations of the Kubernetes Gateway API use Envoy at the edge, so teams often learn the model once and apply it in both places.

9xDS: How Envoy Learns Its Configuration

Envoy does not read a big file. It subscribes to a live feed of changes.

Services in Kubernetes come and go constantly. Pods start, die, move, and scale. A static configuration file would be out of date in seconds. So Envoy uses xDS, a set of discovery APIs where the “x” stands for a family. The control plane streams updates, and Envoy applies each update live with no restart and no dropped connections.

sequenceDiagram
  participant E as Envoy proxy
  participant P as pilot-agent
  participant I as istiod
  E->>P: Open xDS stream on local socket
  P->>I: Forward stream to istiod over mTLS
  I-->>E: Clusters CDS
  I-->>E: Endpoints EDS
  I-->>E: Listeners LDS
  I-->>E: Routes RDS
  E-->>I: ACK each accepted update
  Note over I: A Service or policy changes
  I-->>E: Push only the changed resources
  E-->>I: ACK or NACK with reason
    
Figure 5. Envoy opens one stream and keeps receiving updates, acknowledging each one.
APIFull nameWhat it delivers
LDSListener Discovery ServiceWhich ports to listen on and which filters to apply
RDSRoute Discovery ServiceRouting tables: which request goes to which cluster
CDSCluster Discovery ServiceThe list of upstream services and their policies
EDSEndpoint Discovery ServiceThe real Pod addresses behind each cluster
SDSSecret Discovery ServiceCertificates and keys, rotated without restart
ADSAggregated Discovery ServiceOne ordered stream carrying all the above, to avoid conflicts
Everyday analogy

A GPS navigation app does not store the whole world’s traffic. It subscribes to a live feed and updates the route as roads close or open. The feed lists roads (clusters), cars on them (endpoints), and rules for turns (routes). Envoy’s xDS is that live feed.

Acknowledge or reject

Each time Envoy receives a configuration, it checks it. If it is valid, Envoy applies it and replies with an acknowledgement (ACK). If it is invalid, Envoy keeps its old working configuration and replies with a rejection (NACK) that carries an error message. This is a safety feature: a bad configuration never replaces a working one. A common debugging step is therefore to ask the control plane whether any proxy is in a stale or rejected state.

Order matters

If routes pointed to a cluster that did not exist yet, requests would fail during the gap. The aggregated stream makes sure that clusters arrive before the routes that use them, and that old resources are removed only after nothing refers to them. This careful ordering is why configuration changes are smooth, even in a busy mesh.

Why config size is a problem

By default, the control plane tells every sidecar about every service in the mesh. In a mesh with thousands of services, each Envoy holds a very large configuration and uses much memory. It also receives a flood of updates for services it will never call. The answer is to limit each proxy’s view to only what it needs, using a scoping resource called Sidecar in Istio. We return to this in the performance chapter.

!
Common trap

Do not confuse the Istio resource named Sidecar with the sidecar container. The resource is a configuration object that narrows what a proxy knows. The container is the proxy itself. The name is unlucky, but the two are different things.

10Resilience Features: Load Balancing, Retries, Timeouts, and Circuit Breaking

This is where the proxy earns its keep, by turning an unreliable network into a more dependable one.

Client-side load balancing

The usual Kubernetes Service balances at the connection level inside the kernel, which can leave long-lived connections stuck on one Pod. Envoy balances at the request level, on the client side. It knows every endpoint and can send each request to a different one. Common policies are round robin, random, and least request, which sends the next request to the endpoint with the fewest requests in flight. Recent Istio versions use least request by default. Envoy can also prefer endpoints in the same zone, to save cost and delay, falling back to others when needed.

Everyday analogy

At a supermarket, a smart usher looks at all the checkout lines and sends each shopper to the shortest one. The old way assigned a shopper to a line at the door and never changed it. The usher is the Envoy balancer.

Retries and timeouts

A retry sends the request again if the first try fails in a way that is probably temporary, such as a refused connection. A timeout sets how long the proxy waits for an answer before giving up. Istio’s defaults include a small number of retries for connection-level failures. Retries are powerful but dangerous: if every layer of a call chain retries three times, one failure can multiply into dozens of calls and overload the struggling service. This is called a retry storm. Good practice is to retry in one place, set retry budgets, and always set timeouts shorter at the edges than in the depths.

Limit

Connection pool limits

Caps on the number of connections and pending requests to an upstream. When the cap is hit, extra requests fail fast instead of piling up.

Detect

Outlier detection

Watches each endpoint. If one returns repeated errors, Envoy ejects it from rotation for a period, then lets it back in to test it.

Probe

Active health checks

Optional probes that ask endpoints “are you well?” Many meshes rely on Kubernetes readiness and outlier detection instead.

Protect

Rate limiting

Caps how many requests a caller may send, either locally in the proxy or through a shared service.

Circuit breaking in plain words

An electrical circuit breaker cuts power when current is too high, protecting the house. A software circuit breaker cuts traffic to a service that is failing or overloaded, protecting both the callers and the service. In Envoy, this takes the form of connection and request limits plus outlier detection. When an endpoint keeps failing, it is ejected for some time, with the base time often thirty seconds, and ejection time grows with repeated failures. The result is that clients fail fast and the sick Pod gets room to recover.

FeatureProtects againstMain risk if misconfigured
RetriesShort glitchesRetry storms that overload services
TimeoutsSlow services freezing callersToo short: healthy slow calls fail; too long: resources pile up
Connection limitsOverload from too many connectionsLimits set too low block normal traffic
Outlier detectionOne bad Pod harming many requestsEjecting too many Pods leaves too few to serve
Locality preferenceCross-zone cost and delayUneven load if one zone has fewer Pods

Production example: canary releases

Large internet companies use the same weighted routing in the proxy to roll out new versions slowly: five percent of requests to the new version, then twenty, then everything, while watching error rates. If the new version misbehaves, one configuration change sends traffic back, and no application redeploy is needed. Airbnb, Salesforce, and many others have shared public talks about running Istio for this kind of safe, gradual change.

11Identity and Mutual TLS: How Sidecars Prove Who They Are

Inside a cluster, an IP address means almost nothing, because Pods come and go. Identity must come from something stronger.

Normal TLS, the lock icon in your browser, proves only the server’s identity to the client. In mutual TLS (mTLS), the client also proves its identity with a certificate. Both sides check the other’s certificate before any data is exchanged, and the connection is encrypted. In a mesh, the sidecars do all of this on behalf of the applications, so the application can speak plain traffic to its local proxy.

sequenceDiagram
  participant PA as pilot-agent
  participant I as istiod CA
  participant E as Envoy
  PA->>PA: Create private key and request
  PA->>I: Send CSR with Pod service account token
  I->>I: Validate token and identity
  I-->>PA: Signed certificate chain
  PA-->>E: Deliver certificate through SDS
  Note over PA,E: Renewed before expiry with no restart
    
Figure 6. How a Pod gets a short-lived certificate without any human step.
1

The agent creates a private key

The key is created inside the Pod and never leaves it. Only a certificate signing request, which does not contain the key, is sent out.

2

The agent proves who the Pod is

It sends the request along with the Pod’s service account token. Kubernetes issued this token and can vouch for the Pod’s namespace and service account.

3

The control plane signs a certificate

After validating the token, istiod’s built-in certificate authority signs a certificate containing a workload identity, such as the trust domain, namespace, and service account name.

4

The certificate reaches Envoy

The agent hands it to Envoy over a local socket using the secret discovery service. No files are written to disk for the key.

5

Rotation happens automatically

Certificates are short-lived, with a default life of about twenty-four hours in Istio, and are renewed well before expiry. A stolen certificate is useful to an attacker only briefly.

Everyday analogy

Imagine an office where each visitor wears a day badge printed by the front desk after checking a passport. Staff on every floor check the badge, and the badge expires at midnight. A lost badge is useless tomorrow. The passport is the service account token, the badge is the certificate, and the front desk is the certificate authority.

Identity based policy

Because each sidecar presents a certificate with a clear workload identity, rules can be written in terms of identity instead of IP addresses. For example, “only the checkout workload may call the payment workload.” The receiving Envoy checks the caller’s certificate and applies the policy before the request ever reaches the application. This is far stronger than IP-based firewalls, which break whenever Pods are rescheduled.

Permissive versus strict

When a mesh is first introduced, not every Pod has a sidecar. To avoid breaking traffic from Pods without proxies, Istio’s default mode accepts both encrypted and plain traffic. This is called permissive mode. Once every workload is in the mesh, you should switch to strict mode, where only mTLS traffic is accepted. Staying permissive forever leaves a door open for unencrypted traffic.

!
Common trap

Turning on strict mode before all callers are in the mesh causes sudden connection failures from older workloads, health probes, or other tools. Move in steps: measure who still sends plain traffic, bring them into the mesh, and only then enforce.

Production example: zero trust inside the cluster

Many regulated organizations adopt a mesh mainly for this: encrypted traffic between all services and identity-based policy, without asking every application team to manage certificates. The SPIFFE identity standard, which Istio follows, is also supported by other systems, which makes it easier to build a common identity story across tools.

12Observability: Metrics, Logs, and Traces for Free

Because every request passes through a proxy, the proxy is the perfect place to measure it.

Without a mesh, each team must add measurement code to every service. With a mesh, the sidecar records the same standard facts for every request, whatever the language. The data falls into three groups, often called the three pillars of observability.

Pillar 1

Metrics

Numbers over time: request count, error count, and request duration, split by source, destination, and response code. The proxy exposes them for Prometheus to collect.

Pillar 2

Access logs

One line per request with times, sizes, codes, and a short response flag that explains how the request ended.

Pillar 3

Distributed traces

A picture of the full path of a request across many services. The proxy creates spans, but the application must pass trace headers along for spans to link together.

The golden signals from the proxy

Operators look at four numbers for every service: how many requests arrive (traffic), how many fail (errors), how long they take (latency), and how busy the service is (saturation). The mesh provides the first three automatically, per service pair, without code changes. This is why a mesh dashboard can show a map of which services call which, with error rates on each line, within minutes of installation.

Everyday analogy

A toll road records every vehicle that passes: time, type, and direction. From the tolls alone, you can tell how busy each road is and where jams begin. The sidecars are toll booths at every road entrance, and the access logs are the ticket stubs.

Reading Envoy response flags

The short flags in access logs are the fastest way to understand a failure. Learn a few by heart.

FlagMeaningTypical cause
NRNo route configuredMissing routing rule, or a wrong host name
UHNo healthy upstreamAll endpoints are unready or ejected
UFUpstream connection failureServer not listening, or TLS mismatch
UCUpstream closed the connectionServer crashed or closed idle connections
URXRetry limit exceededThe upstream kept failing across all retries
DCDownstream connection closedThe caller gave up or disconnected
UTUpstream request timeoutThe server was too slow for the configured timeout
i
Tip about cost

Metrics split by many labels can multiply into millions of time series, which makes monitoring systems slow and expensive. Keep only the labels you truly use, and avoid adding high-variety labels such as user IDs. Likewise, do not log every request at full detail on busy services without a plan for storage.

Production example: finding a hidden dependency

Teams new to a mesh often report that the service map reveals calls nobody knew about, such as an old reporting job still calling a retired API. Seeing the real traffic graph, rather than the diagram in an old document, is often the first big win of installing a mesh.

13Lifecycle: Startup, Shutdown, and Jobs That Never End

Two containers in one Pod must start and stop in a sensible order. Kubernetes did not guarantee that for a long time.

stateDiagram-v2
  [*] --> InitRules
  InitRules --> ProxyStarting: Traffic rules installed
  ProxyStarting --> ProxyReady: Config received from istiod
  ProxyReady --> AppRunning: App container starts
  AppRunning --> Draining: Pod deletion begins
  Draining --> [*]: Proxy exits after app finishes
    
Figure 7. The ideal order of events in a Pod with a sidecar.

Startup race

All normal containers in a Pod start at about the same time. If the application starts faster than Envoy, its first outgoing calls are redirected to a proxy that is not ready yet, and they fail. Applications that call other services right at startup, for example to load configuration, often crash and restart a few times until the proxy catches up. A setting often named hold application until proxy starts makes the platform start the proxy first and wait until it is ready before starting the app.

Shutdown race

When a Pod is deleted, Kubernetes tells all containers to stop at once. If the sidecar exits first, the application can no longer make outgoing calls while finishing its last requests, and in-flight requests may be cut. The proxy therefore has a drain period, during which it stops accepting new connections but keeps serving existing ones. In Istio it defaults to a few seconds, and for slow applications it should be raised, so the proxy outlives the application’s final work.

Jobs and CronJobs

A batch Job’s Pod is finished when its main container exits. But a sidecar container keeps running forever, so the Pod never completes, and the Job never finishes. Teams used to solve this by calling a special endpoint to tell the proxy to quit once the work was done, or by adding wrapper scripts. It was an awkward chore that every team had to learn.

Everyday analogy

A taxi driver and a co-driver share one car. The co-driver must have the map ready before the car leaves, and must not jump out before the passenger has reached the door. If the co-driver refuses to leave after the trip is over, the car never gets parked. Startup order, shutdown order, and the “finished” signal are the three coordination problems.

Native sidecar containers

Kubernetes now has a built-in answer. A special kind of init container, marked to restart always, runs as a true sidecar: it starts before the main containers, stays running during the Pod’s life, is stopped after the main containers have finished, and does not block a Job from completing. This feature moved through preview stages and became generally available in Kubernetes 1.33. Recent versions of service meshes can use it for injection, which removes most of the awkward workarounds.

ProblemOld workaroundModern answer
App calls out before proxy is readyHold app until proxy startsNative sidecar starts first and must be ready
Proxy exits before app finishesLonger drain period, pre-stop hooksNative sidecar is stopped after main containers
Job never completesCall the quit endpoint of the proxy at the endNative sidecar does not block completion
Rules installed by privileged init containerAllow the permissions in policyUse a CNI plugin to set rules instead
!
Common trap

Connection failures that occur only in the first seconds of a Pod’s life, or only at the moment of rollout, are often lifecycle races rather than network bugs. Check the order of events in the Pod before blaming the mesh configuration.

14Variations: CNI Plugin, Ambient Mode, Linkerd, and Proxyless gRPC

The sidecar is the classic design, but it is not the only one.

CNI plugin instead of the init container

The Container Network Interface (CNI) is the plugin system the kubelet uses to set up Pod networking. A mesh can supply a CNI plugin that installs the traffic redirection rules while the Pod’s network is created. Then the Pod needs no privileged init container. This helps in clusters with strict security policy, because ordinary application namespaces no longer need elevated network permissions.

Ambient mode: no sidecar in the Pod

Sidecars cost memory in every Pod and require restarts to upgrade. Istio’s ambient mode splits the data plane into two layers. First, a small node-level agent called ztunnel, written in Rust, runs once per machine and handles identity and mTLS for all Pods on that machine, using a tunnel protocol on port 15008. Second, optional waypoint proxies, which are Envoy instances shared by a namespace or service, handle the richer request-level features only where needed. Ambient mode reached general availability in Istio 1.24.

QuestionSidecar modeAmbient mode
Where does the proxy run?In every PodPer node (ztunnel), plus shared waypoints
Memory costGrows with the number of PodsGrows with the number of nodes and waypoints
Upgrading the data planeRestart every PodUpgrade node agents and waypoints without restarting apps
Request-level featuresAlways availableOnly where a waypoint is enabled
IsolationProxy is private to each PodShared by many Pods on a node
Everyday analogy

Giving every flat its own security guard is expensive but very personal. Giving each floor one shared guard for ID checks, and calling a specialist only for special cases, costs less but shares more. Sidecar mode is a guard per flat, and ambient mode is a guard per floor.

Linkerd: a different proxy

Linkerd, also a graduated CNCF project, keeps the sidecar model but uses its own small proxy written in Rust. It aims for simplicity and a low resource cost, with fewer configuration options than Envoy-based meshes. Its injection also uses a webhook and an annotation, and it offers a CNI plugin as well.

Proxyless gRPC

Some gRPC libraries can speak xDS themselves. Then the application gets routing and load balancing directly from the control plane, without a sidecar for those requests. This removes the extra network hop for the most latency-sensitive services, at the price of tying the feature to a library and language.

i
Choosing

Start with the problem. If you mainly need encryption and identity everywhere, ambient mode’s lightweight layer may be enough. If you need rich per-request control for a few services, sidecars or waypoints serve those. Many organizations run a mix as they migrate.

15Performance and Scalability of the Data Plane

The mesh adds work to every request. Knowing where the cost lives lets you control it.

Each request passes through two extra proxies, one on each side. Each proxy reads the request, applies filters, and writes it out again. In practice this adds a small amount of delay, often around a millisecond or a few, depending on the features enabled and the load. Many applications never notice it. Latency-sensitive paths, such as calls that happen dozens of times inside one user request, can feel it more, because delays add up along the chain.

Config

Scope each proxy’s view

Use the scoping resource so each sidecar only learns about the services it really calls. This lowers memory and reduces update traffic.

Config

Avoid wildcard rules

Huge, overlapping route tables make configuration larger and slower to process.

Telemetry

Trim metric labels

Remove unused labels and disable unneeded access logs, which cost CPU and storage.

Resources

Right-size requests

Set proxy CPU and memory requests from measured use. Too low causes throttling and added latency; too high wastes cluster capacity.

Network

Reuse connections

HTTP/2 and keep-alive reduce handshakes between proxies, lowering CPU and delay.

Control plane

Scale istiod

Run several replicas and watch push times. A large mesh with frequent Pod changes drives many updates.

Where the time goes

1

Connection handshake

The first request between two proxies pays for a TLS handshake. After that, connections are reused, so the cost is spread over many requests.

2

Encryption and decryption

Modern processors handle this efficiently, and the cost is usually small compared with parsing and routing.

3

Parsing and filters

HTTP parsing, header changes, authorization checks, and statistics each add a little CPU. Extra plug-ins, especially custom WebAssembly filters, add more.

4

Extra hop through the loopback

Each request crosses the local network inside the Pod twice more than without a mesh. This is cheap, but it is not zero.

Everyday analogy

Adding airport security checks makes every journey a little longer, but the delay is small compared with the flight, and the safety is worth it. If every journey includes ten short hops, the checks add up, which is why architects try to reduce the number of hops in a chain.

i
Production example

Large operators of Istio commonly report that two things dominate their data plane costs: the memory held by sidecars because of a large default configuration, and the volume of telemetry. Scoping each proxy’s configuration and trimming metrics are therefore the first optimizations they reach for, well before tuning anything inside Envoy itself.

16High Availability and Failure Scenarios

The data plane is on the path of every request, so its failures matter. Here is what happens when each part breaks.

What failsWhat happensHow it recovers
istiod is down for a short timeExisting proxies keep working with last known config; no new config or new certificatesRestart or reschedule istiod; run several replicas
istiod is down for longer than certificate lifetimesCertificates expire and mTLS failsRestore the control plane well before expiry
The injection webhook is unreachableNew Pods may be blocked or created without a proxy, depending on the failure policyRestore the webhook; choose the failure policy deliberately
One Envoy crashesThat Pod loses connectivity brieflyThe agent restarts Envoy; Kubernetes may restart the container
A bad configuration is pushedEnvoy rejects it (NACK) and keeps the old oneFix the source rule; check for stale proxies
A destination Pod diesRequests to it fail until it is removed from the endpoint listRetries and outlier detection route around it
Node failureAll sidecars on the node vanish together with their PodsPods are rescheduled and re-injected on other nodes
Everyday analogy

If the head office of a chain of shops loses its phone line, the shops continue to sell using the last price list. But if the head office stays silent for weeks, the price list goes stale and the shop licenses expire. Short outages are survivable. Long ones are not.

The webhook failure policy decision

When the injection webhook cannot be reached, the API server must decide what to do. If the policy is fail, the Pod creation is rejected, so you never get a Pod without a proxy, but a webhook outage blocks all new Pods in the injected namespaces. If the policy is ignore, Pods are created without a proxy, so deployments continue, but those Pods bypass the mesh silently, which may violate security rules. Both choices have costs, and the right one depends on whether availability or security is more important for the namespace.

!
Common trap

The webhook is called for Pods in many namespaces, including, if you are not careful, the namespace where the control plane itself lives. A circular dependency, where the control plane cannot start because its own webhook is unavailable, can lock you out. Always exclude the control plane’s namespace from injection.

i
Good to know

Zone-aware load balancing and locality failover let proxies prefer nearby endpoints and shift to another zone only when local ones are unhealthy. This is a built-in way to survive the loss of a whole zone with little fuss.

17Security of the Data Plane Itself

The mesh adds security, and it also adds new things that need protecting.

Do

Enforce strict mTLS

After onboarding, require encrypted and authenticated traffic between all workloads.

Do

Write authorization policy

Start with deny by default, then allow specific callers by identity, method, and path.

Do

Protect the control plane

Limit who can change mesh policy and the injection settings. These settings control the traffic of every service.

Do

Use a CNI plugin or tight policy

Avoid giving application namespaces broad network permissions just for the init container.

Do

Plan the root of trust

Decide who owns the root certificate, how it is stored, and how it is rotated, especially across several clusters.

Do

Keep proxies patched

The proxy handles untrusted traffic. Security fixes in Envoy matter, and rolling Pods is how sidecars are updated.

Where the mesh does not protect you

A mesh protects traffic between proxies. It does not protect against a compromised application, a stolen database password, or a vulnerable library. Traffic that bypasses the proxy, for example excluded ports or processes running as the proxy’s user, gets no mesh protection. The loopback link between the application and its own sidecar inside the Pod is also unencrypted, since it never leaves the Pod. And because the sidecar shares the Pod with the application, an attacker who breaks into the application container may be able to reach the sidecar’s local interfaces, so the admin port must be kept local and the Pod hardened.

Everyday analogy

Armored vans protect valuables on the road between banks. They do nothing about a dishonest clerk inside a bank. The mesh is the armored van service: excellent in transit, unrelated to what happens inside each building.

!
Common trap

An authorization policy that has no rules does not mean “allow all” or “deny all” in the way people assume; the exact behavior depends on the policy action. Test policies in a staging environment and use the mesh’s dry-run and logging options before enforcing.

Production example: platform teams enforcing mesh membership

Platform teams in larger companies often use admission policies to require that production namespaces carry the injection label and that Pods cannot opt out without approval, so developers cannot accidentally or deliberately run unprotected workloads next to protected ones.

18Monitoring and Debugging the Data Plane

When a request fails inside a mesh, there are more places to look. A good order saves hours.

Metrics for the data plane and control plane

SignalWhat it tells youWarning sign
istio_requests_totalRequest counts by source, destination, and response codeRising 5xx or 503 rates
istio_request_duration_millisecondsLatency distribution per service pairHigh percentiles climbing
Proxy memory and CPU usageSidecar resource pressureNear the limit; throttling
Control plane push timeHow long a config change takes to reach proxiesSeconds or more, which means slow propagation
Proxy sync statusWhether each proxy has the latest configStale or not-sent entries
Certificate expiryWhen workload and root certificates endExpiry within days with no renewal

A calm debugging order

1

Confirm injection

Check that the Pod really has the sidecar container and that it is ready. A Pod with one container in an injected namespace usually means injection did not happen.

2

Check proxy sync

Ask the control plane for each proxy’s sync status. A stale proxy has old configuration, which explains many odd failures.

3

Read the access log flag

The response flag names the failure type: no route, no healthy upstream, connection failure, or timeout.

4

Inspect the proxy’s own view

The command line tool can show the listeners, routes, clusters, and endpoints a specific proxy holds, so you can see what the proxy believes.

5

Check the policy and mTLS settings

Mismatched mTLS modes between a client and a server are a classic source of resets and 503 errors.

6

Look at the application last

If the proxies agree and the flags are clean, then the problem is likely in the application itself.

Everyday analogy

If a letter did not arrive, you first check that it was posted (injection), then that the post office has the right address book (sync), then read the stamp from the sorting office (flag), and only after that visit the recipient’s house.

i
Tip about 503 errors

The status 503 is the most common error people see in a mesh, and it can mean many things. The flag next to it tells you which. Never debug a 503 without reading the response flag first.

19Advantages, Disadvantages, and Trade-offs

Every design has a price. Here is an honest look at the sidecar mesh.

Advantages

  • Language independent: works for any application that speaks over the network.
  • Consistent security: mTLS and identity-based policy everywhere.
  • Uniform observability: the same metrics and logs for every service.
  • Central control: change a rule once and it spreads live.
  • Safer releases: weighted traffic shifting and fast rollback.
  • Strong isolation per Pod: a proxy failure affects only one Pod.

Disadvantages

  • Resource overhead: CPU and memory in every Pod.
  • Extra latency: two additional hops on each call.
  • Operational complexity: a control plane, certificates, and many new settings.
  • Hard debugging: more places where a request can fail.
  • Lifecycle friction: startup, shutdown, and Job problems.
  • Upgrade effort: sidecars update only when Pods restart.
Trade-offChoiceWhat you gainWhat you give up
Sidecar versus ambientAmbient modeLower per-Pod cost, easier upgradesShared proxies, rich features only at waypoints
Strict versus permissive mTLSStrictEverything is encrypted and authenticatedOlder callers may break
Retry often versus fail fastMore retriesHides short glitchesRisk of retry storms
Full detail telemetry versus minimalFull detailRich diagnosisCost and CPU
Whole mesh versus selected namespacesSelectedLower risk and costGaps in coverage and uneven security
Fail open versus fail closed webhookFail closedNever run an unprotected PodDeployments blocked during an outage

Do you need a mesh at all?

A mesh is a strong tool, but not a free one. A cluster with a handful of services, one language, and modest security needs may be better served by simple libraries, ingress rules, and network policies. The mesh pays off when there are many services, many teams, strong security or compliance needs, and a need for uniform control. Adopt it for a reason you can state in one sentence.

The best proxy is the one you can run, understand, and debug at three in the morning.

20Design Patterns and Anti-Patterns

A few habits keep a mesh helpful. A few others turn it into a burden.

Patterns worth copying

Pattern

Onboard gradually

Start with one namespace, in permissive mode, watch results, then widen and tighten.

Pattern

Scope proxy configuration

Give each namespace an explicit list of the services it needs to see.

Pattern

Revision-based upgrades

Run old and new control planes side by side, and move namespaces one at a time.

Pattern

Default deny, then allow

Authorization starts closed and opens only for approved identities.

Pattern

Name ports by protocol

So the proxy treats HTTP, gRPC, and TCP correctly.

Pattern

One place for retries

Decide which layer retries, and set budgets and timeouts consistently.

Anti-patterns to avoid

ANTI-PATTERN 01Avoid
The mistake

Injecting every namespace on day one, including system namespaces and batch jobs.

Why it hurts

You multiply risk and cost at once, and lifecycle issues hit Jobs and system components that gain nothing from the mesh.

Do this instead

Select namespaces on purpose, exclude the control plane and system components, and use native sidecars for Jobs.

ANTI-PATTERN 02Avoid
The mistake

Leaving mTLS permissive forever.

Why it hurts

Plain traffic is still accepted, so the mesh gives a false sense of security.

Do this instead

Measure plain traffic, bring remaining callers in, and then enforce strict mode.

ANTI-PATTERN 03Avoid
The mistake

Stacking retries at every layer of the call chain.

Why it hurts

One failure multiplies into a storm of requests that finishes off the struggling service.

Do this instead

Retry at one layer, cap retries, and use shorter timeouts closer to the caller than to the deepest service.

ANTI-PATTERN 04Avoid
The mistake

Running the application as the proxy’s user ID, or excluding ports casually.

Why it hurts

Traffic silently bypasses the proxy, so security and metrics have invisible holes.

Do this instead

Use a different user ID, document every exclusion, and review exclusions regularly.

ANTI-PATTERN 05Avoid
The mistake

Leaving the default configuration for each proxy to include the whole mesh.

Why it hurts

Memory per sidecar grows with every new service, and every change creates a flood of updates.

Do this instead

Scope each proxy’s configuration to its real dependencies.

ANTI-PATTERN 06Avoid
The mistake

Assuming that upgrading the control plane upgrades the sidecars.

Why it hurts

Proxies stay on old versions, possibly with known security issues or behavior mismatches.

Do this instead

Plan rolling restarts as part of every mesh upgrade, and track the proxy version of every Pod.

21Best Practices and Common Mistakes

A short checklist to read before you add a mesh to a cluster.

1

Have a clear reason

Write down the one or two problems you want the mesh to solve, such as encrypted traffic or uniform metrics, and judge success against them.

2

Start small and measure

Record resource use and latency before and after for a pilot namespace.

3

Fix the startup and shutdown order

Use native sidecars or the hold-until-ready setting, and set a sensible drain time.

4

Keep the control plane highly available

Several replicas, spread across zones, with resource requests and alerts.

5

Watch certificates

Alert on expiry for both workload certificates and the root.

6

Name ports and set protocols

So the proxy can use the best handling for each service.

7

Automate upgrades

Revision labels, canary namespaces, and a routine of rolling workloads.

8

Teach the debugging order

Make sure every on-call engineer knows how to read sync status and response flags.

Mistakes beginners make

  • Labeling a namespace and expecting running Pods to change. Injection only happens at Pod creation.
  • Forgetting that the sidecar counts in resource requests. Cluster capacity shrinks after injection.
  • Blaming the mesh for every failure. Many errors are real application errors that the mesh is now able to show you.
  • Setting timeouts too short or retries too many. Both cause more trouble than they solve.
  • Treating a Job like a long-running service. Without a native sidecar or a quit step, it never finishes.
  • Skipping protocol naming on ports. The proxy falls back to plain TCP handling, and metrics disappear.
  • Enforcing strict mTLS without a readiness plan. Health probes and old clients start failing.
i
A quick mental check

When a call fails in a mesh, ask three questions in order: does the Pod have a healthy sidecar, does the proxy have the latest configuration, and what does the response flag say. These three answer most cases before you need to look deeper.

22Real-World and Industry Examples

The same ideas appear in many production environments.

Lyft: where Envoy was born

Lyft built Envoy to tame the networking of a fast-growing set of services in several languages, and then open-sourced it. It became a graduated project of the Cloud Native Computing Foundation and is now the data plane or edge proxy in a large share of the cloud-native ecosystem.

Istio users: Airbnb, Salesforce, and others

Several large companies have given public talks about running Istio at scale, including Airbnb and Salesforce. Their themes are consistent: uniform security and observability, safer releases through traffic shifting, and the importance of scoping configuration and planning upgrades carefully.

Linkerd users: simplicity first

Organizations that value a small footprint and easy operation often choose Linkerd. Its Rust proxy has a smaller feature set but a lower resource cost, and many teams find it quicker to learn.

Managed offerings: Google Cloud, Amazon, and Azure

Cloud providers offer managed or integrated service mesh products, many built on Istio and Envoy, so customers get the benefits without running the control plane themselves. The data plane still lives in the customers’ own Pods, so ideas such as injection, startup order, and resource sizing still apply.

Edge gateways: Envoy at the front door

Envoy is also the engine of many ingress and API gateway products, including implementations of the Kubernetes Gateway API. The same listeners, routes, clusters, and xDS ideas apply at the edge, so skills transfer.

i
The common thread

The successful adopters share a pattern: they start with a clear goal, onboard slowly, measure costs, invest in debugging skills, and tune configuration scope and telemetry before scaling out. The technology is powerful, but the habits around it decide the result.

23Frequently Asked Questions

Short answers to the questions beginners ask most often.

Q1What is the difference between the control plane and the data plane?
The control plane decides the rules and distributes them. The data plane, made of the proxies, carries the actual requests and enforces those rules. If the control plane pauses, the data plane keeps working with its last known rules.
Q2How does the sidecar get into my Pod without me editing my files?
A mutating admission webhook. When a Pod is created, the API server sends it to the mesh’s webhook, which returns a patch that adds the init container, the proxy container, and supporting volumes before the Pod is stored.
Q3How does the application’s traffic reach the proxy?
Traffic redirection rules in the Pod’s network namespace, installed by an init container or a CNI plugin, send outgoing connections to the proxy’s outbound port and incoming connections to its inbound port. The proxy’s own traffic is marked so it does not loop.
Q4Why did my existing Pods not get a sidecar after I labeled the namespace?
Injection runs only when a Pod is created. Restart or roll out the workloads so the new Pods pass through the webhook.
Q5What does xDS stand for?
It is a family of discovery services: listeners, routes, clusters, endpoints, secrets, and others. Together they let a control plane stream configuration to Envoy and update it live.
Q6Does the mesh encrypt traffic automatically?
Between sidecars, yes, using mTLS in the default setup. But in permissive mode plain traffic is still accepted, so you should move to strict mode once all workloads are in the mesh.
Q7How much overhead does a sidecar add?
It adds CPU and memory to each Pod and a small amount of delay to each call, often around a millisecond or a few. The exact numbers depend on features, traffic, and configuration size, so measure in your own cluster.
Q8Why does my Job never finish when a sidecar is present?
The sidecar container keeps running after the main container exits, so the Pod never completes. Native sidecar containers solve this, or you can ask the proxy to quit at the end of the work.
Q9What happens if the control plane goes down?
Existing proxies continue with their last configuration. New Pods may not receive configuration, and certificates cannot be renewed, so a long outage eventually breaks mTLS when certificates expire.
Q10Is ambient mode a replacement for sidecars?
It is an alternative. Ambient mode moves basic identity and encryption into a per-node agent, with optional shared proxies for richer features. Many teams will use sidecars for some workloads and ambient mode for others.
Q11What does a 503 error with the flag UH mean?
The proxy had no healthy upstream endpoint to send the request to. Check whether the destination Pods are ready, and whether outlier detection has ejected them.
Q12Do I need a service mesh for a small cluster?
Often not. If you have few services, one language, and modest security needs, simpler tools may suffice. A mesh pays off with many services, many teams, and a need for uniform security and observability.

24Summary and Key Takeaways

You started with an assistant sitting beside every employee and finished with a full picture of how a service mesh data plane works. A webhook slips a proxy into every Pod. Network rules quietly redirect all traffic through it. Envoy processes each request through listeners, filters, routes, and clusters, guided by a live feed of configuration. Short-lived certificates give every workload an identity, so traffic can be encrypted and controlled by who is calling. The price is extra resources and extra moving parts, and the reward is consistent security, reliability, and visibility across every service.

Key Takeaways

  • The data plane is the set of proxies that carry traffic. In an Envoy-based mesh, each Pod gets a sidecar, while the control plane decides rules and sends them out.
  • Sidecar injection uses a mutating admission webhook that patches each new Pod with an init container, the proxy container, and supporting volumes. It happens only at Pod creation, so running Pods need a restart.
  • Traffic is captured by kernel rules inside the Pod, sending outgoing traffic to the proxy’s outbound port and incoming traffic to its inbound port, with the proxy’s own traffic exempted to avoid loops.
  • Envoy is an assembly line: listeners, filter chains, routes, clusters, and endpoints, run on a few non-blocking worker threads and configured live through xDS with acknowledge-or-reject safety.
  • Certificates give identity. Each Pod obtains a short-lived workload certificate, enabling mutual TLS and identity-based policy, which should be moved from permissive to strict mode in steps.
  • Resilience features need care. Load balancing, retries, timeouts, and circuit breaking help, but stacked retries and bad timeouts can cause storms. Fix lifecycle races with native sidecars or hold-until-ready, and drain time.
  • Run it deliberately. Scope proxy configuration, trim telemetry, keep the control plane highly available, plan sidecar upgrades, learn to read response flags, and consider CNI or ambient mode when security policy or cost demands it.