copyright | lastupdated | ||
---|---|---|---|
|
2019-03-07 |
{:java: #java .ph data-hd-programlang='java'} {:swift: #swift .ph data-hd-programlang='swift'} {:ios: #ios data-hd-operatingsystem="ios"} {:android: #android data-hd-operatingsystem="android"} {:shortdesc: .shortdesc} {:new_window: target="_blank"} {:codeblock: .codeblock} {:screen: .screen} {:tip: .tip} {:pre: .pre}
{: #multi-region-serverless}
This tutorial shows how to configure IBM Cloud Internet Services and {{site.data.keyword.openwhisk_short}} to deploy serverless apps across multiple regions.
Serverless computing platforms give developers a rapid way to build APIs without servers. {{site.data.keyword.openwhisk}} supports automatic generation of REST API for actions, turning actions into HTTP endpoints, and the ability to enable secure API authentication. This capability is helpful not only for exposing APIs to external consumers but also for building microservices applications.
{{site.data.keyword.openwhisk_short}} is available in multiple {{site.data.keyword.cloud_notm}} locations. To increase resiliency and reduce network latency, applications can deploy their back-end in multiple locations. Then, with IBM Cloud Internet Services (CIS), developers can expose a single entry point in charge of distributing traffic to the closest healthy back-end.
{: #objectives}
- Deploy {{site.data.keyword.openwhisk_short}} actions.
- Expose actions via {{site.data.keyword.APIM}} with a custom domain.
- Distribute traffic across multiple locations with Cloud Internet Services.
{: #services}
This tutorial uses the following runtimes and services:
- {{site.data.keyword.openwhisk_short}}
- {{site.data.keyword.cloudcerts_short}}
- IBM Cloud Internet Services
This tutorial may incur costs. Use the Pricing Calculator to generate a cost estimate based on your projected usage.
{: #architecture}
The tutorial considers a public web application with a back-end implemented with {{site.data.keyword.openwhisk_short}}. To reduce network latency and prevent outage, the application is deployed in multiple locations. Two locations are configured in the tutorial.
- Users access the application. The request goes through Internet Services.
- Internet Services redirect the users to the closest healthy API back-end.
- {{site.data.keyword.cloudcerts_short}} provides the API with its SSL certificate. The traffic is encrypted end-to-end.
- The API is implemented with {{site.data.keyword.openwhisk_short}}.
{: #prereqs}
- Cloud Internet Services requires you to own a custom domain so you can configure the DNS for this domain to point to Cloud Internet Services name servers. If you do not own a domain, you can buy one from a registrar such as godaddy.com.
- Install all the necessary command line (CLI) tools by following these steps.
The first step is to create an instance of IBM Cloud Internet Services (CIS) and to point your custom domain to CIS name servers.
-
Navigate to the Internet Services in the {{site.data.keyword.Bluemix_notm}} catalog.
-
Set the service name, and click Create to create an instance of the service. You can use any pricing plans for this tutorial.
-
When the service instance is provisioned, set your domain name by clicking Let's get started and click Add domain.
-
Click Next step. When the name servers are assigned, configure your registrar or domain name provider to use the name servers listed.
-
After you've configured your registrar or the DNS provider, it may require up to 24 hours for the changes to take effect.
When the domain's status on the Overview page changes from Pending to Active, you can use the
dig <your_domain_name> ns
command to verify that the new name servers have taken effect. {:tip}
Exposing {{site.data.keyword.openwhisk_short}} actions through a custom domain will require a secure HTTPS connection. You should obtain a SSL certificate for the domain and subdomain you plan to use with the serverless back-end. Assuming a domain like mydomain.com, the actions could be hosted at api.mydomain.com. The certificate will need to be issued for api.mydomain.com.
You can get free SSL certificates from Let's Encrypt. During the process you may need to configure a DNS record of type TXT in the DNS interface of Cloud Internet Services to prove you are the owner of the domain. {:tip}
Once you have obtained the SSL certificate and private key for your domain make sure to convert them to the PEM format.
- To convert a Certificate to PEM format:
{: pre}
openssl x509 -in domain-crt.txt -out domain-crt.pem -outform PEM
- To convert a Private Key to PEM format:
{: pre}
openssl rsa -in domain-key.txt -out domain-key.pem -outform PEM
- Create a {{site.data.keyword.cloudcerts_short}} instance in a supported location.
- In the service dashboard, use Import Certificate:
- Set Name to the custom subdomain and domain, such as api.mydomain.com.
- Browse for the Certificate file in PEM format.
- Browse for the Private key file in PEM format.
- Import.
In this section, you will create actions, expose them as an API, and map the custom domain to the API with a SSL certificate stored in {{site.data.keyword.cloudcerts_short}}.
The action doWork implements one of your API operations. The action healthz is going to be used later on the check if your API is healthy. It could be a no-op simply returning OK or it could do a more complex check like pinging the databases or other critical services required by your API.
The three following sections will need to be repeated for every location where you want to host the application back-end. For this tutorial, you can pick Dallas (us-south) and London (eu-gb) as targets.
- Go to {{site.data.keyword.openwhisk_short}} / Actions.
- Switch to the target location and select an organization and space where to deploy the actions.
- Create an action
- Set Name to doWork.
- Set Enclosing Package to default.
- Set Runtime to the most recent version of Node.js.
- Create.
- Change the action code to:
{: codeblock}
function main(params) { msg = "Hello, " + params.name + " from " + params.place; return { greeting: msg, host: params.__ow_headers.host }; }
- Save
- Create another action to be used as health check for our API:
- Set Name to healthz.
- Set Enclosing Package to default.
- Set Runtime to most recent Node.js.
- Create.
- Change the action code to:
{: codeblock}
function main(params) { return { ok: true }; }
- Save
The next step involves creating a managed API to expose your actions.
- Go to {{site.data.keyword.openwhisk_short}} / API.
- Create a new managed {{site.data.keyword.openwhisk_short}} API:
- Set API name to App API.
- Set Base path to /api.
- Create an operation:
- Set Path to /do.
- Set Verb to GET.
- Set Package to default.
- Set Action to doWork.
- Create
- Create another operation:
- Set Path to /healthz.
- Set Verb to GET.
- Set Package to default.
- Set Action to healthz.
- Create
- Save the API
Creating a managed API gives you a default endpoint like https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/1234abcd/app
. In this section, you will configure this endpoint to be able to handle requests coming from your custom subdomain, the domain which will later be configured in IBM Cloud Internet Services.
-
Go to APIs / Custom domains.
-
In the Region selector, select the target location.
-
Locate the custom domain linked to the organization and space where you created the actions and the managed API. Click Change Settings in the action menu.
-
Make note of the Default domain / alias value.
-
Check Apply custom domain
- Set Domain name to the domain you will use with the CIS Global Load Balancer such as api.mydomain.com.
- Select the {{site.data.keyword.cloudcerts_short}} instance holding the certificate.
- Select the certificate for the domain.
-
Go to the dashboard of your instance of Cloud Internet Services, under Reliability / DNS, create a new DNS TXT record:
- Set Name to your custom subdomain, such as api.
- Set Content to the Default domain / alias
- Save the record
-
Save the custom domain settings. The dialog will check for the existence of the DNS TXT record.
If the TXT record is not found, you may need to wait for it to propagate and retry saving the settings. The DNS TXT record can be removed once the settings have been applied. {: tip}
Repeat the previous sections to configure more locations.
At this stage, you have setup actions in multiple locations but there is no single entry point to reach them. In this section, you will configure a global load balancer (GLB) to distribute traffic between the locations.
Internet Services will be regularly calling this endpoint to check the health of the back-end.
- Go to the dashboard of your IBM Cloud Internet Services instance.
- Under Reliability / Global Load Balancers, create a health check:
- Set Monitor type to HTTPS.
- Set Path to /api/healthz.
- Provision the resource.
By creating one pool per location, you can later configure geo routes in your global load balancer to redirect users to the closest location. Another option would be to create a single pool with all locations and have the load balancer cycle through the origins in the pool.
For every location:
- Create an origin pool.
- Set Name to app-<location> such as app-Dallas.
- Select the Health check created before.
- Set Health Check Region to a region close to the location where {{site.data.keyword.openwhisk_short}} are deployed.
- Set Origin Name to app-<location>.
- Set Origin Address to the default domain / alias for the managed API (such as 5d3ffd1eb6.us-south.apiconnect.appdomain.cloud).
- Provision the resource.
- Create a load balancer.
- Set Balancer hostname to api.mydomain.com.
- Add the regional origin pools.
- Provision the resource.
After a short while, go to https://api.mydomain.com/api/do?name=John&place=Earth
. This should reply with the function running in the first healthy pool.
To test the fail over, a pool health check must fail so that the GLB would redirect to the next healthy pool. To simulate a failure, you can modify the health check function to make it fail.
- Go to {{site.data.keyword.openwhisk_short}} / Actions.
- Select the first location configured in the GLB.
- Edit the
healthz
function and change its implementation tothrow new Error()
. - Save.
- Wait for the health check to run for this origin pool.
- Get
https://api.mydomain.com/api/do?name=John&place=Earth
again, it should now redirect to the other healthy origin. - Revert the code changes to get back to a healthy origin.
{: #removeresources}
- Remove the GLB.
- Remove the origin pools.
- Remove the health checks.
{: #related}