---
title: "Istio Routing Basics: A Step-by-Step Tutorial"
source: "https://wordpress-1075849-4005834.cloudwaysapps.com/blog/istio-routing-basics/"
---

[Technical Blog](https://wordpress-1075849-4005834.cloudwaysapps.com/category/technical-blog/)

# Istio Routing Basics: A Step-by-Step Tutorial

By [Mete Atamel](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/mete-atamel/) on Sep 13, 2019 • 6 min read

When learning a new technology like [Istio](http://istio.io/), it’s always a good idea to take a look at sample apps. Istio repo has a few [sample](http://github.com/istio/istio/tree/master/samples) apps but they fall short in various ways. [BookInfo](http://github.com/istio/istio/tree/master/samples/bookinfo) is covered in the docs and it is a good first step. However, it is too verbose with too many services for me and the docs seem to focus on managing the BookInfo app, rather than building it from ground up. There’s a smaller [helloworld](http://github.com/istio/istio/tree/master/samples/helloworld) sample but it’s more about autoscaling than anything else.

In this post, I’d like to get to the basics and show you what it takes to build an Istio enabled ‘HelloWorld’ app from ground up. One thing to keep in mind is that Istio only manages the traffic of your app. The app lifecycle is managed by the underlying platform, Kubernetes in this case. Therefore, you need to understand containers and Kubernetes basics and you need to know about Istio Routing primitives such as Gateway, VirtualService, DestinationRuleupfront. I’m assuming that most people know containers and Kubernetes basics at this point. I will focus on Istio Routing instead in this post.

 

## Basic Steps

These are roughly the steps you need to follow to get an Istio enabled ‘HelloWorld’ app:

- Create a Kubernetes cluster and install Istio with automatic sidecar injection.

- Create a HelloWorld app in your language of choice, create a Docker image out of it and push it to a public image repository.

- Create Kubernetes Deployment and Service for your container.

- Create a [Gateway](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#Gateway) to enable HTTP(S) traffic to your cluster.

- Create a [VirtualService](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#VirtualService) to expose Kubernetes Service via Gateway.

- (Optional) If you want to create multiple versions of your app, create a [DestinationRule](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#DestinationRule) to define subsets that you can refer from the VirtualService.

- (Optional) If you want to call external services outside your service mesh, create a [ServiceEntry](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#ServiceEntry).

I won’t cover steps 1 and 2 in this post because they are not Istio specific. If you need help with these steps, you can take a look at the codelabs I mention at the end of this post. Step 3 is not Istio specific either but it’s kind of prerequisite to everything else, so let’s start with that.

## Deployment and Service

As I mentioned, the app lifecycle is managed by Kubernetes. Therefore, you need to start with creating a Kubernetes Deployment and Service. In my case, I have a containerized ASP.NET Core app whose image I already pushed to Google Container Registry. Let’s start with creating an `aspnetcore.yaml` file:

Create the deployment and service:

```
`$ kubectl apply -f aspnetcore.yaml service "aspnetcore-service" created deployment.extensions "aspnetcore-v1" created`
```

Nothing Istio specific so far.

## Gateway

We can now start looking into Istio Routing. First, we need to enable HTTP/HTTPS traffic to our service mesh. To do that, we need to create a [Gateway](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#Gateway). Gateway describes a load balancer operating at the edge of the mesh receiving incoming or outgoing HTTP/TCP connections. Let’s create an `aspnetcore-gateway.yaml` file:

Create the Gateway:

```
`$ kubectl apply -f aspnetcore-gateway.yaml gateway.networking.istio.io "aspnetcore-gateway" created`
```

At this point, we have HTTP traffic enabled for our cluster. We need to map the Kubernetes Service we created earlier to the Gateway. We’ll do that with a VirtualService.

## VirtualService

A [VirtualService](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#VirtualService) essentially connects a Kubernetes Service to Istio Gateway. It can also do more such as defining a set of traffic routing rules to apply when a host is addressed but we won’t get into those details.

Let’s create an `aspnetcore-virtualservice.yaml` file:

Notice that a VirtualService is tied to a specific Gateway and it defines a host that refers to the Kubernetes Service. Create the VirtualService:

```
`$ kubectl apply -f aspnetcore-virtualservice.yaml virtualservice.networking.istio.io "aspnetcore-virtualservice" created`
```

 

## Test the v1 of app

We’re ready to test our app. We need to get the IP address of the Istio Ingress Gateway:

```
`$ kubectl get svc istio-ingressgateway -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP istio-ingressgateway LoadBalancer 10.31.247.41 35.240.XX.XXX`
```

When we browser to the `EXTERNAL-IP`, we should see the HelloWorld ASP.NET Core app:

![Screenshot of the HelloWorld ASP.NET Core app, confirming successful deployment](/app/uploads/2019/06/1_WksXRI3XV54SegfmFd0_bg.png)

 

## DestinationRule

At some point, you want to update your app to a new version. Maybe you want to split the traffic between two versions. You need to create a [DestinationRule](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#DestinationRule) to define those versions, called subsets in Istio. First, update `aspnetcore.yaml` file to define the Deployment for `v2` with `v2`version of the container:

Create the new deployment:

```
`$ kubectl apply -f aspnetcore.yaml service "aspnetcore-service" unchanged deployment.extensions "aspnetcore-v1" unchanged deployment.extensions "aspnetcore-v2" created`
```

If you refresh the browser with the `EXTERNAL-IP` , you’ll see that VirtualService rotates through `v1` and `v2` versions of the app:

v1 of the app

![HelloWorldAspNetCore site showcasing ASP.NET Core running on Windows, Linux, and OSX](/app/uploads/2019/06/1_vqfpTeJtV1aP8v0mV8Ff2g.png)

v2 of the app

This is expected because both versions are exposed behind the same Kubernetes service:`aspnetcore-service`.

What if you want to pin your service to only `v2`? This can be done by specifying a subset in the VirtualService but we need to define those subsets first in a DestinationRules. A DestinationRule essentially maps labels to Istio subsets.

Create a `aspnetcore-destinationrule.yaml` file:

Create the DestinationRule:

```
`$ kubectl apply -f aspnetcore-destinationrule.yaml destinationrule.networking.istio.io "aspnetcore-destinationrule" created`
```

Now, you can refer to `v2` subset from VirtualService:

Update the VirtualService:

```
`$ kubectl apply -f aspnetcore-virtualservice.yaml virtualservice.networking.istio.io "aspnetcore-virtualservice" configured`
```

If you browse back to the`EXTERNAL-IP` , you should now only see the `v2` of the app.

## ServiceEntry

The last thing I want to mention in Istio Routing is [ServiceEntry](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#ServiceEntry). By default, all the external traffic in Istio is blocked. If you want to enable external traffic, you need to create a ServiceEntry to list what protocols and hosts are enabled for external traffic. I won’t show an example in this post but you can read more about it [here](http://istio.io/docs/reference/config/istio.networking.v1alpha3/#ServiceEntry).

This article originated from [http://medium.com/google-cloud/istio-routing-basics-14feab3c040e](http://medium.com/google-cloud/istio-routing-basics-14feab3c040e)

[Mete Atamel](http://uk.linkedin.com/in/meteatamel) is a Tigera guest blogger. He is a Developer Advocate at Google, helping developers to be successful on Google Cloud Platform, and a regular speaker at tech conferences/meetups across the globe. His focus areas are Windows/.NET apps on Google Cloud, Kubernetes, Istio and Knative. Previously, he was a Software Engineer/Architect/Tech Lead at Nokia, EMC, Adobe, Skype and Microsoft, building apps and services on various web, mobile and cloud platforms.

————————————————-

[**Free Online Training**](https://wordpress-1075849-4005834.cloudwaysapps.com/events/)

Access Live and On-Demand Kubernetes Tutorials

[**Calico Enterprise – Free Trial**](https://www.calicocloud.io/home)

Solve Common Kubernetes Roadblocks and Advance Your Enterprise Adoption

[How-To](https://wordpress-1075849-4005834.cloudwaysapps.com/tags/how-to/)[Service Mesh](https://wordpress-1075849-4005834.cloudwaysapps.com/tags/service-mesh/)

Add Tigera as a preferred source on Google to see more of our content in your search results.

[![Add as a preferred source on Google](https://wordpress-1075849-4005834.cloudwaysapps.com/app/themes/tigera2021/dist/img/google-preferred-source-light.png)](https://www.google.com/preferences/source?q=tigera.io)

## Related posts

[![AI Assistant for Calico: Troubleshooting at the Speed of Thought](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/03/Blog-Mar-20-AI-Assistant-for-Calico.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

#### [AI Assistant for Calico: Troubleshooting at the Speed of Thought](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

By [Veronika Smolik](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/veronika-smolik/)
on Mar 19, 2026

Despite the wealth of data available, distilling a coherent narrative from a Kubernetes cluster remains a challenge for modern infrastructure teams. Even with powerful visualization tools like the Policy Board, Service Graph, and specialized dashboards,...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

[![What Your EKS Flow Logs Aren’t Telling You](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/03/Blog-Mar-18-What-Your-EKS-Flow-Logs-Arent-Telling-You.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

#### [What Your EKS Flow Logs Aren’t Telling You](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

By [Phil DiCorpo](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/phil-dicorpo/)
on Mar 18, 2026

If you’re running workloads on Amazon EKS, there’s a good chance you already have some form of network observability in place. VPC Flow Logs have been a staple of AWS networking for years, and AWS...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

[![Kubernetes Network Observability: Comparing Calico, Cilium, Retina, and Netobserv](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/02/Blog-Feb-11-Comparing-Calico-Cilium-Retina-and-Netobserv-1.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/kubernetes-network-observability-comparing-calico-cilium-retina-and-netobserv/)

#### [Kubernetes Network Observability: Comparing Calico, Cilium, Retina, and Netobserv](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/kubernetes-network-observability-comparing-calico-cilium-retina-and-netobserv/)

By [Reza Ramezanpour](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/rezar/)
on Feb 11, 2026

Calico, Cilium, Retina, and Netobserv: Which Observability Tool is Right for Your Kubernetes Cluster? Network observability is a tale as old as the OSI model itself and anyone who has managed a network or even...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/kubernetes-network-observability-comparing-calico-cilium-retina-and-netobserv/)

<!-- plugin=object-cache-pro client=phpredis metric#hits=6183 metric#misses=17 metric#hit-ratio=99.7 metric#bytes=2212505 metric#prefetches=0 metric#store-reads=419 metric#store-writes=10 metric#store-hits=432 metric#store-misses=6 metric#sql-queries=26 metric#ms-total=907.53 metric#ms-cache=63.57 metric#ms-cache-avg=0.1485 metric#ms-cache-ratio=7.0 sample#redis-hits=75261011 sample#redis-misses=9070667 sample#redis-hit-ratio=89.2 sample#redis-ops-per-sec=312 sample#redis-evicted-keys=0 sample#redis-used-memory=121651904 sample#redis-used-memory-rss=110755840 sample#redis-memory-fragmentation-ratio=0.9 sample#redis-connected-clients=1 sample#redis-tracking-clients=0 sample#redis-rejected-connections=0 sample#redis-keys=33629 -->
