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! 😅
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! 🤟