IBM Cloud Code Engine is the easiest way to deploy and run your source code or container on the IBM Cloud. Our goal has always been to allow you to focus on the development of the application code itself, while Code Engine manages the underlying infrastructure.
Part of that infrastructure is automatically providing a secure and reliable HTTPS endpoint for your application, which includes DNS routing and TLS certificates. Once your application is deployed, it will be accessible via a generic URL like this: https://<myapp>.<randomcharacters>.<region-name>.codeengine.appdomain.cloud. By configuring domain mappings, you can also expose your Code Engine application on your own domain, meaning it would be accessible via https://<myapp>.<mydomain>
This setup is great to serve an application that may reside in a specific region of the world for your localized users. However, if your audience is global, there is a slight issue. All requests will be routed to one specific IBM cloud data center. Assuming you’ve chosen the Frankfurt MZR for your deployment, users in Australia or South America will have to deal with some latency. For a personal or hobby application that might not be a big deal, but it could become an issue for enterprise-grade applications.
To address these use cases, we will combine Code Engine with another IBM Cloud service—IBM Cloud Internet Services (CIS)—that provides capabilities for exposing internet applications in a secure, scalable and reliable manner.
In this blog post, we’ll demonstrate how one specific CIS capability called DNS-based geo-locational routing can be used to reduce latency for a globally distributed Code Engine application and achieve high availability using multiple regions.
Let’s start by creating a Cloud Internet Services instance in your IBM Cloud account. Start by navigating to the appropriate place in the Catalog. There is a free 30-day trial available that provides enough capabilities for our setup.
After your instance is created, you will need to add your domain to it. This process includes delegation of the domain management to Cloud Internet Services. The full set of steps is described in Add and configure your domain. If you haven’t done this already, then it is time for a cup of coffee, because the propagation of DNS records can take a few minutes up to a couple of hours.
Once your domain is ready for use in Cloud Internet Services, it’s time to decide which domain to use to serve your application. Let’s assume your domain is “example.com” and you allowed your CIS instance to control it in the step above. Obviously, you can use any other domain name, but example.com is what we’ll use for this blog post.
Note: From now on, this example will assume that “example.com“ was handed over to CIS and uses “global-app.example.com” as the domain name for the application. Make sure that you adjust sample commands when you copy them from the following steps.
certbot certonly --manual --preferred-challenges dns --emailwebmaster@example.com --server https://acme-v02.api.letsencrypt.org/directory --agree-tos --domain global-app.example.com
In the next step, we’ll set up the same Code Engine application in three projects that are distributed across the world in three different IBM Cloud regions. I suggest that you take one region that is near to your current location and two locations that are far away. Since I’m located in Europe, I will use Frankfurt, Sao Paolo and Sydney.
Go to Code Engine’s project page, and create three projects. You may want to use a common naming pattern and a shared tag like shown in the screenshot below:
Next, we’ll go into all of three projects and create a simple application:
We now have the same Code Engine application running in three regions that are mapped to the same domain. Next, we need to make sure that Cloud Internet Services distributes the load to these three regions.
Let’s move over to Cloud Internet Services and configure a health check that is suitable for the application:
Please see Setting up health checks for more information.
As a next step, let’s define one origin pool per region:
After the origin pool is saved, it will initially be shown with critical health. After around two minutes (at most), it should change to healthy. A manual page refresh in your browser may be necessary to see the status update.
Before moving on to the next section, make sure to create an origin pool for each region that you want to address.
Finally, you can set up the load balancer:
And that’s it. We have set up an application that will be routed to the nearest Code Engine region.
Open your domain in your browser. Using the CE_DOMAIN environment variable, you can see which Code Engine region you are targeting. If the region does not match your expectation, it could have one of these reasons:
Public internet services such as https://www.iplocation.net/ can help you to determine where the IP address that you are using to connect to the internet is located.
I ended up, as expected, in Frankfurt.
Now, let’s do an exercise. Let’s assume there is a regional problem, and for whatever reason, your application is down in one region. Will CIS still route the request?
Let’s delete the Code Engine application in the region that is currently being targeted. In my case, I am deleting the “global-app” from the Code Engine project in Frankfurt. Directly after the app is deleted, refresh the browser. Assuming you were quick enough, you will now see a failure. At this point in time, the target application in Frankfurt is down, but the health check that runs in Cloud Internet Services every 60 seconds by has not yet determined this. Eventually, the endpoint will be functional again. You now reach the Code Engine region that is the second priority original pool in the geo route. In my case, this is Sydney..
Note: 60 seconds is the default and the minimum interval for the Cloud Internet Services Free and Standard plans. You can reduce this to five seconds in the advanced options of the health check if you are using an enterprise plan.
You can now recreate the application in Code Engine including the domain mapping. While creating the domain mapping, you can select the existing secret that still exists assuming you did not delete it. After at most a minute, the app will be served again from Frankfurt.
Note: Browsers will, by default, reuse the existing connection. Given the other region is still alive, you may still get the response from there (in my case, from Sydney). A browser restart may be required to force using a new connection. Alternatively, use another browser or curl from the command line.
We have set up an IBM Cloud Code Engine application in several IBM Cloud regions and used its domain mapping feature together with IBM Cloud Internet Services to set up a global endpoint that is routed by geo location to provide optimized latency and high availability.
What’s next?
If you have feedback, suggestions, or questions about this post, please reach out to us on StackOverflow by using one of the following tags “ibm-cloud” or “ibm-cloud-code-engine“.