In Kubernetes, the biggest security exposure usually isn’t at the edge; it’s inside the cluster, in all the service-to-service (east–west) calls between pods. Once an attacker lands in the cluster, a flat internal network makes it easy to probe services, abuse internal APIs, and move laterally.

A service mesh lets you treat every pod-to-pod request as untrusted until authenticated and authorized. Using meshes like Istio, Linkerd, and Consul, you can combine:

  • mTLS for workload identity
  • JWTs for user/client identity
  • Fine-grained API policies
  • WASM filters and rate limits for advanced controls
  • Telemetry + eBPF + SIEM/SOAR for detection and response

The goal is zero-trust east–west traffic without breaking your performance budget.

mTLS: the base for identity and encryption

Mutual TLS (mTLS) is the starting point for securing east–west traffic in a mesh. It gives you three core things:

  • Encryption in transit between workloads
  • Authentication of both sides using X.509 certificates
  • A stable, cryptographic identity (for example, namespace and service account) that you can reference in policy

Istio: strict mTLS

apiVersion: security.istio.io/v1

kind: PeerAuthentication

metadata:

  name: default

  namespace: default

spec:

  mtls:

    mode: STRICT

With STRICT mode, workloads in that namespace are expected to use mTLS for their inbound traffic. When combined with the right DestinationRule settings for outbound calls, you effectively remove the possibility of plaintext traffic between meshed services.

Linkerd

In Linkerd, once a pod is meshed, mTLS is automatically applied to its in-mesh communication. Identities are derived from Kubernetes service accounts, and all traffic inside the mesh is encrypted and authenticated by default, without you having to configure mTLS for each service individually.

Consul service mesh

Consul’s service mesh uses Envoy sidecars and a built-in certificate authority. It layers L4 allow/deny logic on top of mTLS identities using “Intentions”:

  • Start from a default-deny stance
  • Add explicit “allow” Intentions, for example, checkoutorders

This ensures only explicitly permitted service pairs can talk to each other over authenticated, encrypted channels. However, mTLS and Intentions only say “who can talk to whom”; they do not control which specific APIs are being called. For that, you need L7 policy and, where appropriate, JWT-based identity.

JWTs: tying user and client identity to requests

mTLS tells you which workload is calling, but not which user, tenant, or external system is behind a request. JSON Web Tokens (JWTs) are commonly used to attach that higher-level identity.

Typical JWT patterns include:

  • End-user tokens issued by an identity provider and passed from an API gateway down to backend services
  • Client or service tokens representing jobs, external integrations, or tenants

Istio example: JWT validation and authorization

First, you validate tokens at the mesh edge for a specific workload:

apiVersion: security.istio.io/v1

kind: RequestAuthentication

metadata:

  name: reviews-jwt

  namespace: default

spec:

  selector:

    matchLabels:

      app: reviews

  jwtRules:

  – issuer: “https://auth.example.com/”

    jwksUri: “https://auth.example.com/.well-known/jwks.json”

This ensures tokens presented to the reviews app are signed by your trusted issuer and can be parsed at the proxy.

Next, you enforce authorization using those claims:

apiVersion: security.istio.io/v1

kind: AuthorizationPolicy

metadata:

  name: reviews-only-payments

  namespace: default

spec:

  selector:

    matchLabels:

      app: reviews

  rules:

  – when:

    – key: request.auth.claims[role]

      values: [“payments”]

Taken together, these resources ensure that only requests with a valid JWT and the correct role claim are allowed through to the application.

With Linkerd and Consul, JWTs are usually validated at an ingress gateway or external auth component. After validation, identity information is forwarded via trusted headers, which downstream services and/or mesh policies can use for authorization.

Enforcing API contracts to prevent lateral movement

Once an attacker has compromised a pod, a common next step is to:

  • Scan and probe other services
  • Call internal admin, debug, or export endpoints that were never meant to be exposed to it

To counter this, you describe “who can call what” as concrete API-level rules in the mesh.

Path and method-level policy in Istio

Instead of simply stating “checkout can talk to orders,” you can restrict it to “checkout may only POST /orders on the orders service”:

apiVersion: security.istio.io/v1

kind: AuthorizationPolicy

metadata:

  name: checkout-to-orders

  namespace: orders

spec:

  selector:

    matchLabels:

      app: orders

  rules:

  – from:

    – source:

        principals: [“cluster.local/ns/checkout/sa/checkout-sa”]

    – operation:

        methods: [“POST”]

        paths: [“/orders”]

If an attacker in the checkout pod tries to access GET /orders, /orders/export, or /admin, the proxy denies those requests before they reach the orders application.

Linkerd and Consul approaches

In Linkerd, HTTP-aware policy is expressed using a combination of Server, ServerAuthorization, and HTTPRoute objects. These let you limit which identities can reach which ports and which HTTP paths and methods are acceptable for those routes.

Consul blends its L4 Intentions with Envoy’s L7 capabilities. By attaching Envoy RBAC rules, Lua/WASM filters, or external authorization to the proxies, you can constrain which HTTP routes and methods are allowed, even after an L4 Intention has allowed the connection.

WASM filters and rate limits

For more advanced controls, Envoy WASM filters or external policy engines can be used to:

  • Validate request payloads against OpenAPI or protobuf schemas
  • Reject requests that contain unknown or suspicious fields
  • Implement per-identity or per-route rate limits
  • Check that tenant identifiers in headers or bodies match the mTLS or JWT identity

These heavier checks are best reserved for particularly sensitive endpoints such as /login, /admin, and /export, where the extra processing cost is justified.

Zero-trust segmentation and multi-cluster policy propagation

Zero trust inside a cluster means a pod isn’t trusted purely because it’s running on the same network or in the same namespace.

Segmentation patterns

Some practical patterns for segmentation:

  • Build policies around the service account and namespace (the mTLS principal), rather than pod IPs
  • Give each tenant its own namespaces and service accounts, and apply mesh policies that only allow them to reach a small set of shared platform APIs
  • Default to “no east–west permissions” and then add explicit, minimal allow rules between services that must communicate

Mesh authorization works well alongside Kubernetes NetworkPolicy:

  • NetworkPolicy controls L3/L4 connectivity
  • Mesh policy handles L7 semantics and identity

Multi-cluster and multi-cloud

In larger deployments, you often have several clusters, possibly across different regions or clouds. To keep identity and policy coherent:

  • Use a shared trust domain or federated CAs so that identities from one cluster can be verified in another
  • Define core policies once and distribute them through GitOps tools like Argo CD or Flux to each cluster
  • Keep cluster-specific differences to a small set of overrides (for example, rate limits, sampling, or environment-specific hosts)

This way, a workload has a consistent identity and set of allowed APIs, regardless of where it runs.

Telemetry, eBPF, SIEM, and SOAR: from visibility to response

Locking down traffic is one half of the story; being able to see and react to what is happening is the other.

Mesh telemetry

Service mesh proxies emit rich operational data, including:

  • HTTP/gRPC metrics such as latency, error rates, and volumes per route
  • Access logs with source identity, destination, method, path, and status code
  • TLS information showing whether mTLS was used and which identities participated in the handshake

These logs are more useful when enriched with Kubernetes metadata (namespace, workload, node) and security-relevant fields like mTLS status and key JWT claims.

eBPF for deeper visibility

eBPF-based tools such as Cilium, Falco, and Pixie can observe kernel-level behavior that the mesh alone does not see, for example:

  • Unusual outbound network connections, including potential attempts to bypass the mesh (when integrated with the CNI)
  • DNS lookups to unexpected or suspicious domains
  • Process activity inside containers, which can be correlated back to pods

Combining mesh telemetry with eBPF data lets you connect an odd traffic pattern with the specific code paths and processes that produced it.

Integrating with SIEM and SOAR

Mesh and eBPF data typically flow into a SIEM via log collectors and metrics exporters. From there, you can define rules to flag:

  • Internal port scans or connection attempts to many internal services
  • New or unexpected destinations for a workload
  • Sudden spikes in 403 responses or abnormal usage of sensitive APIs

Once a pattern is detected, a SOAR system or automation pipeline can:

  • Apply a temporary deny-all mesh policy to a suspicious identity or namespace
  • Tighten existing authorization policies to only allow a minimal subset of routes
  • Adjust rate limits on stressed or targeted endpoints
  • Notify on-call staff with recent deployment history, pod details, and relevant policies

In this model, the mesh becomes a control surface that your security team can programmatically adjust in response to events.

Balancing security with performance

Each layer of control adds overhead. In high-throughput environments, you need to be conscious of where that cost comes from and how to manage it.

Some practical points:

  • Budget explicitly for mTLS; modern CPUs cope well with crypto, but many short-lived connections can still be expensive
  • Apply more complex L7 checks (WASM, external auth, schema validation) only to endpoints where the risk justifies the cost
  • Give proxies clear CPU and memory requests and limits, and track P99 latency and error rates to catch resource-related issues
  • Use log sampling: record everything for errors and sensitive endpoints, but sample normal traffic to reduce volume
  • As you add controls, benchmark with scenarios such as mTLS only, then mTLS plus authorization, then mTLS plus authorization plus WASM, so you can see the impact of each step

Handled carefully, you end up with east–west controls that follow zero-trust principles, strong visibility into what is happening in the mesh, and performance characteristics that both platform and security teams can work with.

Share:

Get involved!

Get Connected!
Join our community. Expand your network and discover great content!

Comments

No comments yet