Episode 12 separates tenants within a single mesh: namespaces as isolation boundaries, per-tenant injection labels, limiting egress scope with the Sidecar CRD, AuthorizationPolicy for isolation, and comparing Kubernetes RBAC with Istio AuthorizationPolicy.

Not every machine is used by a single team. When many teams, products, or even clients share one mesh, you need isolation — without it, one wrong VirtualService can disrupt another tenant's traffic. Episode 12 covers how to separate tenants safely using namespaces, the Sidecar CRD, and AuthorizationPolicy.
The simplest pattern: one tenant, one namespace. Each tenant gets its namespace, injection labels, and clear rules without interfering with each other:
kubectl create ns tenant-a
kubectl create ns tenant-b
kubectl label ns tenant-a istio.io/rev=1-22-1Per-tenant revision labels let you move one tenant to a new Istio version without touching other tenants — isolation for the upgrade process we covered in episode 3.
Namespaces provide basic Kubernetes isolation, but they do not automatically isolate the mesh. By default, a VirtualService can still reference hosts across namespaces (with the service.namespace.svc.cluster.local format), and sidecars can access other tenants' services. That is where the next two mechanisms come in.
To prevent tenant A's sidecars from carrying tenant B's service configuration, limit their scope with Sidecar:
apiVersion: networking.istio.io/v1
kind: Sidecar
metadata:
name: default
namespace: tenant-a
spec:
egress:
- hosts:
- "./*"
- "istio-system/*"egress.hosts: ["./*"] limits tenant-a's egress to services in the same namespace plus istio-system. The effect compounds: the service map in Envoy shrinks (saving resources) and the lateral attack surface is reduced.
For inbound traffic, ingress can limit which traffic reaches specific workloads:
spec:
ingress:
- port:
number: 80
protocol: HTTP
defaultEndpoint: 127.0.0.1:8080This pattern limits the listeners Envoy creates, so workloads do not receive traffic from arbitrary sources.
The Sidecar CRD controls who can send; AuthorizationPolicy controls who may be received. Combine the two for full isolation:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-cross-tenant
namespace: tenant-a
spec:
action: DENY
rules:
- from:
- source:
notNamespaces: ["tenant-a", "istio-system"]notNamespaces rejects requests coming from namespaces outside tenant-a and istio-system. This is a safety net: even if a VirtualService tries to route across tenants, the request is still rejected at the authorization level.
These two mechanisms are often confused. The difference matters:
RBAC controls who may do what to Kubernetes objects — create Pods, read Secrets, delete Deployments. It is an administrative control: it protects the cluster itself, not application traffic. Example: giving a developer access only within their tenant namespace.
AuthorizationPolicy controls traffic flowing through the mesh — HTTP requests between services. It operates on workload identity and JWT claims, not Kubernetes accounts. Example: the frontend service may call productpage, but the backend service may not.
An easy mental table:
kubectl what.The two complement each other. RBAC keeps the infrastructure safe from human misuse; AuthorizationPolicy keeps application communication aligned with policy. Both must be installed together.
RBAC = who may manage the cluster
AuthzPolicy = which service may talk to which serviceEpisode 12 arranged multi-tenancy: namespaces as tenant boundaries with per-tenant revision labels, the Sidecar CRD for limiting egress and ingress scope, AuthorizationPolicy as a cross-tenant safety net, and a clear understanding of the role split between Kubernetes RBAC and Istio AuthorizationPolicy.
Key takeaways:
In the next episode, episode 13, we will discuss another network layer: network policies and CNI integration — comparing Kubernetes NetworkPolicy with Istio policies, understanding the role of the Istio CNI plugin, and its implications for sidecar lifecycle and traffic capture.