Skip to main content

Documentation Index

Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt

Use this file to discover all available pages before exploring further.

In this lesson you’ll configure an Istio Ingress Gateway to expose the Bookinfo application. The steps covered:
  • Verify Istio is installed and sidecar injection is enabled on the namespace.
  • Deploy Bookinfo and confirm sidecar injection on pods.
  • Create an internal-only VirtualService.
  • Create a Gateway that selects the Istio ingress dataplane.
  • Update the VirtualService to bind to the Gateway and test via curl.
  • Explain differences between cloud clusters (LoadBalancer) and kubeadm-style labs (NodePort).
Relevant resources

1. Verify Istio installation and namespace injection

  1. Check Istio control-plane / system pods:
kubectl get pods -n istio-system
Example output:
NAME                           READY   STATUS    RESTARTS   AGE
istio-egress-cfcd9bc96-9yncl   1/1     Running   0          4m32s
istio-ingress-6cf77d4858-g2cvz 1/1     Running   0          4m31s
istiod-5fcb7d9676-j9vr9        1/1     Running   0          4m42s
  1. Confirm sidecar injection is enabled for the default namespace:
kubectl get ns --show-labels
Example output:
NAME               STATUS   AGE     LABELS
default            Active   5m29s   istio-injection=enabled,kubernetes.io/metadata.name=default
istio-system       Active   4m51s   kubernetes.io/metadata.name=istio-system
kube-node-lease    Active   5m29s   kubernetes.io/metadata.name=kube-node-lease
kube-public        Active   5m29s   kubernetes.io/metadata.name=kube-public
kube-system        Active   5m29s   kubernetes.io/metadata.name=kube-system
Tip: If istio-injection=enabled is not present, enable injection with:
kubectl label namespace default istio-injection=enabled --overwrite

2. Deploy Bookinfo and confirm sidecar injection

Deploy Bookinfo using your usual method (the YAMLs are omitted here). After deploying, verify the pods show 2/2 (application + Envoy sidecar) where sidecar injection applies:
kubectl get pods
Example output:
NAME                               READY   STATUS    RESTARTS   AGE
details-v1-65599dcf88-m7qpm        2/2     Running   0          4s
productpage-v1-9487c9c5b-qk955     1/2     Running   0          4s
ratings-v1-59b99c644-2dgfs         2/2     Running   0          4s
reviews-v1-5985998544-ntzxh        2/2     Running   0          4s
reviews-v2-86d6cc668-qgqmj         2/2     Running   0          4s
reviews-v3-dbb5fb5dd-p78hv         1/2     Running   0          4s
If some pods show 1/2, check pod events and sidecar injection policies for the namespace.

3. Create an internal-only VirtualService

Start by creating a VirtualService that routes traffic for the productpage service internally. Save this manifest as vs.yaml:
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: book-info-vs
spec:
  hosts:
  - productpage
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: productpage.default.svc.cluster.local
        port:
          number: 9080
Apply it:
kubectl apply -f vs.yaml
Expected feedback:
virtualservice.networking.istio.io/book-info-vs created
At this stage the VirtualService is internal-only: it matches the productpage service host but is not yet exposed through a Gateway.

4. Locate the ingress dataplane label for Gateway selector

Istio Gateways select the ingress dataplane (ingress pod) using pod labels. Inspect the ingress pod(s) in istio-system to find the label to use as the Gateway selector:
kubectl get pods -n istio-system
kubectl describe pod -n istio-system istio-ingress-6cf77d4858-g2cvz
Look for the Labels: block. Example:
Labels:
  app=istio-ingress
  istio=ingress
  sidecar.istio.io/inject=true
  ...
Note the label (for example istio=ingress or app=istio-ingress) — you will use this value under spec.selector in the Gateway manifest.

5. Create an Istio Gateway

Create a Gateway manifest that selects the ingress dataplane label and listens on port 80. Save as gw.yaml in the same namespace as your VirtualService (here we use default):
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: istio-gateway
spec:
  selector:
    istio: ingress
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "book.info.com"
Apply it:
kubectl apply -f gw.yaml
Verify Gateway and VirtualService presence:
kubectl get gateways.networking.istio.io
kubectl get virtualservices.networking.istio.io
Example outputs:
# Gateways
NAME           AGE
istio-gateway  10s

# VirtualServices
NAME           GATEWAYS   HOSTS             AGE
book-info-vs               ["productpage"]   30s
At this point the Gateway resource exists, but the VirtualService is still not bound to the Gateway and still only matches the internal productpage host.

6. Check Istio ingress Service type (Cluster behavior)

Istio’s ingress Service type varies by environment:
kubectl get svc -n istio-system
Example (kubeadm lab, NodePort):
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)
istio-ingress   NodePort    10.97.88.127     <none>        15021:31817/TCP,80:30992/TCP,443:30171/TCP
Example (cloud-managed cluster, LoadBalancer):
NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP
istio-ingressgateway LoadBalancer   10.100.188.237   abb6be537f8134cc084b21378582f75-477874693.us-east-1.elb.amazonaws.com
Table: Service types and how to reach the ingress
Service TypeHow to target for curl / external tests
LoadBalancerUse the external IP/hostname in requests (no Host header required if DNS points to it).
NodePortUse nodeIP:nodePort (or node IP + NodePort). When targeting a NodePort for a Gateway with port 80 mapped to a NodePort, use the node IP and that NodePort.
ClusterIPMust curl from inside the cluster (e.g., using a temporary curl pod) and target the ClusterIP.

7. Test the Gateway (initial behavior)

If you test now without updating the VirtualService, you may get a 404. Example (curl from inside the cluster to the ClusterIP):
curl --head --header "Host: book.info.com" http://10.97.88.127
Possible response:
HTTP/1.1 404 Not Found
date: Fri, 11 Apr 2025 21:33:08 GMT
server: istio-envoy
transfer-encoding: chunked
Why 404? The VirtualService still matches only the internal host productpage. The Gateway receives traffic for book.info.com, but no VirtualService is bound to that host + gateway combination yet.

8. Update the VirtualService to bind to the Gateway

Edit vs.yaml to include the external host and reference the Gateway. The updated manifest:
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: book-info-vs
spec:
  hosts:
  - "book.info.com"
  - productpage
  gateways:
  - istio-gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: productpage.default.svc.cluster.local
        port:
          number: 9080
Apply the change:
kubectl apply -f vs.yaml
Expected feedback:
virtualservice.networking.istio.io/book-info-vs configured

9. Re-test and validate a 200 response

Target the ingress address that is reachable from where you run curl. If you don’t have DNS for book.info.com, continue using the Host header: Example (from inside the cluster using the ClusterIP):
curl --head --header "Host: book.info.com" http://10.97.88.127
You should now receive a 200:
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 1683
server: istio-envoy
date: Fri, 11 Apr 2025 21:35:57 GMT
x-envoy-upstream-service-time: 21
If you have DNS pointing book.info.com to the external LoadBalancer hostname/IP, you can omit the Host header and call the DNS name directly.
Testing without a DNS record: pass the Host header to the ingress IP to emulate requests for the hostname (for example, Host: book.info.com). On cloud clusters the ingress Service typically becomes a LoadBalancer with an external hostname—update DNS to point your host (e.g., book.info.com) to that external IP/hostname.

10. Quick troubleshooting checklist

  • Confirm the Gateway spec.selector matches an ingress pod label (e.g., istio=ingress).
  • Ensure the VirtualService lists the external host (e.g., book.info.com) under spec.hosts.
  • Bind the VirtualService to the Gateway by adding spec.gateways: - istio-gateway.
  • Verify the ingress Service type (LoadBalancer vs NodePort vs ClusterIP) and use an accessible address for curl tests.
  • Inspect Envoy logs on the ingress pod for routing errors:
    kubectl logs -n istio-system <ingress-pod> -c istio-proxy
    

Summary

  • Create a Gateway whose selector matches the ingress dataplane label (e.g., istio=ingress).
  • Create or update a VirtualService to include the external host(s) and a reference to the Gateway.
  • Test using curl with a Host header when DNS is not configured, making sure you target an ingress address reachable from your client.
  • On cloud-managed clusters, Istio commonly provisions a LoadBalancer for the ingress Service; on kubeadm lab environments you may see NodePort instead.

Watch Video

Practice Lab