Deploy an app with Nomad service discovery
Service discovery is a method of automatically detecting services running on a host machine with the intent of making them available to other services connected to the host. Tools that offer these functionalities expose the service's address and port for communication by way of a service name or endpoint. Consul is one of these tools that takes care of routing requests sent to the service name endpoint and forwarding them on to the application running on a specific host and port.
Nomad offers an easy-to-use integration with Consul that abstracts away a lot of the configuration necessary for service discovery, requiring only a few lines of configuration in the Nomad job spec file.
However, this means that Consul must either be installed separately alongside Nomad on the host or running somewhere else, such as in HCP. Including Consul in your environment adds another layer of complexity to the deployment and, depending on the application, additional complexity that may not be worth the effort.
Nomad v1.3 added built-in native service discovery (SD), making Consul or other third-party tools unnecessary. Nomad's service discovery is not meant to be a replacement for those tools. Rather, it is an alternative for easier testing and deployments with simpler architectures.
Read on to see how you can easily connect your services together that are running in Nomad.
Prerequisites
For this tutorial, you will need:
- Nomad v1.3.3 or later installed locally
- Terraform v1.2.0 or later installed locally
- An AWS account with credentials set as local environment variables and an AWS keypair
- An AMI available in your AWS region created by following the steps in the Nomad Cluster Setup on AWS tutorial
Note
This tutorial creates AWS resources that may not qualify as part of the AWS free tier. Be sure to follow the Cleanup process at the end of this tutorial so you don't incur any additional unnecessary charges.
Service discovery usage
The Nomad job spec file defines services and service queries but you can also interact with the catalog and find information about services through the Nomad CLI tool. Each of these options are shown in the examples below.
Service definition
The service
block enables a Nomad service for discovery by setting the provider
attribute to nomad
. By default, the value is set to consul
implicitly.
Service query
A template
block can specify a function to query a service's address and port. This is a similar procedure for querying services registered in Consul. The following example uses the nomadService
function.
Service commands
Once a service is registered, you can interact with it via the service
command of the Nomad CLI.
Load balancing
Nomad balances service workloads by selecting an allocation of the referenced service (e.g. database
) when the upstream service (e.g. product-api
) allocation is created. Nomad selects from available allocations of the referenced service that have not previously been selected from any of the upstream service’s currently active allocations.
HashiCups with Nomad SD
In this tutorial, you will deploy HashiCups, a demo coffee shop application made up of several microservices running on Docker. Each of the services configured in the HashiCups job spec file use the native service discovery feature to retrieve downstream service connection information.
Additionally, you will modify the application after the initial deployment to integrate the load balancing feature of the native service discovery.
You can read more about the HashiCups application in the HashiCups overview.
Clone the example repository
The example repository contains Terraform configuration to set up a cluster and a Nomad job spec file (hashicups.hcl
) containing the entire HashiCups application.
Clone the example repository.
Navigate to the cloned repository folder.
Check out the v0.1
tag of the repository as a local branch named nomad-hashicups-sd
.
Deploy Nomad cluster
Rename the example variables file from terraform.tfvars.example
to terraform.tfvars
.
The module in main.tf
requires an Amazon Machine Image (AMI) for provisioning the cluster's servers and clients. Copy the AMI ID that you created as part of the prerequisites and replace the placeholder value for ami
in the terraform.tfvars
with it.
Replace the region
and key_name
values with the AWS region that contains the AMI from above and SSH key registered in that region. Replace the allowlist_ip
value with a range of IP addresses if you want to limit access to the virtual machines.
Finally, generate UUIDs for the nomad_consul_token_id
and nomad_consul_token_secret
and replace the placeholder values for them in terraform.tfvars
.
Provision the Nomad cluster
Initialize Terraform so that it retrieves any required plugins and sets up the workspace.
Provision the resources. Respond yes
to the prompt to confirm the operation and then press the Enter key to start the process. This will take a few minutes to provision.
Set up access to Nomad
Run the post-setup.sh
script to complete the setup process.
Note
The Consul UI may take some time to finish setting up and becoming responsive. If the post-setup.sh
script fails, wait a minute, make sure the Consul UI is up, and run rm nomad.token && ./post-setup.sh
to delete the empty token file and try again.
Copy the export
commands from the output, paste them into your terminal, and press the Enter key.
Finally, verify connectivity to the cluster by running a Nomad command.
Add security groups for HashiCups
The Nomad cluster module sets up the minimum amount of ingress rules necessary for Nomad and Consul to function by opening up access to Consul on port 8500 and Nomad on port 4646 through AWS security groups. Additional rules for the HashiCups ports (80
, 3000
, 5432
, 8080
, 8081
, and 9090
) need to be added for the application to run properly.
Open the secgroups.tf
file, add the following configuration to the end of it, and save the file. This attaches the security group defined in the same file to the Nomad clients running in the cluster.
Run Terraform again to update the client machines. Respond yes
to the prompt to confirm the operation.
Deploy HashiCups
The hashicups.hcl
job spec file configures the HashiCups application.
Submit the job file to Nomad. Some services may report as unhealthy at first but will become healthy soon after.
Note
If you are running a Nomad cluster that is not on AWS, you will need to use a different attribute for each of the services' addresses because the attr.unique.platform.aws.public-ipv4
attribute is specific to AWS. For local dev clusters, you can use attr.unique.network.ip-address
. Check the Client Detail page in the Nomad UI to see a full list of the available attributes.
When the deployment is complete, list the HashiCups services.
Inspect the nginx
service, copy the public address listed, and open it in your browser to see the HashiCups application.
Enable service load balancing
To see the service load balancing available in Nomad, you will modify the HashiCups job spec to create an additional instance of the frontend
and nginx
services. Each of the nginx
services will communicate with a different instance of frontend
.
Modify the HashiCups job
Open hashicups.hcl
. Add the count
attribute to the frontend
service group.
Then, add the same attribute to the nginx
group.
Finally, in the template
block of the nginx
group, add a line for the $allocID
variable and modify the nomadService
to match the highlighted example below. Save the file.
Submit the job file to Nomad.
When the deployment is complete, inspect the nginx
service. Note that there are two instances. Copy each address and open them in a different browser tab.
Scroll down to the bottom of the page. The text in the footer shows which instance of the frontend
service the Nginx instance is using. Note that they are different as Nomad attaches each one to a specific nginx
instance during the job creation process.
Note
If you notice that both pages are displaying the same frontend instance name, your browser may be caching the result. In this case, try a hard refresh of the page or open it in a private browser window. If that still doesn't work, you can try stopping and deleting the job with nomad job stop -purge hashicups
and resubmitting with nomad job run hashicups.hcl
.
Next steps
In this tutorial, you learned about the native service discovery present in Nomad and deployed an application that uses it.
Continue onto the next tutorial in the collection to learn how to convert from Nomad to Consul service discovery.