Istio Service Mesh
TL;DR
Istio injects Envoy sidecars or uses ambient dataplane to control service-to-service traffic. Debug by checking injection, sidecar readiness, istiod config push, VirtualService/DestinationRule, mTLS policy, and Envoy config.
Sidecar Traffic Flow
Istio sidecar mode: outbound Envoy → inbound Envoy → app container.
Components
| Component | Role | Check |
|---|---|---|
| istiod | Control plane; sends config to proxies. | kubectl get pods -n istio-system |
| Envoy sidecar | Per-Pod proxy for traffic and telemetry. | Pod has istio-proxy container. |
| Gateway | Ingress/egress proxy entry point. | Gateway Service and routes. |
| VirtualService | HTTP/TCP routing rules. | Host, gateway, destination subset. |
| DestinationRule | Subsets, load balancing, TLS policy. | Subset labels match Pods. |
Injection And Health
bashistio-health.sh
kubectl get pods -n istio-system -o wide # istiod and gateways should be Ready.
kubectl get namespace app --show-labels # Look for istio-injection=enabled or revision label.
kubectl get pod -n app web-api-abc123 -o jsonpath='{.spec.containers[*].name}' # Should include istio-proxy in sidecar mode.
kubectl describe pod -n app web-api-abc123 # Sidecar injection, readiness, and init container events.
kubectl logs -n istio-system deploy/istiod --tail=100 # Config push, validation, cert, or discovery issues.Canary Traffic Split
yamlvirtualservice-destinationrule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: web-api
namespace: app
spec:
host: web-api.app.svc.cluster.local
subsets:
- name: stable
labels:
version: v1 # Must match labels on stable Pods.
- name: canary
labels:
version: v2 # Must match labels on canary Pods.
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: web-api
namespace: app
spec:
hosts:
- web-api.app.svc.cluster.local
http:
- route:
- destination:
host: web-api.app.svc.cluster.local
subset: stable
weight: 90
- destination:
host: web-api.app.svc.cluster.local
subset: canary
weight: 10mTLS Policy
yamlpeer-authentication.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: app
spec:
mtls:
mode: STRICT # Workloads must use Istio mTLS; non-mesh clients may fail.
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-frontend
namespace: app
spec:
selector:
matchLabels:
app: web-api # Destination workload.
rules:
- from:
- source:
principals:
- cluster.local/ns/app/sa/frontend # Source workload identity.
to:
- operation:
methods: ["GET"]
paths: ["/health"]Debugging Commands
bashistio-debug.sh
istioctl analyze -A # Static analysis for broken Istio config.
istioctl proxy-status # Shows whether Envoy proxies are synced with istiod.
istioctl proxy-config routes web-api-abc123.app # Envoy route config for the Pod.
istioctl proxy-config clusters web-api-abc123.app | grep web-api
istioctl proxy-config listeners web-api-abc123.app
kubectl logs -n app web-api-abc123 -c istio-proxy --tail=100 # Envoy access/errors.
kubectl get virtualservice,destinationrule,gateway,peerauthentication,authorizationpolicy -AGotchas
- Namespace labels affect sidecar injection only for newly created Pods; restart workloads after enabling injection.
- DestinationRule subset labels must match Pod labels exactly or traffic gets no healthy upstream.
- STRICT mTLS breaks calls from non-mesh clients unless you design exceptions.
- VirtualService host names must match the caller's destination host, not just the Service you intended.