Private DNS Service Discovery

Service discovery is a technique for getting traffic from one container to another using the containers direct IP address, instead of an intermediary like a load balancer. It is suitable for a variety of use cases:

  • Private, internal service discovery
  • Low latency communication between services
  • Long lived bidirectional connections, such as gRPC.

Service discovery via DNS generally looks like this:

private subnet private service discovery

Note that in this private architecture there is no public subnet, just a private subnet. Containers inside the subnet can communicate to each other using their internal IP addresses. But they need some way to discover each other’s IP address.

AWS service discovery offers two approaches:

  • DNS based (Route 53 create and maintains a custom DNS name which resolves to one or more IP addresses of other containers, for example http://nginx.service.production Then other containers can send traffic to the destination by just opening a connection using this DNS name)
  • API based (Containers can query an API to get the list of IP address targets available, and then open a connection directly to one of the other container.)

Deploy in an self managed EC2 cluster

Use these templates:
Launch a custom EC2 cluster in a private VPC with a NAT gateway Launch Download
Add a private service discovery endpoint Launch Download
Deploy a private EC2 service with private service discovery Launch Download

Deploy in AWS Fargate

Use these templates:
Launch an AWS Fargate cluster in a private VPC with a NAT gateway Launch Download
Add a private service discovery endpoint Launch Download
Deploy a private Fargate service with service discovery Launch Download

Launch a Cloud9 IDE for testing

Once the service discovery enabled ECS service is launched, you can test out sending a request to it. Because this is private service discovery it can only be accessed from another instance inside the same VPC as your ECS cluster. We need to launch an instance to use for testing:

Use this template:
Launch a Cloud9 IDE in the same VPC Launch Download

Once the template is finished deploying check its outputs section for a link to access the Cloud9 IDE. The IDE will load up and give you access to a shell on a remote EC2 instance that is running inside the VPC, and therefore has access to the private Route 53 DNS records for the service discovery service, and the other instances in your ECS cluster.

Execute the following commands to test out service discovery:

Test the EC2 launch type service discovery

Execute the following command from the Cloud9 IDE to verify that the service discovery service is available:

dig srv nginx.service.production

To test out sending a request to the service you need to use an HTTP agent that supports SRV records. For example the Cloud9 IDE has Node.js available, so execute the following commands to install a SRV compatible HTTP agent:

npm install service-agent
npm install request

And then run the following Node.js code:

var ServiceAgent = require('service-agent'),
    Request = require('request');
 
var request = Request.defaults({
  agentClass: ServiceAgent,
  agentOptions: { service: '' },
  pool: {}
});
 
request('http://nginx.service.production', function(error, result, body) {
  console.log(body);
});

Test Fargate launch type service discovery

Execute the following command from the Cloud9 IDE to verify that the service discovery service is available:

dig nginx.service.production

Because each Fargate container has its own IP address, and the service discovery DNS is using a simple A record we can use a basic curl command to send a request to the service and get the response:

curl nginx.service.production