This is no longer needed with ECS.
This project has been created to facilitate the creation of microservices on top of AWS ECS.
Some of the tenets are:
You need a private hosted zone in Route53 to register all the containers for each service.
To create an ECS cluster with all the required configuration and the Route53 domain and the example microservices you can use the CloudFormation template.
You should create a Lambda function to monitor the services, in case a host fails completely and the agent cannot delete the records. You can also use the Lambda function to do HTTP health checks for your containers.
Create a role for the Lambda function, this role should have full access to Route53 (at least to the internal hosted zone), read only access to ECS, read only access to EC2 and to your VPC. The Lambda function needs to call the AWS APIs and should be added to a subnet that provides internet access via a NAT gateway and should have a security group that allows the respective outbound traffic.
Example CloudFormation template:
"LambdaRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version" : "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Principal": {
"Service": [ "lambda.amazonaws.com" ]
},
"Action": [ "sts:AssumeRole" ]
} ]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",
"arn:aws:iam::aws:policy/AmazonRoute53FullAccess",
"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"
],
"Policies": [
{
"PolicyName": "ecs-read-only",
"PolicyDocument": {
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:Describe*",
"ecs:List*"
],
"Resource": "*"
}
]
}
}
],
"Path": "/"
}
}
Create a Lambda function using this code, you can modify the parameters in the funtion:
ecs_clusters
: This is an array with all the clusters with the agent installed. You can leave it empty and the function will get the list of clusters from your account.check_health
: Indicate if you want to do HTTP Health Check to all the containers.check_health_path
: The path of the Health Check URL in the containers.You should then schedule the Lambda funtion to run every 5 minutes with the python3.6
runtime.
Once the cluster is created, you can start launching tasks and services into the ECS Cluster. For each task you want to register as a microservice, you should specify an environment variable in the task definition, the name of the variable should be SERVICE_<port>_NAME
, where <port>
is the port where your service is going to listen inside the container, and the value is the name of the microservice with the standard scheme _service._proto
(see https://en.wikipedia.org/wiki/SRV_record), for example SERVICE_8081_NAME=_calc._tcp
. You can define multiple services per container using different ports.
You should publish the port of the container using the PortMappings
properties. When you publish the port I recommend you to not specify the HostPort
and leave it to be assigned randomly within the ephemeral port range, this way you could have multiple containers of the same service running in the same server.
When the service starts, and the container is launched in one of the servers, the ecssd agent registers a new DNS record automatically, with the name <serviceName>.servicediscovery.internal
and the type SRV
. For each instance, the agent also creates a new A record to make sure that the host name resolves in the private hosted zone.
You can use this name to access the service from your consumers, Route53 balances the requests between your different containers for the same service. For example in Go you can use:
func getServiceEndpoint() (string, error) {
var addrs []*net.SRV
var err error
if _, addrs, err = net.LookupSRV("serviceName", "tcp", "servicediscovery.internal"); err != nil {
return "", err
}
for _, addr := range addrs {
return addr.Target + ":" + strconv.Itoa(int(addr.Port)), nil
}
return "", errors.New("No record found")
}
We've included an example of usage of the service discovery, the example is composed of the following containers:
curl -u admin:password 127.0.0.1:32804/time/15:04%20Jan%202
curl -u admin:password 127.0.0.1:32799/calc/\(2+2\)*3
You can launch the examples using the CloudFormation template, then you can connect to the portal from a browser and test both microservices and the service discovery.
You can review the Route53 records created by the service (only for time and calc, because portal is not a microservice and it doesn't provide the SERVICE_<port>_NAME
environment variable), and stop a container to see how the Route53 records change automatically.