Zero-Trust Networking in Kubernetes

Zero-Trust Networking in Kubernetes

Why "inside the cluster" should never mean "trusted", and how identity, encryption, and tight rules turn a wide-open network into one where every connection must prove itself, explained from zero.

Picture an old medieval castle. A thick wall surrounds it, and one big gate lets people in. Once you are past the gate, nobody asks any more questions. You can walk into the kitchen, the armory, the treasury, and the king’s bedroom. The whole defense depends on one idea: the wall keeps the bad people out. Then one day a single thief sneaks in disguised as a delivery driver, and within minutes he has the keys to everything.

For many years, computer networks worked exactly like that castle. A strong firewall guarded the edge, and everything inside was trusted. A default Kubernetes cluster is built the same way. Any pod can talk to any other pod, and nobody checks who is calling. Zero-trust networking throws that old idea away. It says: never trust, always verify. Every single connection, even one between two pods sitting side by side, must prove who it is and show that it is allowed. This post explains how to build that world in Kubernetes, assuming you know nothing about the topic yet. By the end, you will understand every layer, every tool, and every trade-off, in simple language you can use in real projects and in interviews.

1What Zero Trust Really Means

The words “zero trust” are used everywhere, often loosely. Before we touch Kubernetes, we need a precise and simple meaning.

The core idea in one sentence

Zero trust is a security approach in which no user, device, or program is trusted automatically just because of where it is on the network. Every request must be identified, checked against a rule, and allowed only if the rule says yes. The phrase was popularized in the early 2010s by an analyst named John Kindervag, and the United States standards body NIST later published a detailed reference, called Special Publication 800-207, that describes zero-trust architecture in formal terms.

Everyday analogy

Think of the difference between a castle and an airport. In a castle, once you pass the gate you roam freely. In an airport, your ticket is checked at the entrance, again at security, again at the gate, and again at the plane door. Even staff badges are scanned at every secure door. Zero trust makes your cluster work like the airport: identity is checked at every door, not only the front one.

Four questions behind every request

A zero-trust system asks the same four questions each time one program tries to talk to another.

Who

Identity

Who is making this request? The answer must be provable, not just a claim.

What

Authorization

Is this caller allowed to do this specific action on this specific target?

How

Encryption

Is the conversation protected so that nobody in the middle can read or change it?

Proof

Visibility

Is the request recorded so that problems can be detected and investigated later?

Three guiding principles

1

Verify explicitly

Always check identity and context. Never accept “it came from inside the network” as proof.

2

Use least privilege

Give each program only the connections it truly needs. Everything else is blocked by default.

3

Assume breach

Design as if an attacker is already inside, so that one stolen pod cannot become a stolen company.

0
connections trusted by location alone
4
questions asked for every request
3
core principles to remember

Production example: Google BeyondCorp and BeyondProd

Google publicly described its move away from perimeter trust in a program called BeyondCorp for employee access, and later in a paper called BeyondProd for its production services. The BeyondProd ideas include strong service identity, encrypted service-to-service calls, and rules that say which service may call which. These are the same building blocks you will meet in this post, and they strongly influenced the design of Kubernetes security tools.

i
Remember this

Zero trust is not a product you can buy and switch on. It is a design habit, built from several smaller controls that work together: identity, encrypted traffic, tight rules, and constant observation.

2Why a Default Cluster Is a Flat Network

To fix a problem, you must first see it clearly. Kubernetes was designed to make networking simple for developers, and that simplicity is exactly what makes it risky.

The Kubernetes networking promises

Kubernetes sets down a few simple rules. Every pod receives its own IP address. Every pod can reach every other pod using that address, without any address translation in between. Nodes can talk to all pods and pods can talk to all nodes. These rules make life easy, because developers never need to think about ports and tunnels. The cost is that, by default, the cluster is one giant open room.

What a flat network allows

In a flat network, a pod running a small public website can connect directly to the payments database in another namespace, because nothing forbids it. The network does not know that the website has no business talking to the database. It only knows that both have IP addresses.

flowchart LR
  I["Internet user"] --> W["Public web pod"]
  W --> A["Orders API pod"]
  A --> D["Payments database pod"]
  W -. "default cluster: also allowed" .-> D
  W -. "default cluster: also allowed" .-> S["Internal admin pod"]
  W -. "default cluster: also allowed" .-> K["Cloud metadata service"]
    
Figure 1: In a default cluster, the dotted lines are open even though the application never needs them

Lateral movement: the real danger

Attackers rarely win by breaking into the most valuable system directly. They usually break into the weakest system first, such as an outdated web component, and then move sideways from machine to machine until they reach what they want. Security people call this lateral movement. A flat network makes sideways travel trivial. Many widely reported breaches, including the 2013 retail breach in which attackers entered through a third-party vendor and then crossed an internal network, followed this pattern.

Why teams accept flat networks

  • It works immediately, with no configuration.
  • Developers never see mysterious connection failures.
  • New services can call old ones without paperwork.

What they quietly accept

  • One compromised pod can scan the whole cluster.
  • Secrets and databases are reachable by every workload.
  • Nothing records who talked to whom.
!
Do not confuse isolation with safety

Putting teams in different Kubernetes namespaces does not separate their network traffic. A namespace is only a folder for organizing objects. Without network rules, a pod in one namespace can still talk to a pod in any other.

The attack surface inside a cluster

Target

Other pods

Databases, caches, and message queues often have no password because “only internal apps can reach them”.

Target

Cluster API server

Reachable from every pod. A stolen token here can mean control of the whole cluster.

Target

Node services

The kubelet and the cloud’s metadata endpoint can hand out powerful credentials if reached.

Target

The outside world

Unrestricted outgoing traffic lets an attacker send stolen data anywhere.

3Kubernetes Networking in Plain English

Zero trust is applied to the network, so you need a clear picture of how traffic actually flows in a cluster. We will build the picture one piece at a time.

Pods and their addresses

A pod is the smallest unit Kubernetes runs: one or more containers that share a network identity. Each pod gets one IP address from a range assigned to its machine. Pods come and go constantly, so their addresses change. This is the first reason zero-trust rules cannot be written around IP addresses alone: the address you trusted a minute ago may now belong to a completely different program.

Services: a stable name in front of moving pods

A Service gives a group of pods one stable name and one stable virtual address. Clients call the Service, and Kubernetes spreads the calls across the healthy pods behind it. A component called kube-proxy, or an equivalent built into the network plugin, performs this spreading by rewriting the destination address of each packet to the address of a real pod.

DNS: names instead of numbers

Cluster DNS translates Service names, such as orders.shop.svc.cluster.local, into virtual addresses. Almost every application call begins with a DNS lookup, so DNS is both essential and a favorite place for attackers to hide. Remember this, because it matters when we write egress rules later.

The network plugin

Kubernetes itself does not move packets between machines. It delegates the job to a CNI plugin, where CNI stands for Container Network Interface. Popular choices include Calico, Cilium, and on Amazon EKS the AWS VPC CNI. The plugin gives out pod addresses and wires up the connections. Very importantly for us, the plugin is also the part that enforces network rules. If your plugin does not enforce rules, the rules you write do nothing.

Ingress and egress

Security people use two simple words. Ingress means traffic coming into a pod. Egress means traffic going out of a pod. They also use compass words: north-south traffic crosses the cluster boundary, such as a customer visiting your website. East-west traffic stays inside, such as the website calling the orders service. Zero trust cares about both, but east-west traffic is the part most teams forget.

flowchart TD
  U["Customer on the internet"] -->|"north-south"| LB["Load balancer"]
  LB --> ING["Ingress or gateway"]
  ING --> WEB["Web pods"]
  WEB -->|"east-west"| API["Orders API pods"]
  API -->|"east-west"| DB["Database pods"]
  API -->|"north-south egress"| EXT["External payment provider"]
  WEB -.-> DNS["Cluster DNS"]
  API -.-> DNS
    
Figure 2: North-south traffic crosses the cluster edge; east-west traffic moves between pods inside it
Everyday analogy

Think of a large office building. Visitors entering through the main lobby are north-south traffic. Employees walking between departments on different floors are east-west traffic. The receptionist’s phone directory is DNS. The building’s wiring contractor is the network plugin, and the security guards at each floor door are the enforcement points that zero trust adds.

i
Key takeaway

Pod addresses change, Services hide those changes, DNS finds Services, and the network plugin carries and polices the packets. Good zero-trust rules are written using labels and identities, never fixed pod addresses.

4The Zero-Trust Stack for Kubernetes

No single feature gives you zero trust. You build it from layers, each answering one of the four questions from the first chapter.

flowchart TD
  L1["Layer 1: Default-deny network rules (NetworkPolicy)"] --> L2["Layer 2: Workload identity (service accounts, SPIFFE)"]
  L2 --> L3["Layer 3: Encrypted traffic (mutual TLS)"]
  L3 --> L4["Layer 4: Request-level authorization (who may call what)"]
  L4 --> L5["Layer 5: Controlled entry and exit (gateways, egress control)"]
  L5 --> L6["Layer 6: Cloud and node boundaries (security groups, metadata protection)"]
  L6 --> L7["Layer 7: Observability and detection (flow logs, audit, alerts)"]
    
Figure 3: Seven layers that together deliver zero-trust networking

Reading the stack

LayerQuestion answeredTypical tools
Network rulesMay these two pods connect at all?NetworkPolicy, Calico, Cilium
Workload identityWho exactly is this program?Service accounts, SPIFFE and SPIRE, certificates
Encrypted trafficIs the conversation private and authentic?Mutual TLS from a mesh or the network plugin
Request authorizationMay this identity perform this exact call?Mesh authorization policy, API gateway rules
Entry and exit controlWhat may come in, and what may leave?Ingress, Gateway API, egress gateways
Cloud boundariesIs the underlying network also locked down?Security groups, private endpoints, metadata protection
ObservabilityCan we see and prove what happened?Flow logs, mesh telemetry, audit logs

Why layers instead of one big wall

Each layer covers a weakness of the others. Network rules are fast and simple but only understand addresses and ports. Identity and encryption understand who is calling but depend on a healthy certificate system. Request authorization understands individual API calls but needs a proxy in the path. Cloud boundaries protect against mistakes inside the cluster. Observability tells you when any of the other layers has failed. This design philosophy is called defense in depth.

Everyday analogy

A bank does not rely on one lock. It has a locked front door, cameras, a guard, a vault door, individual safe-deposit keys, and an alarm. If a thief defeats one, the others still stand. Zero-trust networking stacks protections in the same way.

i
Where to start

If you can only do three things this quarter, do these: apply default-deny network rules per namespace, stop pods from reaching the cloud metadata service, and turn on encrypted service-to-service traffic. These three remove most of the easy attack paths.

5NetworkPolicy: The First Wall

Kubernetes gives you one built-in object for controlling pod traffic. It is called NetworkPolicy, and it is the foundation of everything else in this post.

What a NetworkPolicy is

A NetworkPolicy is a rule that lives inside one namespace. It selects a group of pods using labels, and then states which incoming connections (ingress) and which outgoing connections (egress) those pods may have. The “allowed” side can be described by pod labels, by namespace labels, or by ranges of IP addresses called CIDR blocks, together with port numbers.

The most important behavior to understand

NetworkPolicy has one behavior that surprises almost every beginner. Pods start with everything allowed. The moment any policy selects a pod for a given direction, that pod becomes isolated in that direction, and only what the policies explicitly allow is permitted. Policies can only add permissions. They cannot subtract them. There is no “deny” rule in the standard object. If two policies select the same pod, the pod gets the combined allowances of both.

1

No policy selects the pod

All ingress and all egress are allowed. This is the default, open state.

2

A policy selects the pod for ingress

The pod now accepts only the incoming connections that some policy allows. Egress is still open.

3

A policy selects the pod for egress

The pod may now make only the outgoing connections that some policy allows.

4

More policies are added

Allowances accumulate. A connection works if at least one policy permits it.

Everyday analogy

Imagine a hotel where every room door is unlocked by default. The first time the manager attaches a guest list to a door, that room becomes private: only people named on any list for that door may enter. Adding more lists adds more names. You can never remove a name by adding a list; you can only edit or delete the list itself.

The three ways to name “who”

Selector

Pod selector

Matches pods by labels, such as “app equals orders”. The most common and most flexible choice.

Selector

Namespace selector

Matches every pod inside namespaces carrying certain labels, such as “team equals payments”.

Selector

IP block

Matches address ranges. Best for things outside the cluster, such as an office network or an on-premises database.

Combine

Both together

A namespace selector and a pod selector in one entry means “pods with this label inside namespaces with that label”.

The enforcement catch

!
Critical warning

The Kubernetes API will happily accept NetworkPolicy objects even if your network plugin does not enforce them. Nothing warns you. A cluster can be full of policies that do absolutely nothing. Always confirm enforcement with a real test: try a connection that should be blocked, and check that it fails.

Plugins that enforce standard network policies include Calico, Cilium, and Antrea. On Amazon EKS, the AWS VPC CNI can enforce them as well when the feature is switched on. Simple plugins that only provide connectivity do not enforce them.

Typical limits of the standard object

What it does well

  • Controls connections by label, namespace, address, and port.
  • Works on every compliant plugin with the same syntax.
  • Is simple to review and store in version control.

What it cannot do

  • It has no explicit deny rules or priorities.
  • It understands only addresses and ports, not web paths or methods.
  • It cannot match by domain name for outside destinations.
  • It does not encrypt anything or prove identity.

6Designing Default-Deny Policies

The recipe for a zero-trust namespace is short: close everything first, then open only what the application truly needs. This chapter shows the pattern step by step.

Step one: the default-deny policy

A default-deny policy selects every pod in a namespace and lists no allowed connections. The result is that all ingress, and optionally all egress, is blocked for the whole namespace. Because allowances accumulate, you then add small policies that open exactly the paths you want. Most teams create two default-deny policies per namespace: one for incoming traffic and one for outgoing traffic.

Step two: do not forget DNS

This is the most common mistake. If you block all egress, pods can no longer ask cluster DNS to translate names, and every application call breaks with a confusing “name not found” message. The fix is a small policy that allows pods to send DNS queries, on port 53 over both UDP and TCP, to the cluster DNS pods in the system namespace. Add this as part of the default egress setup so that nobody ever has to debug it twice.

Step three: allow each real path

For every legitimate connection, add one small policy named after what it does. A good habit is to write each rule from the point of view of the receiving pod: “the orders API accepts connections from the web pods on port 8080”. Rules that read like plain sentences are easier to review in code reviews.

flowchart LR
  ING["Ingress gateway"] -->|"allow port 8080"| WEB["Web pods"]
  WEB -->|"allow port 9090"| API["Orders API"]
  API -->|"allow port 5432"| DB["Database"]
  API -->|"allow port 443 to payment provider"| EXT["External provider"]
  WEB -. "blocked" .-> DB
  ING -. "blocked" .-> API
    
Figure 4: A three-tier application where only the solid arrows are allowed and the crossed dotted lines are blocked

A policy catalog you can reuse

PatternWhat it doesWhen to use it
Deny all ingressBlocks every incoming connection to the namespaceEvery namespace, as the starting point
Deny all egressBlocks every outgoing connection from the namespaceEvery namespace that does not need broad internet access
Allow DNS egressLets pods resolve names through cluster DNSAlways paired with deny all egress
Allow same-namespaceLets pods in one namespace talk to each otherSmall, tightly related apps; use sparingly
Allow from gatewayAccepts traffic only from the ingress gateway namespaceFront-door web services
Allow to databaseOpens one port to one database labelApplication-to-data-store links
Allow monitoring scrapeLets the metrics system read metrics portsEvery workload that is monitored

Namespace labels make policies simple

Kubernetes automatically adds a label to every namespace that holds the namespace name. You can use it in namespace selectors to say “pods from the gateway namespace” without inventing labels yourself. For team-level rules, add your own labels, such as the owning team or the environment, and select on those.

i
Practical tip

Write down a communication map before you write a single policy: a simple table listing which service calls which, over which port. The map becomes your review checklist, your test plan, and your documentation, all in one.

Services versus pods in rules

Network policies are checked against the pods behind a Service, not the Service name. When one pod calls a Service, the packet is rewritten to a real pod address first, and the rule is evaluated against that pod. In practice this means you write rules about pod labels and ports, and the port you allow is the pod’s real container port, which may differ from the Service port. Mixing these up is a classic reason a rule appears correct but still blocks traffic.

Production example: default-deny at a digital bank

Monzo, the UK digital bank that runs a large microservice platform on Kubernetes, has spoken publicly about using network policies to control which services can talk to each other. Their approach illustrates the key idea in this chapter: with hundreds of small services, the only manageable way to limit lateral movement is to describe permitted calls once and block everything else automatically.

7Beyond Basics: Identity-Aware Network Plugins

Standard policies are a strong start, but real systems soon need more: explicit denies, domain names, and rules about web requests. Two popular network plugins add these powers.

Calico: richer policy and priorities

Calico extends the policy model with its own objects. It supports explicit allow and deny rules, rules ordered by priority, policies that apply to the whole cluster rather than one namespace, and policies that protect the machines themselves. This lets a security team set cluster-wide guardrails that application teams cannot override, such as “no pod may ever reach the cloud metadata address”.

Cilium: identity and eBPF

Cilium takes a different approach. Instead of tracking IP addresses, it gives each group of pods with the same labels a numeric security identity, and writes rules in terms of those identities. It enforces them inside the Linux kernel using a technology called eBPF, which lets small, safe programs run directly in the kernel’s packet path. Because the rules follow identities rather than addresses, they keep working correctly as pods come and go, and the checks are very fast.

Everyday analogy

An address-based rule is like a guard who memorizes people by the seat they sit in. When people change seats, he gets confused. An identity-based rule is like a guard who checks each person’s badge. It does not matter where they sit; the badge tells him who they are.

What identity-aware plugins add

Rules

Explicit deny and ordering

Cluster owners can deny first and let application teams allow within those limits.

Rules

Domain-name egress

Allow a pod to reach a named service, such as a payment provider, instead of a list of changing IP addresses.

Rules

Web-aware rules

Allow only certain HTTP methods and paths, so a pod may read orders but not delete them.

Insight

Flow visibility

Cilium’s Hubble component and Calico’s flow logs show every allowed and denied connection.

A standard emerging for cluster-wide rules

The Kubernetes networking community has been developing additional policy objects that let cluster administrators set rules above the namespace level, including baseline defaults and explicit denies. These efforts are still maturing and support differs by plugin, so check what your plugin and version support before relying on them.

Choose standard NetworkPolicy when

  • You want portability across plugins.
  • Your rules are simple allow lists.
  • Your team is new to network security.

Choose plugin-specific policies when

  • You need cluster-wide guardrails or explicit denies.
  • You need domain-name or HTTP-aware rules.
  • You can accept some lock-in to the plugin.
!
Watch the lock-in

Plugin-specific policy objects do not work if you later change the plugin. Keep your communication map in a neutral format so you can rewrite the rules if you ever migrate.

8Workload Identity: Proving Who You Are

Network rules based on addresses and labels are a good start, but labels can be edited and addresses can be spoofed in some situations. True zero trust needs identities that can be proven with cryptography.

The problem with trusting labels

A label is just a piece of text attached to a pod. Anyone with permission to create or edit pods can write any label they like. If your network rules say “allow pods labeled app equals billing”, then an attacker who can create a pod with that label can borrow the permission. Strong zero trust therefore pairs label-based rules with identities that cannot be forged.

Kubernetes service accounts

Every pod runs as a service account, which is Kubernetes’ built-in way to name a workload. Modern clusters issue each pod a short-lived, signed token tied to its service account, delivered through a mechanism called a projected volume. These tokens expire, are bound to a specific audience, and are rotated automatically by the kubelet. They are good proof of identity to the Kubernetes API server and to any system that can verify them.

i
Good habit

Give every application its own service account and turn off automatic mounting of tokens in pods that never call the Kubernetes API. A token that is never mounted can never be stolen from the pod.

SPIFFE: a universal name tag

SPIFFE stands for Secure Production Identity Framework for Everyone. It is an open standard that defines a name format for workloads, called a SPIFFE ID, which looks like a web address with the pattern spiffe://trust-domain/ns/namespace/sa/serviceaccount. It also defines how a workload receives a short-lived certificate proving it owns that name. SPIRE is the most well-known program that implements the standard. Companies such as Uber have publicly described adopting SPIFFE and SPIRE for workload identity across their systems.

flowchart TD
  P["Pod starts"] --> A["Local agent checks pod facts: namespace, service account, node"]
  A --> S["Identity server verifies the facts"]
  S --> C["Short-lived certificate issued with the workload's SPIFFE ID"]
  C --> W["Workload presents the certificate when it connects"]
  W --> R["Receiver verifies the certificate chain and the ID"]
    
Figure 5: How a pod earns a verifiable identity without anyone typing a password

Why short lifetimes matter

A stolen password works until someone notices and changes it. A stolen certificate that lives for only a day, or even an hour, becomes useless quickly. Zero-trust systems therefore issue certificates with short lifetimes and renew them automatically in the background. Service meshes typically rotate workload certificates about once a day by default, with no human involved.

Cloud identity for pods

Pods also need identities when they call cloud services such as storage buckets and queues. On Amazon EKS you can link a service account to a cloud role, so each pod receives only the permissions that role grants. This is the same least-privilege idea applied to cloud calls, and it prevents a compromised pod from using the machine’s broad permissions.

Strong identity gives you

  • Rules that follow the real workload, not a movable label.
  • Automatic rotation with no shared secrets.
  • A clear audit trail of who called whom.

Strong identity costs you

  • A certificate authority that must stay healthy.
  • More moving parts to monitor.
  • A learning curve for platform teams.

9Mutual TLS: Encrypted and Authenticated Conversations

Network rules decide who may connect. Mutual TLS decides who is really on the other end, and makes sure nobody can eavesdrop or tamper along the way.

Start with ordinary TLS

When you open a secure website, your browser uses TLS, short for Transport Layer Security. The website shows a certificate that proves its identity, and the two sides agree on secret keys to scramble the conversation. In ordinary TLS, only the server proves who it is. The browser stays anonymous.

Now make it mutual

In mutual TLS, usually written mTLS, both sides show certificates. The caller proves who it is, and the receiver proves who it is. After the handshake, the receiver knows with cryptographic certainty which workload is calling, and both know the conversation is private. This is exactly the “verify explicitly” principle applied to service-to-service traffic.

sequenceDiagram
  participant C as Client workload
  participant S as Server workload
  C->>S: Hello and request to connect
  S-->>C: Server certificate with its identity
  C->>C: Verify server certificate against trusted authority
  C->>S: Client certificate with its own identity
  S->>S: Verify client certificate and read caller identity
  C-->>S: Agree on session keys
  C->>S: Encrypted application request
  S-->>C: Encrypted response
    
Figure 6: The simplified mutual TLS handshake between two workloads
Everyday analogy

Ordinary TLS is like calling a bank and having the bank prove who it is, while you stay anonymous. Mutual TLS is like two spies meeting in a cafe who each show a special ID card to the other before saying a single word, and then speak in a private code only they share.

What mTLS gives you

Identity

Proven callers

The server learns the caller’s verified workload identity, not just an address.

Privacy

Encryption in transit

Packets crossing the network are scrambled, so snooping on the wire reveals nothing useful.

Integrity

Tamper detection

Any change to the data in transit is detected and rejected.

Policy

A base for authorization

Rules like “only billing may call payments” become reliable because identity is proven.

The problem mTLS creates

Asking every application team to add certificate handling to every program would be slow, error-prone, and different in every language. Certificates must be requested, renewed, and checked correctly everywhere. This is the reason most organizations hand the job to a shared layer. That layer is a service mesh, or increasingly, the network plugin itself.

Production example: encrypting everything between services

Google’s production network encrypts and authenticates calls between its own services using an internal system, as described in the BeyondProd paper. The lesson for Kubernetes teams is that service-to-service encryption is treated as a baseline platform feature, not something each application team builds on its own.

10Service Meshes: mTLS Without Changing Your Code

A service mesh is a layer of infrastructure that handles secure communication for every service, so developers can focus on business logic.

What a mesh actually is

A service mesh places a small network proxy next to each workload. All traffic into and out of the workload passes through its proxy. The proxies together form the data plane, which does the real work of encrypting, checking identity, and applying rules. A separate set of components called the control plane hands out certificates and distributes policy to the proxies.

flowchart LR
  subgraph PodA["Pod A"]
    AppA["App container"] --- PxA["Proxy"]
  end
  subgraph PodB["Pod B"]
    PxB["Proxy"] --- AppB["App container"]
  end
  PxA == "mutual TLS" ==> PxB
  CP["Mesh control plane: certificates and policy"] -.-> PxA
  CP -.-> PxB
    
Figure 7: Proxies beside each workload create encrypted tunnels while the control plane manages identity and rules

Meet the popular meshes

MeshApproachNotable traits
IstioEnvoy proxies, with a newer sidecar-free ambient modeVery feature-rich; powerful authorization policies; more to learn and operate
LinkerdLightweight purpose-built proxySimple to start; mTLS enabled automatically for meshed workloads
Cilium service mesheBPF in the kernel with optional shared proxiesFewer extra containers; one tool for networking and mesh
Cloud-managed optionsProvider-run control planes or latticesLess operating work; tied to a cloud vendor

Sidecars and the new sidecar-free designs

The original mesh design puts one proxy container, called a sidecar, inside every pod. It works well but uses extra memory and CPU in every pod and adds some startup complexity. Newer designs move the work out of the pod. Istio’s ambient mode uses a small shared agent on each node to handle encryption and identity, and adds optional shared proxies only for workloads that need request-level rules. Cilium uses the kernel itself. These designs reduce overhead, though they are younger, so evaluate their maturity for your version.

Sidecar model

  • Mature and widely deployed.
  • Strong isolation: each pod has its own proxy.
  • Uses extra resources in every pod.

Sidecar-free model

  • Lower resource cost per pod.
  • Fewer pod restarts when upgrading the mesh.
  • Newer, with fewer years of production history.

Permissive and strict modes

You cannot flip a whole cluster to encrypted-only in one night. Meshes therefore offer a permissive mode, in which a service accepts both encrypted and plain connections, and a strict mode, in which only authenticated mTLS connections are accepted. The usual path is to start permissive, watch which callers are still using plain traffic, fix them, and then switch to strict one namespace at a time.

!
Do not stay permissive forever

Permissive mode is a migration tool, not a destination. A namespace that is permissive still accepts plain connections from an attacker, so it provides little zero-trust value until it is switched to strict.

Production example: Lyft and Envoy

Lyft built the Envoy proxy to handle reliable and observable communication between its many services, and then released it as open source. Envoy later became the data plane for Istio and many other systems, which is why so many meshes share similar concepts and features.

11Request-Level Authorization

Once identity is proven, you can write rules far more precise than “this pod may connect to that pod”. You can say which identity may perform which action.

From connections to requests

A network rule says “the web pods may reach the orders API on port 8080”. An authorization rule says “the web workload may read orders, but only the billing workload may create refunds”. The second rule needs a component that understands web requests, namely the mesh proxy or a gateway. It can examine the caller’s identity, the HTTP method, the request path, and even specific headers before deciding.

1

Connection arrives

The proxy completes the mTLS handshake and learns the caller’s verified identity.

2

Request is read

The proxy reads the method and path, such as a request to read an order or to issue a refund.

3

Policy is evaluated

The proxy checks deny rules first, then allow rules, against identity, method, and path.

4

Decision is applied

The request is passed to the application, or rejected immediately and logged.

Example rule ideas, in words

Allow

Read-only for the website

The web workload may use read methods on the orders service, and nothing else.

Allow

Refunds only from billing

Only the billing workload identity may call the refund path.

Deny

Admin paths from everyone else

Any caller other than the admin tool is rejected on administrative paths.

Default

Nothing unless named

When any allow rule exists on a service, requests that match no allow rule are rejected.

End users, not only services

Zero trust also covers the human on the other side of the request. A common pattern is for the user to log in through an identity provider and receive a signed token, often a JSON Web Token. The mesh or gateway can validate the token’s signature, check its expiry and audience, and pass the verified claims to the application. Combined with workload identity, the service sees both which service is calling and which person it is acting for.

Everyday analogy

Imagine a hospital. A nurse badge (workload identity) opens the ward door. But to open a specific patient’s file, the system also checks the doctor’s signed order (user token). Two proofs, two different questions, both required.

i
Layer them

Use network policies for coarse blocking, mTLS for identity, and request-level rules for fine control. If the proxy fails or is bypassed, the network rules still stand. If a network rule is too broad, the request-level rule still protects the sensitive path.

Benefits of request-level rules

  • Very precise control over what each caller may do.
  • Rules read like business policy.
  • Rejected calls are logged with identity and reason.

Costs to plan for

  • Rules must be kept up to date as APIs evolve.
  • Debugging a rejected call needs good tooling.
  • Applications should still check permissions themselves.

12Controlling the Front Door: North-South Traffic

The edge of the cluster is where the outside world meets your workloads. Zero trust treats this boundary with extra care, but it does not stop there.

Ingress and the Gateway API

An ingress controller or a gateway receives traffic from outside and routes it to the right Service. Kubernetes has two ways to describe such routes. The older Ingress object is simple and widely supported. The newer Gateway API is more expressive and separates responsibilities: infrastructure teams own the gateway itself, while application teams own the routes attached to it. This separation fits zero trust well, because it limits who can expose what.

What the edge should do

1

Terminate and re-establish TLS

Decrypt customer traffic at the edge, then re-encrypt it toward the backend so the inside is not left plain.

2

Authenticate users

Check tokens or sessions before the request ever reaches an application.

3

Filter and rate-limit

Use a web application firewall and rate limits to block common attacks and abusive clients.

4

Route only what is published

Expose only the specific paths and services you intend. Everything else returns an error.

Do not let the gateway become a trust shortcut

A common mistake is to treat everything arriving from the gateway as automatically trusted. In a zero-trust design, the gateway is just another workload with its own identity. The backend still authenticates it, still checks the user’s token, and still applies request-level rules. The gateway is allowed to talk only to the services it truly fronts, not to the entire cluster.

!
Common trap

Giving the ingress controller broad network access to every namespace “so routing just works” turns it into a perfect stepping stone. A single flaw in the gateway then exposes everything. Restrict it with network policies like any other workload.

Cloud load balancers and the layers behind them

On a cloud such as AWS, a managed load balancer usually sits in front of the gateway. It adds its own protections: network access rules, optional web application firewall, and managed certificates. These cloud features complement the in-cluster rules and form the outer layers of the stack.

flowchart LR
  USER["Customer"] --> WAF["Cloud firewall and load balancer"]
  WAF --> GW["Gateway with its own identity"]
  GW -->|"mTLS and token check"| SVC["Backend service"]
  SVC -->|"mTLS and identity rule"| DATA["Data service"]
    
Figure 8: Every hop re-checks identity; none of them trusts the previous hop blindly

Production example: layered edges at large retailers

Large e-commerce sites commonly place a content delivery network and a web application firewall in front of their load balancers, then terminate and re-encrypt at the gateway, and then use a mesh for internal calls. A request may be inspected and authenticated at four separate points before it reaches a database, which is exactly the repeated verification that zero trust demands.

13Egress Control: Stopping Data from Leaving

Most teams worry about attackers getting in. Zero trust also worries about what gets out. Outgoing traffic is how stolen data leaves, and how a captured pod calls home to its master.

Why egress is often wide open

Developers want their pods to download packages, call partner APIs, and reach cloud services. Locking this down feels like friction, so most clusters allow all outgoing traffic. That means an attacker who compromises one pod can download hacking tools, contact a remote control server, and upload your customer data to any address on the internet, with no resistance.

The layers of egress control

Layer 1

Default-deny egress

Block all outgoing traffic per namespace, then allow only DNS and the specific destinations needed.

Layer 2

Name-based allow lists

Where the plugin supports it, allow a pod to reach a named external service rather than a list of changing addresses.

Layer 3

Egress gateway

Route all outside calls through a small set of controlled nodes, so one fixed address and one inspection point exist.

Layer 4

Cloud network rules

Use virtual-network firewalls and private endpoints to restrict which destinations are reachable at all.

The egress gateway pattern

An egress gateway is a dedicated workload through which all traffic to the outside must pass. It gives you one place to log, inspect, and allow destinations. It also lets your partners allow-list a single stable address for your whole cluster. Applications cannot reach the internet except through it, because network policies block every other route.

flowchart LR
  APP["Application pods"] -->|"allowed"| EG["Egress gateway"]
  APP -. "direct internet blocked" .-> NET["Internet"]
  EG -->|"approved destinations only"| PART["Partner API"]
  EG --> LOG["Central logs and alerts"]
    
Figure 9: All outside calls pass through one controlled and logged exit

DNS as a hidden exit

Even when ordinary connections are blocked, attackers have been known to hide stolen data inside DNS queries, because DNS is almost always allowed. To limit this, make sure pods use only the cluster DNS service rather than public resolvers, and monitor for unusual volumes of strange-looking name lookups.

Everyday analogy

A company can have perfect front-door security and still lose secrets if every employee can walk out carrying documents. A mailroom that inspects and logs all outgoing packages is the egress gateway: one controlled exit instead of a hundred unwatched windows.

i
Practical tip

Start egress control with the workloads that handle the most sensitive data, such as payment and identity services. They usually call very few external destinations, so the rules are short and the security gain is large.

Production example: regulated industries

Financial and healthcare companies that run Kubernetes under strict regulation commonly require every outbound destination to be approved and logged. They often combine namespace-level egress rules, a central egress gateway, and cloud firewall rules, so that no single misconfiguration can open a path to the internet.

14Guarding the Control Plane and the Nodes

The most valuable targets in a cluster are not your applications. They are the Kubernetes control plane and the machines running your pods. Zero-trust networking must protect both.

The API server

The API server is the front door to the entire cluster. Anyone who can talk to it with enough permissions can create pods, read secrets, and change rules. Zero trust applies in three ways. First, limit who can reach it at the network level: keep the endpoint private where possible, or restrict it to approved address ranges. Second, require strong authentication for every caller. Third, use fine-grained role-based access control so that each person and program has only the permissions it needs.

The kubelet

Every node runs an agent called the kubelet, which has its own network port. If that port accepts unauthenticated requests, an attacker who reaches it can run commands in pods. Modern, hardened clusters turn off anonymous access to the kubelet and require the API server to authenticate to it. Managed services configure this securely, but self-managed clusters need a deliberate check.

The data store

Cluster state, including secrets, lives in a data store called etcd. It should accept connections only from the API server, require mutual TLS, and encrypt sensitive data at rest. On managed services the provider handles this for you.

ComponentWhat attackers wantZero-trust protection
API serverCluster-wide controlPrivate or restricted endpoint, strong authentication, least-privilege access control
KubeletCommand execution on a nodeNo anonymous access, authenticated and authorized requests only
etcdEvery secret in the clusterOnly the API server may connect, mutual TLS, encryption at rest
Node metadata endpointCloud credentials of the machineBlock from pods, require session-protected access
Container runtime socketControl of all containers on the nodeNever mount it into ordinary pods

Pods that call the API server

Some pods, such as controllers and operators, must talk to the API server. Treat them as high-value targets. Give each its own service account with narrow permissions, and use network policies to confirm that only those pods can reach the API server address at all. Most ordinary applications never need to call it, so blocking them closes a major path.

!
Privileged pods break the model

A pod that runs in privileged mode, shares the host network, or mounts the host filesystem can bypass many network and identity controls. Use pod security standards to forbid these settings in normal namespaces and allow them only for carefully reviewed system components.

Production example: public exposure incidents

Security researchers have repeatedly found real clusters whose management dashboards or kubelet ports were reachable from the internet without authentication, leading to attackers installing cryptocurrency miners. These cases are widely reported and share one cause: a management interface trusted its network location. Zero trust removes that assumption.

15Certificates, Authorities, and Rotation

Everything cryptographic in zero trust rests on a chain of trust that begins with a certificate authority. If that foundation is shaky, the whole structure is.

What a certificate authority does

A certificate authority, or CA, is the trusted party that signs certificates. When a workload presents a certificate, the receiver checks whether it was signed by a CA that it trusts. If yes, the identity inside is believed. If the CA is compromised, an attacker can mint a certificate for any identity, so protecting the CA is the single most important job in the system.

A sensible hierarchy

flowchart TD
  ROOT["Root CA: kept offline and heavily protected"] --> INT["Intermediate CA: used by the cluster"]
  INT --> W1["Workload certificate: orders service"]
  INT --> W2["Workload certificate: billing service"]
  INT --> W3["Workload certificate: gateway"]
    
Figure 10: A root authority that stays offline, and a working authority that signs short-lived certificates

Good practice keeps the root authority offline and uses an intermediate authority for day-to-day signing. If the intermediate is ever compromised, you replace it without having to rebuild trust from scratch. Meshes and identity systems can be set up to use an intermediate issued by your organization’s own root, which lets workload identities connect cleanly to the rest of your company’s trust system.

Automating certificates

Certificates for human-facing websites are usually handled by a Kubernetes add-on called cert-manager, which requests, renews, and installs certificates automatically from public or private authorities. Certificates for workload-to-workload mTLS are typically handled by the mesh or identity system itself. The goal in both cases is the same: no human ever copies a certificate by hand, and nothing expires unnoticed.

1

Issue

A workload proves its facts and receives a certificate that lives for hours or a day.

2

Renew

Well before expiry, the agent quietly requests a fresh certificate and swaps it in without dropping connections.

3

Revoke or expire

If a workload is compromised, short lifetimes mean its certificate soon dies on its own, and emergency steps can cut it off sooner.

4

Audit

Issuance logs record which identity received what and when, for later investigation.

!
The classic outage

An expired certificate is one of the most common causes of surprise outages in encrypted systems. If automatic renewal silently fails, every connection starts failing at the same moment. Monitor remaining certificate lifetime and alert long before it reaches zero.

Secrets are part of the network story

Database passwords, API keys, and tokens are credentials that grant network access. Keep them out of container images and plain configuration files. Use a dedicated secret store with access control and audit logging, and prefer short-lived credentials over long-lived ones. Where possible, replace passwords with identity-based access so there is nothing to steal at all.

16The Cloud Layer: Zero Trust on Amazon EKS

Your cluster sits inside a cloud network, and the cloud has its own firewalls and identities. The strongest designs make the cloud layer and the Kubernetes layer agree with each other.

Network policy on the VPC CNI

The AWS VPC CNI assigns pods addresses from your virtual network, and recent versions can enforce standard Kubernetes network policies directly. This means the same policy objects you write for any cluster can control pod traffic on EKS once you enable the feature. As always, confirm enforcement with a real test, and check which policy features your version supports.

Security groups for pods

AWS lets you attach a cloud security group to individual pods on supported machine types. This gives a pod the same kind of firewall rule as any other cloud resource. A typical use is letting only the orders pods reach the database service, with the database security group itself referring to the pod security group. It provides a second, independent barrier outside Kubernetes, which is valuable if someone misconfigures a Kubernetes policy.

Blocking the metadata service

Every cloud machine has a special internal address, called the instance metadata service, that hands out information about the machine, including temporary credentials for the machine’s role. If a pod can reach it, an attacker who takes over the pod may steal those credentials and gain the machine’s broad cloud permissions. On AWS, require the session-based version of the service, known as IMDSv2, and set its hop limit to one so that pod traffic cannot reach it. Also use per-pod roles so pods never need the machine’s role at all.

!
A well-known breach pattern

Several public cloud breaches have started with an attacker tricking an application into making a request to the metadata address, stealing credentials, and then using them to read storage. Blocking pods from the metadata service and moving to per-pod roles closes this path.

Pod-level cloud identities

With per-pod roles

  • Each workload receives only the cloud permissions it needs.
  • Credentials are short-lived and delivered securely.
  • A compromised pod reaches only its own resources.

Without per-pod roles

  • Every pod on a node can use the node’s role.
  • One flaw exposes storage, queues, and databases.
  • Audit logs cannot tell workloads apart.

Private connections to cloud services

Instead of sending traffic to cloud services over the public internet, use private endpoints that keep traffic on the provider’s internal network. Combine them with endpoint policies that state which buckets, tables, or queues may be reached from your network. This turns “can this pod reach the service” into a decision made in two places: Kubernetes and the cloud.

Choosing a mesh on AWS

AWS has announced the retirement of its older managed mesh product, App Mesh, so new designs generally choose an open-source mesh such as Istio or Linkerd, a network-plugin approach such as Cilium, or a service-networking offering from AWS called VPC Lattice. Verify the current status of any managed product before committing to it.

ControlWhere it livesWhat it protects
Network policyInside KubernetesPod-to-pod and pod-to-outside connections
Security group for podsCloud networkPod access to cloud resources and databases
Metadata protectionCloud machine settingsMachine credentials
Per-pod rolesCloud identity systemAccess to storage, queues, and other services
Private endpointsCloud networkPaths between the cluster and cloud services

17Seeing Everything: Observability and Detection

A rule that you cannot test or observe is only a hope. Zero trust includes continuous watching, so that failures and attacks become visible quickly.

Three sources of truth

Network

Flow logs

Records of which workload connected to which, allowed or denied. Produced by the network plugin and the cloud network.

Mesh

Request telemetry

Per-request metrics and traces showing callers, targets, status codes, and delays.

Control

Audit logs

The API server’s record of who changed which policy, role, or secret, and when.

Runtime

Behavior alerts

Tools that watch what processes do inside containers and flag odd behavior, such as a web server starting a shell.

What to look for

1

Unexpected denials

A burst of blocked connections from one pod may mean it has been compromised and is probing the network.

2

New communication paths

A service that suddenly talks to something it never has before deserves a question.

3

Plain traffic in strict areas

Any unencrypted connection in a namespace that should be strict signals a misconfiguration or an attack.

4

Policy changes

Edits to network policies or mesh rules outside the normal change process should alert someone.

5

Unusual egress volume

A sudden jump in outbound data from a database-adjacent pod is a classic sign of data theft.

Discovery before enforcement

Observability has a second, practical use: it tells you what rules to write. Run in an observing mode for a few weeks, collect the flows that really occur, and turn them into the first draft of your policies. Tools exist that read flow data and propose network policies automatically. Always review their suggestions by hand, since they will happily approve a connection that was itself a mistake.

i
Make denials explain themselves

When a connection is blocked, engineers need to know which rule did it. Choose tools that report the matching policy in their logs, and train the on-call team to read those logs first. This single habit removes most of the fear around enforcing strict rules.

Production example: using flow visibility to plan

Teams that adopt Cilium commonly use its Hubble component, and teams that adopt Calico use its flow logs, to see which services really talk to each other before enforcing rules. This turns the hardest part of zero trust, knowing what traffic is legitimate, from guesswork into evidence.

18Rolling It Out Without Breaking Production

The biggest risk of zero trust is not the attacker. It is the well-meaning engineer who turns on strict rules on a Friday afternoon and takes down checkout. A careful rollout plan avoids that.

The phased path

1

Inventory and map

List the services, their owners, and who calls whom. Use flow data to fill in what documentation forgot.

2

Choose enforcement tools

Confirm your network plugin enforces policies, and decide whether you need a mesh now or later.

3

Start with low-risk namespaces

Pilot on a test or internal-tools namespace, so mistakes teach lessons without hurting customers.

4

Observe, then enforce

Run in permissive or audit mode, review what would be blocked, fix the gaps, and only then switch to strict.

5

Expand by sensitivity

Move on to namespaces that hold the most sensitive data first, since they gain the most from protection.

6

Make it the default

Bake default-deny and identity into the template used to create every new namespace.

Manage policy as code

Treat every network policy, mesh rule, and authorization policy as source code. Store it in version control, review it like any other change, test it, and deploy it through an automated pipeline. This approach is often called GitOps. It gives you history, rollback, and a clear answer to the question “who allowed this and why”.

Test the rules, not just the application

Add automated checks that prove the policies work. A good test suite includes both positive checks, confirming that required connections succeed, and negative checks, confirming that forbidden connections fail. Run them after every policy change and on a schedule, because drift and plugin upgrades can quietly change behavior.

Good rollout habits

  • Change one namespace at a time.
  • Keep a quick rollback ready for every step.
  • Tell application teams before and after.
  • Write runbooks for the most likely failures.

Rollout mistakes

  • Enforcing cluster-wide in a single change.
  • Skipping the observation phase.
  • Leaving temporary exceptions in place forever.
  • Giving no one clear ownership of policies.
i
Make the secure path the easy path

Provide teams with ready-made policy templates and a simple request process for new connections. When opening a legitimate connection takes ten minutes instead of ten days, people stop looking for ways around the controls.

19Worked Example: Securing an Online Store

Let us apply everything to one imaginary application, step by step, and watch the open cluster turn into a zero-trust one.

The application

An online store runs in a cluster with five parts. A web service serves the shop pages. An orders service manages carts and orders. A payments service charges cards through an outside provider. A catalog service holds product data. A database stores orders. An ingress gateway receives all customer traffic, and a monitoring system scrapes metrics from every service.

Step one: draw the communication map

FromToWhy
GatewayWebCustomers load pages
WebOrdersPlace and view orders
WebCatalogShow products
OrdersPaymentsCharge a card
OrdersDatabaseStore orders
PaymentsOutside providerProcess the payment
MonitoringAll servicesCollect metrics

Step two: close everything

Create a default-deny policy for both ingress and egress in the store namespace. Add the DNS allowance so names still resolve. At this moment nothing works, which is exactly the safe starting point.

Step three: open each mapped path

Add one small policy for each row of the table. For example, the orders service accepts connections only from the web workload, and the database accepts connections only from orders. The web service has no path to the database or payments at all, so even a fully compromised web pod cannot reach them.

Step four: add identity and encryption

Enable the mesh in the namespace and move from permissive to strict mode. Now every connection in the table is encrypted and authenticated, and each service knows the verified identity of its caller.

Step five: add request-level rules

On the payments service, allow only the orders identity to call the charge path, and nobody to call administrative paths. On the orders service, allow the web identity to read and create orders, but not delete them.

Step six: control the exit

Allow the payments pods to reach only the payment provider’s name through the egress gateway. Every other pod in the namespace has no route to the internet, apart from DNS.

flowchart TD
  CUST["Customers"] --> GW["Gateway"]
  GW -->|"mTLS, port 8080"| WEB["Web"]
  WEB -->|"mTLS, read and create only"| ORD["Orders"]
  WEB -->|"mTLS, read only"| CAT["Catalog"]
  ORD -->|"mTLS, charge path only"| PAY["Payments"]
  ORD -->|"mTLS, port 5432"| DB["Database"]
  PAY -->|"via egress gateway"| EXT["Payment provider"]
  MON["Monitoring"] -.->|"metrics port only"| WEB
  MON -.-> ORD
  MON -.-> PAY
    
Figure 11: The finished design, where each arrow is a named, encrypted, and limited connection

The result in numbers

7
approved connection types, down from every possible pair
100%
of internal traffic encrypted and authenticated
1
controlled exit to the internet
i
What changed for an attacker

Before, taking over the web pod opened the door to the database, the payment keys, and the internet. After, the same takeover yields a pod that can speak only to two services, in limited ways, with every attempt logged. The attacker has gone from owning the building to holding a single room key.

20An Attack, With and Without Zero Trust

Theory feels abstract until you watch a realistic attack play out twice: once against an open cluster, once against a zero-trust one.

The attack begins

An attacker finds a flaw in a library used by the web service and gains the ability to run commands inside one web pod. This is the starting point in both stories.

Story one: the flat cluster

1

Scan

The attacker scans the pod network and finds the database, the orders service, and the monitoring tools, all reachable.

2

Steal credentials

The attacker reaches the cloud metadata address and obtains the machine’s temporary credentials.

3

Read data

The attacker connects to the database directly, or uses the credentials to read cloud storage.

4

Exfiltrate

Data is uploaded to a server on the internet. Nothing blocks it, and nobody is told.

Story two: the zero-trust cluster

1

Scan fails

Default-deny blocks connections to everything except the two approved services. The scan produces a burst of denials that an alert notices.

2

Metadata blocked

The metadata address is unreachable from pods, and pods use per-pod roles, so there are no machine credentials to steal.

3

Limited calls only

The attacker can still call the orders service as the web identity, but request-level rules allow only read and create, and every call is logged.

4

Exit closed

No route to the internet exists from the web pod. Stolen data has nowhere to go.

5

Detection and response

The alert team isolates the pod, rotates its identity, and patches the library, long before real damage is done.

Side-by-side comparison

Flat cluster outcome

  • Database accessed directly.
  • Cloud credentials stolen.
  • Data leaves unnoticed.
  • Discovered weeks later, if at all.

Zero-trust outcome

  • Reach limited to two approved services.
  • No credentials available to steal.
  • No exit route for data.
  • Alerts fire within minutes.
Zero trust does not promise that attackers never get in. It promises that getting in is not enough.

21Costs, Performance, and Trade-offs

Zero trust is powerful, but it is not free. Understanding the costs lets you spend wisely and answer honestly when someone asks “is it worth it”.

Performance overhead

Encrypting every connection and checking identity takes a little time. Modern processors perform encryption very quickly, and long-lived connections pay the handshake cost only once. In practice, the added delay per call is usually small compared to the time applications spend doing their own work, but the effect grows with the number of hops in a request. A request that passes through ten services pays the overhead ten times. Measure with your own traffic before and after, rather than trusting a published number.

Resource overhead

Sidecar proxies consume memory and CPU in every pod. With hundreds of pods, this adds up to real money. Sidecar-free designs lower this cost, as do shared agents per node. Include proxy resources when you size pods, and remember that a proxy without enough CPU becomes a source of latency.

Operational complexity

A mesh and an identity system are two more large systems to upgrade, monitor, and debug. When a call fails, the cause might now be an application bug, a network policy, a certificate problem, or a mesh rule. Teams need good tooling and training to find it fast. Without them, engineers lose trust in the platform and ask for exceptions.

CostWhat it looks likeHow to reduce it
LatencySmall added delay per hopReuse connections, keep call chains short, measure regularly
ComputeProxy memory and CPU in every podRight-size proxies, consider sidecar-free modes
ComplexityMore layers to debugStrong observability, runbooks, training
Failure modesExpired certificates, control-plane outagesAutomatic renewal, alerts, tested recovery plans
People timePolicy writing and reviewsTemplates, automation, self-service requests

What happens when the control plane fails?

A key design question is how the data plane behaves if the mesh control plane or certificate system becomes unavailable. A well-designed system keeps existing connections and cached policies working for a while, and certificate lifetimes are long enough to ride out brief outages. But if the outage outlasts those lifetimes, new certificates cannot be issued and connections start to fail. Plan for this by running the control plane in several zones, by testing failure drills, and by choosing certificate lifetimes that balance security against survivability.

!
Security versus availability

Shorter certificate lifetimes improve security but make the system depend more on the issuing service staying healthy. There is no universal best number. Pick a lifetime that your recovery drills show you can survive.

Is it worth it?

For a small internal tool with no sensitive data, perhaps a lighter setup is enough: default-deny policies and a locked-down egress. For systems that handle money, personal data, or regulated information, the answer is almost always yes, because the cost of one serious breach far exceeds the cost of running these controls. A sensible compromise is to apply the full stack to the most sensitive namespaces first and keep the baseline everywhere.

22Beyond Web Traffic: Databases, Queues, and Other Protocols

Most zero-trust examples show web requests. Real systems also move data through databases, message queues, caches, and custom protocols. These need slightly different handling.

Not everything speaks HTTP

A web request has a method and a path, which makes request-level rules easy to write. A database connection or a message queue speaks its own language. A mesh proxy can still encrypt and authenticate these connections as plain streams of data, which is called opaque TCP handling, but it cannot read inside them to say “this user may read this table”. For that kind of rule, you rely on the data service’s own permissions.

Traffic typeWhat the mesh or plugin can doWhat must come from elsewhere
HTTP and gRPCEncrypt, authenticate, allow by method and pathBusiness-level permissions in the application
Database connectionsEncrypt, authenticate the calling workload, restrict by portTable and row permissions inside the database
Message queuesEncrypt, authenticate the connecting workloadTopic-level permissions from the broker
CachesEncrypt and restrict who may connectPasswords or access lists from the cache itself
Custom TCP or UDPNetwork rules by identity and portApplication-level checks

Two layers of protection for data stores

Treat every database and queue as protected twice. The first layer is the network and identity layer: only the approved workloads can even open a connection, and the connection is encrypted. The second layer is the data service’s own login and permissions. If either layer is misconfigured, the other still holds. Never rely on “only internal apps can reach it” as the only protection for a data store.

Everyday analogy

A vault sits behind a guarded corridor, and the vault has its own combination lock. The guard decides who may walk down the corridor. The lock decides who may open the vault. A thief who slips past the guard still cannot open the door, and a thief who knows the combination still cannot get down the corridor.

Stateful applications and stable names

Databases and brokers often run as StatefulSets, where each pod has a stable name and its own storage. Pods inside such a cluster talk to each other directly, for example to copy data between replicas. Zero-trust rules must therefore allow replica-to-replica traffic on the replication ports, and block everything else. Write these rules by label, so that a new replica automatically gains the same access.

Protocol quirks to watch

Detection

Protocol sniffing

Meshes often guess the protocol by looking at the first bytes. Some protocols, where the server speaks first, can confuse this, so declare the protocol explicitly on the Service port.

Startup

Proxy readiness

If the application starts before its proxy is ready, early connections may fail. Configure the mesh to hold the application until the proxy is up.

Jobs

Short-lived pods

Batch jobs must be able to stop cleanly even though a sidecar proxy is still running. Check how your mesh handles job completion.

Native TLS

Data stores with their own TLS

Many databases support TLS and client certificates directly. This can replace or complement mesh encryption, at the cost of managing certificates for each store.

i
Practical tip

For the most sensitive data stores, use both mesh-level mutual TLS and the data store’s own authentication. The overlap is deliberate. It is the zero-trust version of wearing both a belt and suspenders.

Production example: payment data environments

Payment card standards require organizations to segment systems that hold card data from the rest of the network and to encrypt that data in transit across open networks. Companies that process cards on Kubernetes typically give the card-handling namespace its own default-deny rules, its own egress controls, and mandatory encrypted connections, so an auditor can see a clear boundary around the sensitive systems.

23Many Clusters, One Trust Model

Large organizations rarely run just one cluster. They run several for different regions, teams, and environments. Zero trust must work across all of them without becoming a tangle.

Why multiple clusters exist

Teams create several clusters to place workloads close to customers, to survive the loss of an entire region, to separate production from testing, or to give sensitive workloads their own boundary. Each cluster has its own control plane, its own network, and its own certificate authority unless you design otherwise.

Two ways to build trust across clusters

Shared root of trust

  • All clusters use intermediate authorities signed by one organization root.
  • Workloads in different clusters can verify each other directly.
  • Simple model, but the root must be guarded extremely well.

Federated trust domains

  • Each cluster keeps its own authority and trust domain name.
  • Clusters exchange and trust each other’s public keys.
  • More flexible, with more moving parts to manage.
flowchart TD
  ROOT["Organization root CA, kept offline"] --> ICA["Intermediate CA for cluster A"]
  ROOT --> ICB["Intermediate CA for cluster B"]
  ICA --> WA["Workloads in cluster A"]
  ICB --> WB["Workloads in cluster B"]
  WA |"mTLS through gateways"| WB
    
Figure 12: Two clusters sharing one root of trust so their workloads can verify each other

Connecting the networks safely

Clusters can be connected in several ways. Some meshes provide gateways that carry encrypted traffic between clusters over the internet or private links. Some network plugins offer a built-in multi-cluster feature that gives workloads in different clusters a shared view of identities. Whichever you choose, the same rules apply: the link must be encrypted, each side must authenticate the other, and the policies must still describe which workload may call which, even across the cluster boundary.

!
Blast radius grows with connections

Every link between clusters is a new path for an attacker. Do not connect clusters just because you can. Connect only the services that truly need to talk, and keep a separate, tighter policy for traffic crossing the boundary.

Hybrid and on-premises systems

Many companies still run older systems outside Kubernetes, such as legacy databases or mainframes. Zero trust treats these exactly like any other workload: they get identities where possible, their connections are limited to what is needed, and the traffic between them and the cluster is encrypted and logged. Where the older system cannot do mutual TLS, place a small proxy in front of it that does the work on its behalf.

1

Decide the trust layout

Choose a shared root or federated domains before you build the second cluster, not after.

2

Connect through controlled gateways

Use dedicated, monitored entry points between clusters rather than opening whole networks to each other.

3

Write cross-cluster rules by identity

Name the exact workloads that may cross, not entire clusters.

4

Test failure scenarios

Practice what happens when the link, a gateway, or one cluster’s authority is lost.

Production example: regional failover

Global services that must keep running when a whole region fails commonly run mirrored clusters in several regions. Their meshes and network plugins use shared trust and cross-cluster gateways so that a service in one region can fail over to a copy in another, while the same identity rules still decide who may call what.

24Proving It to Auditors: Compliance and Governance

Security that you cannot demonstrate is hard to defend. Zero trust gives you both stronger protection and clearer evidence for the people who check your work.

What auditors usually ask

Whatever the regulation, auditors tend to ask the same few questions. Is sensitive data separated from everything else? Is data encrypted while traveling across the network? Who can access the system, and is each access recorded? Can you prove the rules are the ones you say they are? Zero-trust controls map directly onto these questions.

Auditor’s questionZero-trust controlEvidence you can show
Is sensitive data segmented?Default-deny network policy per namespacePolicy files in version control and passing negative tests
Is data encrypted in transit?Strict mutual TLSMesh configuration and reports showing zero plain connections
Who can access what?Workload identity and authorization rulesRule definitions and per-request logs
Are changes controlled?Policy as code with reviewPull request history and approvals
Can you detect misuse?Flow logs, audit logs, alertsRetained logs and alert records
Is outbound traffic controlled?Egress rules and gatewayApproved destination list and gateway logs

Standards and benchmarks that help

Reference

NIST zero-trust architecture

A formal description of zero-trust components and principles, useful for design documents and board-level explanations.

Benchmark

CIS Kubernetes Benchmark

A checklist of recommended settings for the control plane, nodes, and policies, with tools that scan against it.

Framework

Payment, health, and service standards

Common compliance programs require segmentation, encryption, access control, and logging, all of which this post covers.

Guidance

Kubernetes hardening guides

Government and vendor guides describe network separation and strong authentication as core hardening steps.

Continuous compliance

Instead of preparing for audits once a year, automate the checks. Run scanners that compare your live cluster to your benchmark every day. Fail deployments that would create a namespace without default-deny rules, using admission controls that reject non-compliant objects. Keep logs for as long as your regulations require. When the auditor arrives, you simply hand over the reports that already exist.

flowchart LR
  GIT["Policy in version control"] --> CI["Automated tests"]
  CI --> ADM["Admission control blocks non-compliant objects"]
  ADM --> LIVE["Live cluster"]
  LIVE --> SCAN["Daily compliance scans"]
  SCAN --> REP["Reports and alerts for auditors and teams"]
    
Figure 13: A pipeline that turns zero-trust rules into continuously proven compliance
i
Compliance is not security

Passing an audit proves you met a checklist on a given day. It does not prove you are safe tomorrow. Use compliance evidence as a by-product of strong engineering, never as the goal itself.

Production example: admission policies as guardrails

Many platform teams use policy engines in the cluster’s admission step to enforce rules such as “every namespace must have a default-deny policy” and “no pod may use the host network”. New objects that break the rules are rejected before they ever run, which turns written security standards into automatic guardrails.

25Common Mistakes and Anti-Patterns

Teams adopting zero trust tend to stumble in the same places. Learn these ahead of time and save months of rework.

ANTI-PATTERN 01 · POLICIES THAT ARE NOT ENFORCEDAvoid
What people do

They write network policies on a cluster whose network plugin does not enforce them.

Why it hurts

The cluster looks secure on paper and is completely open in reality. Auditors may even sign off on the paper.

Better approach

Verify enforcement with automated negative tests that try forbidden connections and expect failure.

ANTI-PATTERN 02 · TRUSTING LABELS ALONEAvoid
What people do

They allow traffic based only on pod labels, while many people can create pods with any label.

Why it hurts

An attacker who can create a pod can copy a trusted label and inherit its access.

Better approach

Pair labels with verified workload identity, and restrict who may create pods in sensitive namespaces.

ANTI-PATTERN 03 · FORGETTING DNSAvoid
What people do

They block all egress without allowing cluster DNS.

Why it hurts

Every service call fails with name errors, panic follows, and the policy is rolled back and never retried.

Better approach

Include the DNS allowance in the standard namespace template from the very beginning.

ANTI-PATTERN 04 · PERMISSIVE FOREVERAvoid
What people do

They enable the mesh in permissive mode during migration and never switch to strict.

Why it hurts

Plain connections are still accepted, so an attacker can skip encryption and identity entirely.

Better approach

Set a deadline for each namespace, watch for remaining plain traffic, and enforce strict mode.

ANTI-PATTERN 05 · TRUSTED GATEWAYAvoid
What people do

They allow the ingress gateway to reach every namespace and treat its traffic as pre-approved.

Why it hurts

One flaw in the gateway becomes access to the whole cluster.

Better approach

Treat the gateway as an ordinary workload with a narrow list of destinations and its own identity checks.

ANTI-PATTERN 06 · IGNORING EGRESS AND METADATAAvoid
What people do

They carefully protect traffic coming in, but leave outgoing traffic and the cloud metadata address open.

Why it hurts

Stolen credentials and data can leave freely, which is where many real breaches end.

Better approach

Default-deny egress, block pods from the metadata service, and use per-pod cloud roles.

ANTI-PATTERN 07 · NO OWNER FOR POLICYAvoid
What people do

They let every team add exceptions, with no review and no cleanup.

Why it hurts

Rules pile up until the default-deny posture is just a long list of allows nobody understands.

Better approach

Assign clear ownership, review changes in version control, and schedule regular cleanups of unused rules.

26Frequently Asked Questions

These questions come up again and again when teams begin their zero-trust journey.

Q1Is zero trust a product I can buy?
No. It is an approach that combines identity, encryption, narrow rules, and monitoring. Vendors sell tools that help, but no single product delivers zero trust by itself.
Q2Do I need a service mesh to be zero trust?
Not on day one. Default-deny network policies, blocked metadata access, and controlled egress give a large security gain with no mesh at all. A mesh adds encryption, workload identity, and request-level rules when you are ready for them.
Q3Does a NetworkPolicy encrypt traffic?
No. It only decides which connections are allowed. Encryption comes from mutual TLS, from a mesh, from a network plugin feature, or from encrypted tunnels between nodes.
Q4Why not just use cloud firewalls and skip Kubernetes policies?
Cloud firewalls see machines and network interfaces, not individual pods and their labels. They are an important outer layer, but fine-grained pod-to-pod control needs rules that understand Kubernetes objects. The best designs use both.
Q5What is the difference between authentication and authorization?
Authentication answers “who are you”, and mutual TLS provides that for workloads. Authorization answers “what are you allowed to do”, and policies provide that. A system needs both, and in that order.
Q6Will mutual TLS make my application slow?
Slightly, in most cases. Connections are reused, so the expensive handshake happens rarely, and modern hardware encrypts quickly. The overhead is usually small next to the work applications do, but you should measure it in your own environment.
Q7How do I know if a policy is working?
Test it. Run automated checks that try a forbidden connection and confirm it fails, and try a required connection and confirm it succeeds. Also read the flow logs to see allowed and denied connections.
Q8What happens to existing traffic when I enable default-deny?
Anything not explicitly allowed stops working. That is why you should map traffic first, observe in a safe mode, and roll out one namespace at a time with a rollback plan ready.
Q9Are pod IP addresses good enough to identify workloads?
No. Pod addresses change constantly and can be reused by different programs. Use labels for policy matching and cryptographic identity for proof.
Q10How short should certificate lifetimes be?
Meshes commonly default to around a day for workload certificates. Shorter is safer but depends more on the issuing system staying up. Choose a value that your failure drills show your team can survive.
Q11Does zero trust protect against a malicious insider with cluster-admin rights?
Only partly. An administrator can change policies and read secrets. Zero trust reduces this risk through least-privilege access, audit logs, and alerts on policy changes, but strong human access controls remain essential.
Q12Where should a beginner start?
Confirm your network plugin enforces policies, apply default-deny with a DNS allowance in one test namespace, block pod access to the cloud metadata address, and write a communication map for your most sensitive application. Then add encryption and identity.

27Summary and Key Takeaways

What to remember

  • Location is not trust. Being inside the cluster proves nothing. Every connection should be identified, checked, and allowed only by an explicit rule.
  • A default cluster is a flat network. Any pod can reach any other pod, which makes sideways movement easy after a single break-in.
  • Start with default-deny. Close ingress and egress per namespace, allow DNS, and open only the connections on your communication map. Verify that your network plugin truly enforces them.
  • Prove identity with cryptography. Labels can be copied. Workload identities and short-lived certificates cannot, and mutual TLS turns them into encrypted, authenticated conversations.
  • Authorize requests, not only connections. Request-level rules say which identity may perform which action, limiting damage even from a trusted-looking caller.
  • Control the exits and the cloud edge. Restrict egress, block pod access to the metadata service, use per-pod cloud roles, and protect the API server and kubelet.
  • Observe, roll out gradually, and own the policy. Use flow data to plan, enforce one namespace at a time, treat rules as code, and monitor for denials and certificate health.