Attach multiple VirtualServices to Istio Gateway
In this post, you'll learn how to expose multiple Kubernetes services running inside your cluster using Istio' Gateway and VirtualService resources.
What will I learn?
How does it work?
hosts
fields in the Gateway and VirtualService resources.gateway
field), only the hosts defined in the Gateway resource will be allowed to make it to the VirtualService.red.example.com
and green.example.com
:apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- 'red.example.com'
- 'green.example.com'
hosts
field, you can define one or more hosts you want to expose with the gateway. In this example, we are specifying the host with an FQDN name (e.g., red.example.com
). We could optionally include a wildcard character (e.g. my-namespace/*
) to select all VirtualService hosts from my-namespace
. You can think of the list of hosts in the Gateway resource as a filter. For example, with the above definition, you are filtering the hosts down to red.example.com
and green.example.com
.apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: red
spec:
hosts:
- 'red.example.com'
gateways:
- gateway
http:
- route:
- destination:
host: red.default.svc.cluster.local
port:
number: 80
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: green
spec:
hosts:
- 'green.example.com'
gateways:
- gateway
http:
- route:
- destination:
host: green.default.svc.cluster.local
port:
number: 80
hosts
in the VirtualService. Gateway uses the values in the hosts
field to do the matching when the traffic comes in.red.example.com
as an example. We make the following request:$ curl -H "Host: red.example.com" http://$GATEWAY_URL
hosts
field in the Gateway resource), then, because we have a VirtualService with a matching host attached to the gateway, the traffic makes it to the destination (red.default.svc.cluster.local
).blue.example.com
, we get back a 404. That's because we didn't specify that host name in the Gateways' hosts field. Even if we deployed a VirtualService that is attached to the gateway and has blue.example.com
defined in its host field, we'd still get back a 404.Try it out
- Install Istio.
- Label the
default
namespace for sidecar injection. - Deploy the Green and Red applications:
kubectl apply -f https://raw.githubusercontent.com/peterj/color-app/main/examples/green.yaml
kubectl apply -f https://raw.githubusercontent.com/peterj/color-app/main/examples/red.yaml
- Create the Gateway, and VirtualServices:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- 'red.example.com'
- 'green.example.com'
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: red
spec:
hosts:
- 'red.example.com'
gateways:
- gateway
http:
- route:
- destination:
host: red.default.svc.cluster.local
port:
number: 80
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: green
spec:
hosts:
- 'green.example.com'
gateways:
- gateway
http:
- route:
- destination:
host: green.default.svc.cluster.local
port:
number: 80
kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
to get the GATEWAY_URL.Note
You can refer to Expose a Kubernetes service on your own custom domain article to learn how to do that.
green.example.com
:$ curl -H "Host: green.example.com" http://$GATEWAY_URL
<link href="/css/style.css" rel="stylesheet" type="text/css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500&display=swap" rel="stylesheet">
<div class="main" style="background-color:#10b981; color:#FFFFFF">
<h1>GREEN</h1>
</div>
red.example.com
as your host.