k8wiz
All graphs

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.

Outside the clusterComes with an add-onYou write ittrafficselects by labelreferences

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 a LoadBalancer Service. They do nothing until a Gateway selects them.
Gateway publicnetworking.istio.io/v1
Opens port 443 on the Pods matching istio: ingressgateway and terminates TLS for reviews.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 public Gateway and, through mesh, 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 v1 and v2 by 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 the version label.
Deployment reviews-v1apps/v1
The stable version. Its Pods carry app: reviews and version: v1, and each one gets an Envoy sidecar injected because the namespace has istio-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:9080 from inside the mesh, running as the ServiceAccount frontend. Its sidecar applies the same VirtualService rules and upgrades the call to mTLS on its own.
PeerAuthentication defaultsecurity.istio.io/v1
Named default with no selector, so it covers every workload in shop. STRICT makes 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 the frontend ServiceAccount and from the ingress gateway. The caller identity comes from the mTLS certificate.

Common mistakes

  • A VirtualService with a gateways list applies only to those gateways. If you list a Gateway and forget mesh, calls from inside the cluster skip your rules entirely.
  • The Secret named in credentialName must be in the ingress gateway's namespace. cert-manager has to issue the certificate there too.
  • Turning on STRICT before every client has a sidecar cuts off the ones without one. Start in PERMISSIVE, 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 shop finds 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.

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"]

Keep going

More graphs