Istio Service Mesh: How to easily redirect To external resources
Istio is the best service mesh created so far, though i can't tell if i'm saying it because it's my favorite π. Working with Istio's service mesh and using it in Kuberenetes is super easy thanks to Istio dev team's clear way of explaining how to use it in their documentation.
When working with Istio, I've come across on one interesting challenge, i.e. Forwarding/Redirecting to external Resources. Just to make it clear and interesting, here's the scenario which clarifies the issue. I do have this back-end micro-service in our Istio service based Kubernetes cluster, it's a react project which exposes many URI endpoints to the public. Let's say my current domain name is example.com, and we do have three endpoints which are exposed to the public, (i.e. example.com/home, example.com/about, and example.com/test-redirect). Now, what we need to do is when a request comes to example.com/test-public, It should redirect or forward our request to google.com (this is just a dummy example). So in reality we could may be do that in our back-end service, it cloud be Angular or React, we can redirect it when that specific endpoint has been activated. But we don't want that, what we want is to redirect the URI to google.com before hitting our backend service.
Before moving on, i also want to humbly thank to this big eye creature for helping me out solve this problem. You deserve it chief! π
... yes you bruv! π
Our Solution
My Initial Try
I've started to implement it easily with a VirtualService object of Istio. I thought that by just specifying the exact URI string; which is "/test-redirect" and rewriting it to google.com will work. And guess what; Yep! It didn't work out. π
# This is my initial VirtualService yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-virtual-service
namespace: istio-system
spec:
gateways:
- my-gateway
hosts:
- example.com
http:
- match:
- uri:
exact: "/test-redirect"
rewrite:
uri: "/"
authority: google.com
route:
- destination:
host: google.com
port:
number: 443
- route:
- destination:
host: my-backend-service
port:
number: 80
Our Final Solution
Once i carefully read Istios documentation, i found out that external resources (in our case google.com) should be added to Istio's internal service registry. To do that we use an Object called ServiceEntry. Here's what we should do to add our external resource google.com to our Istio's internal service registry.
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: google
namespace: istio-system
spec:
hosts:
- google.com
location: MESH_EXTERNAL
ports:
- number: 443
name: https
protocol: TLS
resolution: DNS
I think it's really self explanatory if you read that one. We're basically saying we want a host called "google.com" as a mesh-external source saved in our internal service registry for a later use. Also, notice that the ports and protocols assigned, Β port 443 as we're trying to access a secure HTTP. That's all, right, NOPE! There one piece left out.
What's the left out piece?
If you try to access example.com/test-redirect, it'll fail. Why! π€
If you notice, we're redirecting HTTP request to an internal service resource of HTTPS external location (which is google.com in our example). Thus we need some rule to act as a TLS client which uses TLS mode. It'll basically say, requests to the host should be conducted over a TLS connection. We use a special object called DestinationRule to satisfy our need here:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: google
namespace: istio-system
spec:
host: "google.com"
trafficPolicy:
tls:
mode: SIMPLE
Now, It magically works! π€