Istio + gRPC Web + Cert Manager = 🔥(Part 1/2)

Ahmed Nader
Level Up Coding
Published in
5 min readMay 6, 2021

--

I was building a Proof of Concept with gRPC-Web and Istio, but I found little to no resources when it comes to combining them both. Not to mention that the search results became even more scarce when I was looking for resources to encrypt the traffic with HTTPs. This pushed me to create a guide myself.

In part 1, I will be explaining how to use Istio to establish communication between a gRPC backend server and a frontend web client that’s using gRPC-Web. In part 2, I will cover how to secure the communication by encrypting the network traffic between the frontend and the backend with HTTPs.

Source: VMware blog

Before we dive into the technical details, let me first introduce what Istio and gRPC-Web actually are.

Istio is a service mesh implementation that creates, manages and helps in understanding the network between microservices. Istio has a lot to offer when it comes to service-to-service communication such as load balancing, authentication and authorization, monitoring, traceability and a lot more.

gRPC-Web enables web apps to communicate directly with gRPC backend services, without requiring an HTTP server to act as an intermediary. gRPC-Web, just like gRPC, lets you define the service “contract” between client (web) and backend gRPC services using Protocol Buffers.
Since we don’t seem to have native browser support for gRPC anytime soon, gRPC-Web offers a great solution that uses a proxy like Envoy or Nginx to translate the HTTP calls coming from the browser into native gRPC calls to the backend. Istio uses Envoy as its service mesh proxy; hence, we are using Istio in that tutorial.

Enough with the intros, let’s get straight to the interesting stuff.

What we will achieve:

  1. Deploy a single node Kubernetes(k8s) cluster. We will use K3s for the sake of this tutorial.
  2. Download and Install Istio service mesh in the k8s cluster.
  3. Determine Istio’s ingress IP and ports.
  4. Deploy the Frontend, gRPC backend services and Envoy gRPC web filter as k8s objects in the cluster.
  5. Create Istio gateway and Virtual Service
  6. Test the application

Now let’s get our hands dirty!

1) Deploy a k8s cluster:

I will be using K3s for this tutorial which in my opinion is a great reliable and lightweight distribution for K8s, perfect for development and edge (environments with limited resources) deployments. To install it you just need to run
$ curl -sfL https://get.k3s.io | sh -

At the time of writing this tutorial, Kubernetes version 1.20 is used.

2) Download and Install Istio:

To install Istio, the following steps need to be done:

  • $ curl -L https://istio.io/downloadIstio | sh - (At the time of writing this tutorial, Istio version 1.9.3 is used)
  • $ cd istio-1.9.3
  • $ export PATH=$PWD/bin:$PATH
  • $ istioctl install — set profile=demo -y (In case of getting connection refused error on running this command, follow the steps mentioned here, this should solve the issue)
  • Last but not least, we want to instruct Istio to automatically inject its Envoy sidecar proxy in the application:
    $ kubectl label namespace default istio-injection=enabled

3) Determining the ingress IP and ports

Follow the steps below in order to identify the k8s cluster Ingress host and port: (For more details on the below steps, check Istio’s documentation)

$ export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')$ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')$ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT$ echo "$GATEWAY_URL"

This is needed to expose the application outside the cluster and allow communication between the frontend client in the browser and the backend.
Take note of the $GATEWAY_URL, we will need it afterwards.

4) Deploy the Frontend, gRPC backend services and Envoy gRPC web Filter

As the implementation details for the backend and frontend are not the scope of this tutorial, I will be reusing the backend and frontend implemented here.

I created a docker image for the backend and the frontend and will be using them in the following K8s deployment manifests.

To get them running, follow the below steps:

  • Create an account on dockerhub if you don’t have one already.
  • Create a docker registry secret to be able to pull the images:
    $ kubectl create secret docker-registry regcred --docker-username=<your-name> --docker-password=<your-password>
  • Create a new directory and copy the below gists into it.
Envoy Filter
backend deployment and service
frontend deployment and service
  • Replace the value of the environment variable REACT_APP_GATEWAY_URL with the value identified at step 3.
  • Run the following commands in order (Note that the envoy filter needs to be created before the backend service as the filter will be installed on Istio’s sidecar running in the backend pod)
$ kubectl create -f envoy-filter.yaml
$ kubectl create -f grpc-backend.yaml
$ kubectl create -f grpc-web-frontend.yaml
  • Validate the deployment by running $ kubectl get pods A similar output to the below should be observed
NAME                      READY   STATUS    RESTARTS   AGE
server-xxxxxx-xxxxxxxxx 2/2 Running 0 xm
client-xxxxxx-xxxxxxxxx 2/2 Running 0 xm

5) Create Istio gateway and Virtual Service

We need to instruct Istio to configure Ingress traffic to the cluster and route HTTP traffic to the backend. This can be achieved by creating destination rules for the backend and frontend, as well as creating a Gateway and Virtual Service.

As you can see in the below objects definition, the virtual service definition should have rules to route traffic to the backend and frontend.

Create the file below in the project directory then run
$ kubectl create -f gateway.yaml

Istio’s destination rules, gateway and virtual service

6) Test the application

After following the previous steps, we should have a successful deployment for a gRPC backend service and a frontend service that uses gRPC-web to communicate with the backend. Istio’s gateway acts as a proxy the translates the http calls coming from the browser to gRPC calls going the backend.

To validate that flow, open a new browser tab and visit http://$GATEWAY_URL/ui

You should be able to see a simple UI that has reading for temperature and humidity as shown below. The numbers should be changing every 5 seconds or less.

Expected output in the UI

That’s all folks! 🎉

In this part, we were able to

  • deploy a gRPC backend service and Frontend service that uses gRPC web to communicate with the backend.
  • Inject Istio’s sidecar proxy on frontend and backend pods
  • Expose the services with Istio Ingress Gateway
  • Configure Istio’s Ingress gateway to proxy HTTP traffic to the gRPC backend

In part 2, I will explain how to secure the frontend to backend communication with HTTPs using Cert Manager. So stay tuned!

Disclaimer: all yaml files used are not necessarily created for production use. Changes might be needed for them to be used in production.

Resources:

--

--