Demonstrates an Istio VirtualService demo using httpbin to show how Envoy sidecars enforce routing, how misconfiguring ports breaks traffic, and how URL rewrites work.
Use this file to discover all available pages before exploring further.
This lesson walks through a concise Istio VirtualService demo using the httpbin sample and a test pod. It shows how VirtualService routes influence traffic only when Envoy sidecars are present, and demonstrates URL rewriting. Follow the steps to reproduce the examples and understand the behavior.
Confirm whether automatic Istio sidecar injection is enabled in the default namespace:
# kubectl get ns --show-labelsNAME STATUS AGE LABELSdefault Active 15m istio-injection=enabled,kubernetes.io/metadata.name=defaultistio-system Active 12m kubernetes.io/metadata.name=istio-systemkube-node-lease Active 15m kubernetes.io/metadata.name=kube-node-leasekube-public Active 15m kubernetes.io/metadata.name=kube-publickube-system Active 15m kubernetes.io/metadata.name=kube-system
Note: Istio is permissive by default for cross-namespace communication unless you enable strict policies (e.g., mTLS strict mode). This helps avoid accidental service disruption after installing Istio.
You might still be able to curl httpbin from the test pod even after applying the broken VirtualService. Why? Because the test pod currently runs without an Envoy sidecar (its namespace was not injection-enabled) so its outbound traffic bypasses Istio and is unaffected by the VirtualService.Check the namespace labels and run analysis:
kubectl get ns --show-labelsistioctl analyze -n test# Info [IST0102] (Namespace test) The namespace is not enabled for Istio injection. Run 'kubectl label namespace test istio-injection=enabled' to enable it, or 'kubectl label namespace test istio-injection=disabled' to explicitly mark it as not needing injection.
6) Enable injection and recreate the pod so Envoy gets injected
Enable automatic sidecar injection for test, then delete and recreate the pod so it receives an Envoy sidecar:
kubectl label namespace test istio-injection=enabledkubectl delete pod test -n testkubectl run test --image=nginx -n testkubectl get pods -n test# NAME READY STATUS RESTARTS AGE# test 2/2 Running 0 10s
Now the test pod’s outbound traffic goes through Envoy and is governed by the VirtualService. Exec into the pod and try to reach httpbin:
kubectl exec -ti -n test test -- /bin/bash# root@test:/# curl -I httpbin.default.svc:8000/ip# HTTP/1.1 503 Service Unavailable# ...# root@test:/# exit
The 503 Service Unavailable is expected because the VirtualService routes to port 9000 (where nothing listens). Fix the VirtualService to route back to port 8000 and re-apply:
You must enable Istio sidecar injection in a namespace for Envoy to enforce VirtualService routing from pods in that namespace. Pods without a sidecar send traffic directly and are not affected by VirtualService rules.
Before applying the rewrite, requesting /hello returns 404 because httpbin has no /hello endpoint. After applying the VirtualService with the rewrite, requests to /hello are rewritten to / and succeed:
kubectl apply -f vs.yamlkubectl exec -ti -n test test -- /bin/bash# root@test:/# curl httpbin.default.svc:8000/ip# {# "origin": "127.0.0.6:36879"# }# root@test:/# curl httpbin.default.svc:8000/hello# 404 page not found # (before apply)## # After apply:# root@test:/# curl httpbin.default.svc:8000/hello# { ... httpbin response for / ... }# root@test:/# exit
The httpbin sample exposes many useful endpoints — for example, /ip, /user-agent, /status/<code>, and /dump/request. The following is an example HTML snippet from the httpbin project to illustrate a typical response:
This minimal demo demonstrates how VirtualService routing rules can change or break traffic when Envoy sidecars are present. In real deployments, VirtualServices are used widely together with DestinationRules, Gateways, and policies for traffic shaping, retries, timeouts, redirects, and header manipulation.Keep the official Istio docs handy for reference and canonical examples: