Service Mesh with Istio: installation and configuration in Kubernetes

We implement an Istio-based service mesh in Kubernetes as a turnkey solution: service connectivity stops depending on manual edits in application code. The customer gets managed traffic rules, predictable behavior during failures, and observability without rebuilding services. We will discuss the task and come back with an estimate and plan.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

Istio in Kubernetes: where service connectivity breaks down

While there are about ten services in a cluster, microservice connectivity rests on agreements: addresses are hardcoded in configuration, access rules — in manifests next to the application.

Over a horizon of several months, replicas move between nodes, dynamic addresses appear, some services communicate via short internal names, others via external ones.

A build that yesterday responded in seconds starts returning connection errors to a neighbor, and the cause is sought in application logs rather than in network state.

The second fault line is policies. Authentication between services is usually implemented inconsistently: in some places verification is inside the code, in others at the ingress gateway, and in others not implemented at all.

As a result, some internal traffic flows entirely without verification of the caller's authenticity, and changing a rule requires rebuilding and rolling out several applications at once. There is no single point where all service-to-service exchange can be seen and configured.

Cascading failures are the most expensive. One service starts responding slowly — the service calling it holds connections, accumulates a queue, and also degrades; then the same repeats down the chain.

Retries of failed requests, which the application makes "just in case", double the load on an already overloaded node.

Request observability is limited: metrics are collected separately for each service, and they do not show at which specific hop the call spent most of its time.

A unified service-to-service exchange layer addresses all three points at once. Traffic management between services moves into declarative rules: distributing request share between versions, limiting concurrent calls, timeouts, and circuit breaking are set in one place.

The network gets end-to-end call identification, so a request's path through five services is assembled into one trace rather than five disparate logs.

This is exactly what Istio, as a layer on top of the cluster, resolves: it takes on addressing, encryption of internal exchange, and telemetry collection without requiring rewriting service code. Below we break down how it works and in what order it is implemented without stopping the product.

What a service mesh delivers: measurable effects

We discuss the effects of a service mesh in verifiable metrics, not in terms of "it became more convenient." Below are the checkpoints for Istio in Kubernetes: they are taken before implementation and repeated after, on the same set of services and the same load profile.

Releasing new versions of services accelerates through weight-based routing: the new version receives a small share of traffic, metrics are compared with the previous one, then the share grows on a schedule or based on check results.

Rollback is a change to one rule, not a rebuild and re-release: time to return to a working state is measured in seconds.

Encryption of traffic between services becomes a platform property: certificates are issued and rotated automatically, the application knows nothing about them — a class of failures due to expired certificates and manual trust configuration goes away.

Load balancing moves to the consumer: requests are distributed across all live instances, slow nodes are removed from rotation, and this is visible in the spread of latency between replicas.

Failure diagnostics relies on a unified telemetry layer: metrics, logs, and tracing are collected identically for all services, regardless of language and stack.

Incident localization time drops from hours to minutes — you can see at which segment of the chain the request loses time.

The control metrics are simple: time to release a new version, failure rate during update, time to rollback, latency spread between instances, failure localization time.

If they do not diverge before and after implementation, the mesh does not solve your problem — and that is an honest reason not to implement it.

Istio deployment modes in Kubernetes

Implementing a service mesh in Kubernetes begins with choosing a mode: it determines the data plane overhead, the speed of onboarding services, and how the multi-cluster configuration will be arranged.

Changing the mode on a running cluster is possible, but it is a separate migration with workload restarts — so the decision is made before rollout, not after the first incident. Below are the options chosen in practice and their limitations.

Option When it fits Mode limitations
Sidecar proxy in each pod Heterogeneous workloads, all security policies and pod-level tracing are needed Additional container in each pod, memory consumption grows, onboarding a service requires a restart
Sidecarless mode, proxy on the node Dense clusters where onboarding speed and resource savings matter Some capabilities appear with delay, an up-to-date kernel branch and a compatible network module are required
Multi-cluster with a single control plane A unified policy for sites, a separate team on member clusters The control cluster becomes a point of failure, trust between clusters is configured manually
Multi-cluster with peer control planes Site-level fault tolerance, independent releases Configuration synchronization and conflict resolution are more difficult when policies diverge

Mode limitations should be checked on your own cluster in advance: network module compatibility, kernel version, and certificate issuance method influence the choice more than the feature list.

Onboarding services to the mesh in any case comes down to a label on the namespace and proxying traffic without changes to application code — and then the mode is scaled up step by step, matching the team's pace of change.

Stages of implementing a service mesh in a cluster

A mesh based on Istio is implemented not with a single installation command, but as a sequence of steps where each is reversible and verifiable.

We do not enable traffic interception across the entire cluster at once — first we record the current connectivity in Kubernetes, then move it into the mesh one namespace at a time.

  1. Cluster audit: inventory of services, dependencies, and current routing. The output is a connectivity map and a list of places where the mesh has an effect and where it adds an unnecessary layer.
  2. Design and boundaries: which namespaces are included in the mesh, how ingress points and access policies are arranged. We agree on the design before changes in the cluster.
  3. Pilot environment: control plane and sidecar proxies in one non-critical namespace. We verify that metrics, traces, and logs are collected without loss.
  4. Phased enablement: we migrate namespaces in groups, with latency and error-rate monitoring after each. A problematic environment is removed from the mesh with one label; the rest of the cluster is unaffected.
  5. Load testing: failure scenarios — node failure, service unavailability, loss of connectivity between zones. We observe how retry and timeout policies behave on real traffic.
  6. Handover to operations: configurations, design, update regulations, and analysis of typical incidents for the team.

Each stage is closed with a measurable criterion: share of services under management, response latency, number of failures requiring manual intervention. Until the criterion is met, the next stage does not begin.

Configurations and regulations: what the team keeps

A service mesh lives not in an engineer's head but in a repository. Implementation ends not with launching Istio but with handing over a kit: configurations, designs, policies, and regulations that the team then uses on its own.

Everything is stored in version control and changed only through review — the history of routing and access decisions remains auditable.

  • Configuration files: deployment parameters for mesh components, resource profiles, behavior of the proxy layer under load.
  • Routing design: which rules direct traffic, canary version weights, timeouts, retries, and circuit breaker thresholds.
  • Access policies: mutual authentication between services, permissions for "who can call whom," rights of external ingress points.
  • Operations regulations: mesh update procedure, maintenance windows, and procedure to roll back to the previous version with a single action.
  • Check descriptions: readiness and liveness probes, load scenarios, acceptance criteria after each configuration change.
  • On-call instructions: what to look at when the error rate grows, how to isolate a service, how to temporarily remove or restore a routing rule.
  • Dependency map: service connections and points where failure of one node affects neighbors.
  • Service mesh documentation: layer structure, what is configured where, whom to contact for a change.

The kit removes dependence on the person who authored the setup: a new engineer brings up a stand and investigates an incident using documents, not chat messages.

Case study: eliminated cascading failures between services

What it was like before implementation

A platform of several dozen services on Kubernetes, connected by direct calls, with request retries and timeouts in each service's code separately.

When one started responding slowly, retries multiplied the load, and a couple of minutes later neighboring services went down, although they themselves had not failed.

The on-call engineer learned about the incident from user reports: there was no unified picture of calls between services.

What we changed

We deployed Istio as a traffic management layer: a proxy appeared next to each service, seeing every call and obeying common rules.

Limits on retries, timeouts, and circuit breaking were moved from code into configuration — now they are the same for all services and change without rebuilding.

Release of a version was switched to gradual rollout: the new version first receives a small share of traffic, then more based on metrics.

What the result was

The share of unsuccessful calls dropped from 4.7% to 0.3%: individual failures are absorbed at the proxy and do not reach the user. A failure is localized in seconds — you can see which service and which route degraded, instead of parsing logs across the whole chain.

Time to release a new version decreased from several hours of manual checks to minutes, and rollback is one command.

The rules operate at the proxy level, so a new service receives the same protection automatically, without code changes. This eliminates the class of cascading failures as a whole, not just a single unsuccessful release.

How does a mesh differ from a library inside the application?

A library in an application is code that a developer integrates into each service separately: retries, timeouts, rate limiting, traffic encryption between services, distributed tracing.

It works, but connectivity management ends up smeared across repositories: to change a timeout or an access rule, you need to edit code, go through a build, and roll out each service.

The more teams there are, the more library versions diverge and the more often the behavior of the same call differs from service to service.

A mesh based on Istio moves this logic out of code into a proxy next to the pod, while the control plane distributes configuration to all nodes at once.

Connectivity becomes a platform property rather than an application property: a routing rule, circuit breaking, or authorization check is applied to the required group of services with one configuration change, without a release.

The application remains an application — its code does not know who exactly delivers the request or how.

The main practical difference is dependence on the development language. A library exists for a specific stack, and in a heterogeneous environment you have to maintain several implementations with different behavior and different feature sets.

The mesh removes this limitation: services in any language receive the same set of functions because it is implemented not in the service code but in the common layer.

A unified policy layer is the second reason to choose a mesh. Encryption between services, access separation, load limits, and routing rules are set centrally and uniformly enforced on all traffic.

The trade-off is an additional link in the request path and requirements for the maturity of the platform team. If the environment is small and homogeneous, libraries are simpler; if there are dozens of services and languages differ, the mesh wins on manageability.

Technical concerns before implementing a mesh

The engineering team's objections before implementation are usually the same: latency will grow, service code will have to be modified, rollback will prove painful. We address them specifically — at the configuration level, not with general promises.

Enablement is structured so that the application does not know about the mesh: traffic goes through a sidecar proxy next to the pod, and no code changes are required. Risks lie not in the application but in the enablement order and in who operates the environment after handover.

How much will latency between services increase?

One network hop is added per call — on a real traffic profile this is fractions and single-digit percentages of response time, not a multiple increase.

We measure latency before and after on a production profile, not synthetic; for sensitive paths we leave an exception via a bypass policy.

Can it be enabled in stages and rolled back?

Yes. First one namespace in observation mode, then sidecar proxies for individual services, then mutual authentication and routing rules. At each step we monitor latency and error rate; rollback is removing a label from the namespace, without rebuilding applications.

Who renews certificates?

The control plane issues and rotates certificates for mutual authentication itself; there is no manual renewal. We configure the lifetime, notifications about upcoming rotation, and trust chain validation — so that an issuance failure does not stop service-to-service exchange.

What remains with us after handover?

Configuration, traffic flow diagrams, access policies, and update regulations — with analysis of typical failures for the on-call shift. We update the control plane to the current branch on an agreed schedule, with validation on a staging environment before rollout.

Let's discuss the task and come back with an estimate and plan

To make the implementation estimate substantive rather than a rough guess, we need the set of initial data: where the cluster is deployed — managed by a provider or assembled manually, how many environments and namespaces it has, what is already at the ingress, and how certificates are currently issued.

  • list of services that need to be included in the mesh and their connections — who communicates with whom and over which protocols;
  • environment diagram: test, pre-production, and production — whether they match in configuration;
  • current method of publishing traffic outside and routing rules, if they are already described;
  • where metrics, logs, and traces are collected — which observability system you are tied to;
  • current security policies and restrictions on access rights inside the cluster;
  • desired mode: strict traffic authentication immediately or a gradual transition with observation.

Next, the analysis of the task is led by the engineer who will do the implementation — we discuss not generalities but configurations and bottlenecks: how traffic will flow if a node fails, what to do with services without a sidecar, and how not to bring down production when switching to strict mode.

We deliver the work plan as a document: stages with checkpoints, responsibility boundaries, rollback procedure at each step, and a list of what is required from your side. Describe the task in free form — we will come back with an estimate and work plan.