API Gateway using Envoy and Docker

Hi Friends,

In this section, we are going to look at API Gateway implementation using Envoy. API Gateway is one of the best way to encapsulate internals of Microservice from outside world. This is the place where we can implement cross cutting concerns like

  • HTTPS Termination
  • Load Balancing
  • Routing
  • Caching
  • Aggregation
  • Logging
  • Transformation
  • etc

Before, jumping to gateway discussion, one point to note here that I have kept everything containerized here say from APIs to envoy as well. And for Microservices, world you should be knowing containers. In case, if you guys new to containers, you can check my course on udemy “Docker for .Net and Angular Developers“. Here, I have covered docker concepts both for .Net and Angular developers in depth.

In this article, we will cover how to achieve HTTPs Termination and Routing using Envoy. You can learn more about this at its portal. Having said that, let’s get started. Here, we are having two different APIs say MoviesAPI and SeriesAPI. Think of these as two different Microservices. Envoy will act as gateway here, whose job is to do routing based on the suffix. For Instance, if request is coming with /movies, it should hit Movies API, if its coming with /series, then it should pick Series API otherwise, it should just land to google.com.




Now, let’s jump at the code and understand its structure first of all.

Github:- https://github.com/rahulsahay19/API-Gateway-Envoy

As you can see, I have very simple two API projects, which is just returning set of movies and series randomly. Both these individual projects are also containerized and it supports both http and https.

For API projects, you can generate the self-signed cert with dotnet dev-certs itself like shown below.

dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\MoviesAPI.pfx -p password!
dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\SeriesAPI.pfx -p password!
dotnet dev-certs https –trust

Upon doing the same, you can see the generated certificate like

Next, we need to is to use these certificates. Therefore, for that I will be creating user secrets for both the applications. This way we can read and apply the certificate in our app. So, for that, we can go to our .csproj file and User Secrets like shown below. I have prefixed with project name so that I can Identify the same.

Then, we need to set the user secrets via dotnet user-secrets set “Kestrel:Certificates:Development:Password” “password!” command. Make sure to keep the password same. So, first we need to execute this command be being in Movies API project next in series project like shown below.

Therefore, there will be two secrets at the end created at location “C:\Users\{your-user}\AppData\Roaming\Microsoft\UserSecrets

If you go into this directory, there will be secrets json file like shown below.

And, if you open the same in notepad, it will have following content.

One point to note here, for APIs, its optional to generate the certificate because will be using HTTPS Termination concept from envoy. But, if you like to test these apps separately on HTTPS, then you need those certificates. That’s why I showed how to create them.

Next, we need to generate the certificate for Envoy as well. And for this, we will be using OpenSSL as we will be extracting key and pem file as well. There are couple of ways to generate self-signed cert using OpenSSL, you can just google that. But I usually follow below steps.

Install OpenSSL using Chocolatey. You first need to install Chocolatey, if you haven’t installed before. Then, you can say choco install openssl -y in powershell. Make sure to run as admin. Once done, then you can create https.config file in system 32 location with below settings.

Then, we can run the following command, openssl req -config https.config -new -out csr.pem This will create the required pem file in system32 location. Afterwards, we can create the certificate using the same. We can do the same using below command. openssl x509 -req -days 365 -extfile https.config -extensions v3_req -in csr.pem -signkey key.pem -out https.crt Once generated, we can take this file and paste the same Envoy directory. Also, we need to import this certificate in our cert store under trusted certificates, otherwise you will get warning while running gateway.

Next, we need to create envoy.yaml file. Below, I have pasted mine finished envoy.yaml file. At first look, it may look over-whelming. But, here, we need to focus on the listener part and cluster rule. For more information on Envoy guidelines, you can obviously refer its site.

This yaml you can take from envoy portal from getting started section. Now, let’s understand the changes here. Basically, envoy starts with listener. Listeners will have filters and filters will have routes. Then, these routes will be mapped to clusters and then clusters will have multiple endpoints. Under the address, I have changed the address to, which means any IP. On the port 9901, admin page will be available. Here, we have static resources. We can also have dynamic resources as well.

Also, here, I have kept two listeners. First listener is without https and 2nd one is with https. Then, under listener, I have virtual hosts which has different routes. For instance, you can see for prefix /movies, its going to cluster movies_service. And, if you go to the cluster section, under movies_service, you will find socket_address. Here, address is my service name for movies api. This you can check, in docker-compose.yaml file. Similarly, for series as well, means address needs to be substituted with your container service name.

Below, I have pasted my finished docker-compose.yaml file for your reference.

If you look at the compose file as well, its also pretty straight forward. First we have two APIs, then we have envoy app. Under envoy, section we are copying the yaml file to the required location.

Having said that, when I run the compose file with docker-compose –build, it will produce the below output. Build flag is to make sure that it will build with my latest changes and use the same rather than pulling from cache.

At this moment, when you do docker ps, you can see below containers in running state.

So, admin portal looks like

And, if I do http://localhost:10000, it will navigate to google like shown below.

Similarly, If I do, https://localhost:10001, then it will also navigate the same page but this time with valid cert, which we imported in our cert store.

Now, If I go to my route say https://localhost:10001/movies, then it will redirect to the Movies API producing the below result.

Similarly, for series as well, https://localhost:10001/series

Having said that, we have successfully setup our API Gateway using Envoy. With this I would like to wrap this here. In coming articles, we will delve further to handle the cross cutting concerns. Till then, stay tuned and Happy Coding.

Rahul Sahay
Happy Coding

Thanks, Rahul Happy Coding