If you're building a microservice-backed application, a key benefit is separating the concerns of your application across individual microservices, each with its own ability to scale and encapsulate different functionality. The frontend - ostensibly a single-page application running in your user's browser - will need access to the microservices that make up your web application. Each service could be directly accessible to the public web, but that adds security concerns. An API gateway, however, allows for a centralized layer to handle concerns like authentication, traffic monitoring, or request and response transformations. API gateways are also a great way to leverage rate limiting and caching to improve the resilience and performance of your application. is a one-stop shop for deploying microservice-based web applications directly from an existing GitHub or GitLab repo. While Render provides many resources for standing up microservices and databases, one element that is not configurable out of the box is an API gateway - something along the lines of the or the . Although access to an API gateway is not a one-click add-on with Render, it's still possible to get one up and running. Render AWS API Gateway Azure Application Gateway In this post, we're going to walk through how to set up Render for path-based routing so that we can use Kong Gateway in front of our microservices. Let's start with a brief overview of our approach. Overview of our mini-project We'll deploy two simple microservice backends using Render. One will be a Python Flask service, and the other will be a Node.js service built on Express. The anticipated end result is shown in Figure 1. We'll have deployed two private services and one web service, Kong, that will accept and route requests to those private services. From the client's perspective they appear to be interacting with a single application. In reality, they are requesting resources across an ecosystem of microservices. Microservices deployed as private services There are two main types of service deployments in Render: and . Web services are directly accessible to the public web. Private services, on the other hand, are only available within the private cloud inside your Render account's ecosystem. This is a good thing, because it allows you to better control the security and access within your microservice ecosystem. web services private services Both of our microservices will be deployed as private services. Kong Gateway deployed as a web service is a highly performant, open-source, API gateway used in many of the biggest web applications in the world today. While there are many choices for API gateways, Kong stands out for being cloud and application agnostic, highly configurable, and - perhaps most importantly - . Kong fast We'll deploy Kong Gateway as a web service, accessible via the public web. Kong (and Kong alone) will have access to our two private microservices, and we'll configure it to do appropriate request routing. Deploying microservices with Render Let's begin by setting up and deploying our two microservices. "Users" microservice with Python and Flask Flask is a service framework for Python with a low barrier to entry. A single Python file is all we need to get a minimal API up and running with Flask. The code for this service is available at . The following snippet creates a working service with a endpoint that returns a simple JSON response and status code: GitHub /users from flask import Flask, jsonify app = Flask(__name__) @app.route("/users") def root(): return jsonify({'userId': 42}), 200 if __name__ == "__main__": app.run(host='0.0.0.0') An important detail to note is that in order for Render to automatically expose the correct host and port for your service, you must and or . The difference between and is the scope from which incoming requests are accepted. Only requests from the same machine are permitted using which is the conventional loopback address. The address allows requests from any network interface and what we need here to be picked up by Render. make sure you bind your application to 0.0.0.0 not localhost 127.0.0.1 0.0.0.0 127.0.0.1 127.0.0.1 0.0.0.0 To deploy this as a private service in Render, first click the button in your Render dashboard and select your git repo with the Flask app. Set the service and the . All other configuration options can be left as their default values. Alternatively, you can add a file to your repository that configures how this service will be deployed. In our demo, though, we'll walk through the user interface. New Name Start Command render.yaml Render has free tiers all the way to enterprise-level hosting offerings. Choose the one that fits your needs. Select the branch that you wish to deploy and set up the build and start commands. Typically for a Python application, building the app just requires having all the proper dependencies in place. We can do that by running . The command to boot up our service is . pip install -r requirements.txt python app.py Once you are satisfied with your selections, click . Within a few moments, your service will be up and running! Create Private Service Notice the internal service address of your private service: In this case, our service address is . Remember that this is a private service, inaccessible outside of our Render account. http://users-service-1w3d:5000 "Widgets" microservice with Node.js and Express Deploying the Node.js service is nearly the same as with the Python service, though the code required to stand up a Node.js project is more involved. We've built a simple "Widgets Service" with an endpoint at . The code for this service is available at . /widgets GitHub Deploying this as a private service is nearly the same as with a Python Flask service. You will add a new private service from the Render dashboard and work through the options in the UI. The build and start commands are fields to pay close attention to ensure the proper scripts from the file are used to build and start up the application correctly. For this service, the build command needs to install all the dependencies and then build the distribution bundle. This is done using two commands in sequence, like so: . package.json npm install && npm run build The double ampersand means that the first command must finish successfully before the second command begins. This is also an example of how to chain commands in Render forms to achieve multiple actions in a single step. After the build stage completes, we can start the service using the . Again, remember to bind your application to in order for Render to automatically know how to connect to it internally. The port and IP that this service uses are defined in the file and are currently set to . npm run start:prd script 0.0.0.0 src/constants.ts 0.0.0.0:5001 Setting up Kong Gateway We'll deploy Kong as a web service and configure it to route to our upstream private services based on the request path. Kong is often set up in tandem with a database such as PostgreSQL, which holds configuration data for the gateway. There is a simpler setup, though, which Kong calls the " ." In this approach, Kong does not need a database, and the configuration is loaded at the boot of the service and stored in its memory. DB-less declarative configuration Below is a simple configuration file ( ) that configures Kong to route to our private services. All of our Kong-related files are available at . kong.yaml GitHub _format_version: "2.1" _transform: true services: - name: user-service url: http://users-service-1w3d:5000 routes: - name: user-routes paths: - /user-service - name: widget-service The first two lines are required to direct Kong to the correct version and how to use this configuration. The block details all the destinations where we want Kong to route incoming traffic, and that routing is based on the paths set up in the block for each service. You can see here the services list contains the URLs for the two private services deployed to Render. For example, our web service (Kong) will listen for a request to the path and then forward that request to . services paths /user-service http://users-service-1w3d:5000 Deploying Kong in a Docker Container Using Render to deploy Kong will be a little different than our two microservices. We need to deploy it as a web service and use the custom Docker application option during configuration. The following Dockerfile will provide a DB-less instance of Kong which will read in the static configuration above from a file named . This sets up port as the port where Kong will listen for incoming requests. If you use , Render will automatically pick up that port from the Docker image to use with this service. kong.yaml 8000 EXPOSE 8000 FROM kong:2.7.1-alpine COPY kong.yaml /config/kong.yaml USER root ENV KONG_PROXY_LISTEN 0.0.0.0:8000 ENV KONG_DATABASE off ENV KONG_DECLARATIVE_CONFIG /config/kong.yaml ENV PORT 8000 EXPOSE 8000 RUN kong start After connecting your repository with the Kong Dockerfile and configuration files, make sure you select a tier with at least 1GB of RAM and 1 CPU. Kong performs erratically with limited resources on a shared CPU. The remaining default configurations can be left as is. After deployment, your Render dashboard should contain three services: Once Kong has successfully deployed, you can test this setup with or . Issue the following request to ensure proper routing to the and services respectively: curl Postman Users Widgets curl https://kong-gateway-lh8i.onrender.com/widget-service/widgets/10 \ -i -H "kong-debug: 1" The additional header tells Kong to add some debugging information to the response headers. We can use that information to validate a successful setup. You should see something like the following in the response: kong-debug HTTP/2 200 content-type: application/json; charset=utf-8 kong-route-id: 8b2d449d-9589-5362-a2a1-3be5683a8f97 kong-route-name: widget-routes kong-service-id: 6c8de697-474a-54cf-a59e-4ad086047749 kong-service-name: widget-service via: kong/2.7.1 x-kong-proxy-latency: 61 x-kong-upstream-latency: 11 x-powered-by: Express {"widget":"10"} Note the Kong prefixed headers detailing the route and services that were used to route the request to the proper upstream service. Similarly, you can test the services routing with: User curl https://kong-gateway-lh8i.onrender.com/user-service/users \ -i -H "kong-debug: 1" Conclusion In this article, we've explored the cloud hosting solutions provided by Render. Specifically, we walked through how to deploy Kong Gateway as a web service that handles path-based routing to microservices deployed to Render as private services. This deployment pattern can set you up for scalable and flexible production deployments of microservice-backed applications. Also Published Here