apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: public
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts: ["reviews.example.com"]
tls:
mode: SIMPLE
credentialName: reviews-tls
---
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: edge-response-header
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: envoy.filters.network.http_connection_manager
subFilter:
name: envoy.filters.http.router
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
defaultSourceCode:
inlineCode: |
function envoy_on_response(handle)
handle:headers():add("x-served-by", "edge")
end
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews
namespace: shop
spec:
hosts:
- reviews.example.com
- reviews.shop.svc.cluster.local
gateways:
- istio-system/public
- mesh
http:
- match:
- headers:
x-user:
exact: tester
route:
- destination:
host: reviews.shop.svc.cluster.local
subset: v2
- route:
- destination:
host: reviews.shop.svc.cluster.local
subset: v1
weight: 90
- destination:
host: reviews.shop.svc.cluster.local
subset: v2
weight: 10
timeout: 5s
retries:
attempts: 2
perTryTimeout: 2s
retryOn: 5xx,reset,connect-failure
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: reviews
namespace: shop
spec:
host: reviews.shop.svc.cluster.local
trafficPolicy:
connectionPool:
http:
http2MaxRequests: 1000
outlierDetection:
consecutive5xxErrors: 5
interval: 10s
baseEjectionTime: 30s
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
apiVersion: v1
kind: Service
metadata:
name: reviews
namespace: shop
spec:
selector:
app: reviews
ports:
- name: http
port: 9080
---
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: shop
spec:
mtls:
mode: STRICT
---
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: reviews-allow
namespace: shop
spec:
selector:
matchLabels:
app: reviews
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/shop/sa/frontend
- cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
to:
- operation:
methods: ["GET"]Istio graph
Istio traffic management: Gateway, VirtualService, DestinationRule and policies
The Istio objects behind a canary release in a sidecar mesh: ingress Gateway, VirtualService routing, DestinationRule subsets, strict mTLS with PeerAuthentication, AuthorizationPolicy and an EnvoyFilter.
Istio doesn't replace Kubernetes Services. It adds objects that configure the Envoy proxies in front of them. A Gateway opens a port on the ingress gateway, a VirtualService decides where each request goes, and a DestinationRule defines the subsets it can go to and how to connect to them.
Security is separate from routing. PeerAuthentication decides whether a workload accepts plaintext, and AuthorizationPolicy decides which callers may reach it. This graph uses the classic sidecar mode with Istio's own networking.istio.io API. With Gateway API you would write an HTTPRoute instead of the Gateway and VirtualService.
Interactive graph
Click a resource to see what it does, or follow the setup step by step.
How it works
All 13 resources and what they do
- Client Browser
- Calls
https://reviews.example.com. - Deployment istio-ingressgatewayapps/v1
- Envoy Pods at the edge of the mesh, labeled
istio: ingressgateway, behind aLoadBalancerService. They do nothing until a Gateway selects them. - Gateway publicnetworking.istio.io/v1
- Opens port 443 on the Pods matching
istio: ingressgatewayand terminates TLS forreviews.example.com. It has no routes. A VirtualService that names this Gateway supplies them. - Secret reviews-tlsv1
- The certificate for
credentialName. It must be in the same namespace as the ingress gateway Pods, not the Gateway's or the app's. - EnvoyFilter edge-response-headernetworking.istio.io/v1alpha3
- Patches the generated Envoy config directly, here adding a Lua filter on the ingress gateway that sets a response header. It's a last resort: it depends on Envoy internals that can change between Istio versions, so prefer a first-class API whenever one exists.
- VirtualService reviewsnetworking.istio.io/v1
- The routing rules. It applies to requests through the
publicGateway and, throughmesh, to calls from inside the mesh. A test user goes to v2, and everyone else is split 90/10, with a timeout and retries. - DestinationRule reviewsnetworking.istio.io/v1
- Defines the subsets
v1andv2by Pod label, and how to connect to them: a connection pool limit and outlier detection that ejects a Pod after five 5xx errors in a row. - Service reviewsv1
- A plain Service selecting
app: reviews, so it covers both versions. Istio uses it to find the endpoints, then the DestinationRule subsets narrow them down by theversionlabel. - Deployment reviews-v1apps/v1
- The stable version. Its Pods carry
app: reviewsandversion: v1, and each one gets an Envoy sidecar injected because the namespace hasistio-injection: enabled. - Deployment reviews-v2apps/v1
- The canary, with
version: v2. Scaling it doesn't change its share of traffic. The VirtualService weights decide that. - Deployment frontendapps/v1
- Calls
http://reviews:9080from inside the mesh, running as the ServiceAccountfrontend. Its sidecar applies the same VirtualService rules and upgrades the call to mTLS on its own. - PeerAuthentication defaultsecurity.istio.io/v1
- Named
defaultwith no selector, so it covers every workload inshop.STRICTmakes the sidecars refuse plaintext, so only mesh workloads with a valid certificate can connect. - AuthorizationPolicy reviews-allowsecurity.istio.io/v1
- Applies to
app: reviews. Once any ALLOW policy selects a workload, everything not allowed is denied. This one allows GET requests from thefrontendServiceAccount and from the ingress gateway. The caller identity comes from the mTLS certificate.
Common mistakes
- A VirtualService with a
gatewayslist applies only to those gateways. If you list a Gateway and forgetmesh, calls from inside the cluster skip your rules entirely. - The Secret named in
credentialNamemust be in the ingress gateway's namespace. cert-manager has to issue the certificate there too. - Turning on
STRICTbefore every client has a sidecar cuts off the ones without one. Start inPERMISSIVE, check that all traffic shows as mTLS in Kiali or the metrics, then switch. - An ALLOW policy that matches nothing still denies everything not allowed. A typo in a principal blocks real traffic, so test with
istioctl x authz check <pod>. istioctl analyze -n shopfinds the usual mistakes: a VirtualService pointing at a subset with no DestinationRule, a Gateway selector that matches no Pods, or two VirtualServices for the same host.
The manifests you write
Everything above that is marked "You write it", in one file. The rest comes from add-ons and controllers.
Keep going
More graphs
- Deployment, Service and Ingress: how a request reaches your Pods
- Gateway API: GatewayClass, Gateway and HTTPRoute with a canary split
- PVC, StorageClass and CSI: how a cloud disk ends up in your Pod
- RBAC: how a ServiceAccount gets its permissions
- cert-manager with Let's Encrypt: Certificate, CertificateRequest, Order and Challenge
- A private CA with cert-manager and trust-manager
- Flux dependencies: Git and OCI sources, Kustomizations and HelmReleases
- Argo CD: ApplicationSet, AppProject and the Applications it generates
- Inside an OCI image: tag, index, manifests, config and layers
- OCI artifacts: Helm charts, Flux artifacts and image volumes