Register and monitor external services with Consul ESM
Consul's service discovery features are a versatile solution for monitoring application health, tracking services and nodes, and keeping a current catalog of healthy service instances. When you register your services to Consul or monitor your application health with distributed checks, a Consul client agent runs on the same node as your service. This client agent performs service and node health checks for the Consul servers and provides a local interface with the Consul DNS service.
Consul binary releases support a wide range of platforms and architectures, allowing many kinds of services and nodes to join a datacenter. However, there are situations where it may not be possible to install a Consul agent on the node that hosts a service. In these situations, the node must run outside of the Consul datacenter. Examples of these external services include:
- third-party SaaS services, such as Amazon RDS or Azure Database for PostgreSQL
- legacy services that do not permit installing third-party software on the node
- services managed by other teams, where you do not have access to the underlying node
In this tutorial, you will learn how to register an external service to your Consul datacenter and make it discoverable using the Consul DNS interface. You will accomplish these tasks using Consul External Service Monitor (ESM), a tool that helps run health checks and update the status of those health checks in the catalog.
Tutorial scenario
This tutorial uses HashiCups, a demo coffee shop application made up of several microservices running on VMs.
Your Consul datacenter will interact with four HashiCups services:
- NGINX runs on a node named
hashicups-nginx-0
- Frontend runs on a node named
hashicups-frontend-0
- API runs on a node named
hashicups-api-0
- Database runs on two nodes named
hashicups-db-0
andhashicups-db-1
At the start of the tutorial, the NGINX, Frontend, and API services are already registered in Consul catalog and are discoverable by their downstream services with Consul DNS. The two instances of the database service are not registered in the Consul catalog because they run on external nodes that cannot join the datacenter.
As a result, the API service is configured to communicate with one of the database instances using its IP address.
The node consul-esm-0
is also registered with the Consul catalog, but starts with no services running.
The initial scenario in this tutorial includes a Consul datacenter with HashiCups deployed. There are two instances of the Database service running on nodes that are not registered with Consul.
Because HashiCups requires the API service to communicate with the database service, the API service uses the IP address of one of the database nodes. Without the Consul agent, it is not possible to load balance between two different nodes.
Prerequisites
This tutorial assumes you are already familiar with Consul and its core functionalities. If you are new to Consul refer to refer to the Consul Getting Started tutorials collection.
If you want to follow along with this tutorial and you do not already have the required infrastructure in place, the following steps guide you through the process to deploy a demo application and a configured Consul service mesh on AWS automatically using Terraform.
To create a Consul deployment on AWS using Terraform, you need the following:
Clone GitHub repository
Clone the GitHub repository containing the configuration files and resources.
Enter the directory that contains the configuration files for this tutorial.
Create infrastructure
With these Terraform configuration files, you are ready to deploy your infrastructure.
Issue the terraform init
command from your working directory to download the
necessary providers and initialize the backend.
Then, deploy the resources. Confirm the run by entering yes
.
Tip
The Terraform deployment could take up to 15 minutes to complete. Feel free to explore the next sections of this tutorial while waiting for the environment to complete initialization.
After the deployment is complete, Terraform returns a list of outputs you can use to interact with the newly created environment.
The Terraform outputs provide useful information, including the bastion host IP address. The following is a brief description of the Terraform outputs:
- The
ip_bastion
provides IP address of the bastion host you use to run the rest of the commands in this tutorial. - The
remote_ops
lists the bastion host IP, which you can use access the bastion host. - The
retry_join
output lists Consul'sretry_join
configuration parameter. - The
ui_consul
output lists the Consul UI address. The Consul UI is not currently running. You will use the Consul UI in this tutorial to verify services registered in your catalog. - The
ui_grafana
output lists the Grafana UI address. You will not use this address in this tutorial. - The
ui_hashicups
output lists the HashiCups UI address. You can open this address in a web browser to verify the HashiCups demo application is running properly.
Check initial state in Consul UI
Retrieve the Consul UI address from Terraform.
Open the address in a browser.
After accepting the certificate presented by the Consul server, you will land on the Services page.
Notice that the Services page only shows the Consul service and three services for the HashiCups application. The Database service is not registered in the Consul catalog.
Click on the Nodes tab.
The Database nodes do not appear. The consul-esm-0
node appears because a properly configured Consul client agent is already running on the node, even though there is no service running.
Login into the bastion host VM
Login to the bastion host using ssh
.
Configure CLI to interact with Consul
Configure your bastion host to communicate with your Consul environment using the two dynamically generated environment variable files.
After loading the needed variables, verify you can connect to your Consul datacenter.
Verify downstream service configuration
The hashicups-db
service instances are not part of Consul catalog. This means the upstream services that need to connect to them must use their IP address. Verify the configuration for the hashicups-api
service instance.
Login to hashicups-api-0
from the bastion host.
Verify hashicups-api
application configuration.
The host
value for the db_connection
is set to the IP address of one of the hashicups-db
instances. As a result, the HashiCups application is unable to scale by using multiple instances of the Database service, and it is prone to errors if the IP address of the instance changes.
To continue with the tutorial, exit the SSH session to return to the bastion host.
Register external services
In the context of Consul, external services run on nodes where you cannot run a local Consul agent. These nodes might be inside your infrastructure but not directly configurable, such as with a mainframe, virtual appliance, or an unsupported platform. These nodes can also be outside of your infrastructure, such as with a SaaS platform. When registering an external service, it is also necessary to register the node it runs on.
For this reason, the configuration for an external service registered directly with the catalog is slightly different than the one for an internal service registered by an agent. Because this scenario contains two hashicups-db
nodes, you will create two configuration files for the two different nodes and services.
Create the service configuration files
Create the folder that will contain the external service definition.
Retrieve the IP address for the hashicups-db-0
node.
Then, create the configuration for hashicups-db-0
that includes the networking information, service definition, and health check to run.
Complete the same process for hashicups-db-1
. Retrieve the IP address of the node.
Finally, create the configuration for hashicups-db-1
node with relative service and health checks.
Observe the following details in this configuration:
- Because you are defining a node that does not have a local Consul agent, you must include the
Datacenter
value so that Consul knows where to register the node and service. - The node is identified using the
Node
,ID
, andAddress
parameters. - The
NodeMeta
parameter is necessary forconsul-esm
to identify the external nodes that will require periodic health checks.- For Consul ESM to detect external nodes and health checks, set
"external-node": "true"
in the node metadata before you register it. - The
external-probe
field determines if Consul ESM performs regular pings to the node to update its health status.
- For Consul ESM to detect external nodes and health checks, set
- The
Status
field inside theChecks
section is set topassing
. When registering a service, Consul sets the initial status tocritical
and then updates the status after it performs its first health check. In the case of external services, since no health check is performed untilconsul-esm
is running, the service will remain in thecritical
state until you startconsul-esm
process. For the scope of this tutorial, you will register the service with an initial state ofpassing
so that you can avoid downtime in the application. However, we recommend that you register services with acritical
health status in production environments to ensure that service instances are healthy before Consul can route traffic to them.
For a full list of service configuration parameters refer to Services configuration reference and Health check configuration reference.
Register the external services in the Consul catalog
Register the nodes in Consul catalog using the /v1/catalog/register
endpoint. First, register hashicups-db-0
.
If the registration is performed correctly the command will output true
.
Then, register hashicups-db-1
.
If the registration is performed correctly the command will output true
.
Verify service and node registration
After you register the services and nodes, you can verify they are present in the Consul catalog.
Get the list of nodes for your Consul datacenter.
The two new nodes hashicups-db-0-ext
and hashicups-db-1-ext
are now present and in the Meta
section you can verify the external-node
and external-probe
metadata.
Get the list of services for your Consul datacenter.
Verify domain name resolution and load balancing
Once the service is present in the Consul catalog, Consul DNS interface will be able to resolve the service correctly.
Login to hashicups-api-0
from the bastion host.
Verify that you can resolve all instances of hashicups-db
services using Consul DNS interface.
Notice the dig
command returns two IPs. Consul will load balance requests across all available instances of the service.
Verify that you can resolve hashicups-db-0-ext
node using Consul.
Verify you can connect to the first instance of hashicups-db
service using Consul FQDN.
Your output should appear similar to the following example:
To continue with the tutorial, exit the SSH session to return to the bastion host.
You will now stop one instance of the hashicups-db
service and verify Consul behavior.
Login to hashicups-db-0
from the bastion host.
Stop the first instance of hashicups-db
service instance.
To continue with the tutorial, exit the SSH session to return to the bastion host.
Login to hashicups-api-0
from the bastion host.
Verify available instances of hashicups-db
services using Consul.
Notice the dig
command still returns two IPs. This is because health checks are not performed periodically.
Verify your connection to the hashicups-db-0-ext
service instance.
This time the command fails. This failure occurs because Consul has not performed a health check on the service instance yet, so it is still marked as healthy in the catalog.
To continue with the tutorial, exit the SSH session to return to the bastion host.
This completes the first part of the tutorial, where you learned how to register external services with Consul. You also learned how to verify that external services are resolved using the Consul DNS interface. Finally, you learned that you cannot rely on the Consul catalog to return healthy instances of external services.
In the next section of the tutorial you will introduce consul-esm
in your datacenter and use it to periodically check the health of your external services.
Create ACL token for Consul ESM
Consul ESM requires access to several Consul resources to operate properly:
agent:read
- to check version compatibility and calculate network coordinates.key:write
- to store assigned health checks, the path is defined in the configuration file.node:write
- to update the status of each node thatconsul-esm
monitors.node:read
- to retrieve list of nodes that need to be monitored.service:write
- to registerconsul-esm
service defined in the configuration file.session:write
- to acquireconsul-esm
cluster leader lock.
When configuring the ACL policy for consul-esm
, you can decide whether to assign fine-tuned permissions to the token to grant permissions to the specific services and nodes you want to monitor, or to use a more permissive ACL policy that permits consul-esm
to monitor newly added services without the need to modify specific ACL permissions.
First, create the rules for the ACL policy.
Then, create the ACL policy using the rules defined in the previous step.
Finally, create the ACL token for the consul-esm
instance.
After you create the token, export it in an environment variable.
Configure Consul ESM
After you create the ACL token for the consul-esm
agent, create the configuration file.
For a full configuration reference refer to Consul ESM configuration.
Copy the configuration file on the consul-esm-0
node.
That output should be similar to the following example.
Start Consul ESM
To start Consul ESM, log in to consul-esm-0
from the bastion host.
Verify that Consul ESM the configuration was copied to the node correctly.
After you confirm that the configuration is correct, start consul-esm
to run as a long-lived process.
The process starts in the background. You can check the logs for the process in the log file specified in the configuration.
The output verifies that Consul ESM is able to retrieve the two nodes that are going to be monitored, alongside their respective checks. Also, notice that the check for hashicups-db-0
is failing, which is expected because you stopped the service earlier in this tutorial.
To continue with the tutorial, exit the SSH session to return to the bastion host.
Verify service state and load balancing
After Consul ESM starts, verify the UI starts showing a failing instance of hashicups-db
service.
Also notice that a new service, consul-esm
, is now present in Consul catalog.
When the health check marks the service instance as failing, Consul DNS will stop including the instance in the results.
Login to hashicups-db-0
from the bastion host.
The output should appear similar to the following example. You may notice that all request are now forwarded to the healthy instance.
To confirm that Consul ESM reacts to changes in service state, you will now restart the hashicups-db
instance.
Login to hashicups-db-0
from the bastion host.
Start the hashicups-db
instance.
To continue with the tutorial, exit the SSH session to return to the bastion host.
Log in to hashicups-api-0
from the bastion host.
Verify that you can resolve all instances of hashicups-db
services using Consul.
Notice the dig
command returns two IPs. Consul will load balance requests across all available instances of the service.
The same information can be retrieved from Consul UI, where the hashicups-db
service now shows two healthy instances.
Now that Consul ESM takes care of the health monitoring for the external services, you can use Consul service discovery to configure your downstream services.
Restart hashicups-api
to use Consul FQDN instead of IP addresses.
From the output you can verify that now the host
parameter for the DB connection is set to hashicups-db.service.dc1.consul
To continue with the tutorial, exit the ssh session to return to the bastion host.
Monitor an HTTP endpoint with Consul ESM
Some application deployments rely on external HTTP endpoints to retrieve deploy information. These endpoints are usually considered always-on and are not monitored inside the deploy workflow. As a result, errors may occur when a failure in the remote endpoint happens.
Registering these endpoints in the Consul catalog and monitoring them with Consul ESM allows you to standardize your processes and leverage additional Consul features, such as watches and events, to build more resilient workflows.
For example, HashiCorp supports the releases.hashicorp.com and checkpoint.hashicorp.com endpoints. These endpoints are often integrated in the tool installation process when version information is required.
You will now learn how to register those endpoints in Consul and to monitor their health using Consul ESM.
Generate a UUID to use as node ID for the external services.
Create the service definition for an external node with the relative services and health checks configured. First, for releases.hashicorp.com
:
Then, for checkpoint.hashicorp.com
:
Note
These service definitions do not include "external-probe": "true"
in the NodeMeta
field. As a result, Consul ESM will only perform the health checks detailed in the service definition and will not check node health. Because node checks are performed by pinging the external node, we omit the external-probe
parameter to prevent checks from failing when the underlying URL does not support a ping.
Register releases.hashicorp.com
.
The command outputs true
when the registration is performed correctly.
Register checkpoint.hashicorp.com
.
The command outputs true
when the registration is performed correctly.
Update ACL permissions for Consul ESM
If you assigned strict permissions to the Consul ESM ACL token, you must update the token to include permissions for the new nodes and services.
With strict ACLs, Consul ESM is not able to discover the new nodes and services that represent the releases.hashicorp.com
and checkpoint.hashicorp.com
endpoints.
As a result, Consul marks these services with a warning
status when you register them, and Consul ESM is not be able to perform checks on them or to change their status into passing
.
To make Consul ESM able to monitor the services, an extended policy with permissions for nodes and services is required.
Update the policy associated with Consul ESM token to use these new rules.
This command produces no output.
With the right ACL permissions, Consul ESM will automatically pick the new services from Consul catalog and retrieve the health checks to perform. The Consul ESM logs will show some information regarding the update.
To inspect Consul ESM logs, login to consul-esm-0
from the bastion host.
Logs for Consul ESM are stored in the /tmp
folder.
Tip
When adding new external nodes to Consul, Consul ESM may take up to 5 minutes to notice them and start performing the health checks. If the services are still in the `warning` state, wait a few minutes and then try again.After the health checks confirm the health of the new external services, the UI updates to show them as passing.
Destroy the infrastructure
Now that the tutorial is complete, clean up the infrastructure you created.
From the ./self-managed/infrastruture/aws
folder of the repository, use terraform
to destroy the infrastructure.
Next steps
In this tutorial you learned how to register external services to your Consul datacenter and how to access them using the different interfaces provided by Consul: UI, CLI, API, and DNS. You also learned how to use Consul External Service Monitor (ESM) to run health checks over external services and nodes and to keep Consul catalog updated with the results of those health checks.
For more information about the topics covered in this tutorial, refer to the following resources:
- Consul External Service Monitor (ESM)
- Service configuration reference
- Health check configuration reference
To learn more about how Consul service discovery can simplify application deployment and load balancing in your datacenter, refer to the following resources: