Service Discovery

Get started with Service Discovery on LocalStack

Introduction

Service Discovery simplifies the management and discovery of services by locating and connecting to the components and resources that make up their applications. Service Discovery allows for a centralized mechanism for dynamically registering, tracking, and resolving service instances, allowing seamless communication between services. Service discovery uses Cloud Map API actions to manage HTTP and DNS namespaces for services, enabling automatic registration and discovery of services running in the cluster.

LocalStack allows you to use the Service Discovery APIs in your local environment to monitor and manage your services across various environments and network topologies. The supported APIs are available on our API coverage page, which provides information on the extent of Service Discovery’s integration with LocalStack.

Getting Started

This guide is designed for users new to Service Discovery and assumes basic knowledge of the AWS CLI and our awslocal wrapper script.

Start your LocalStack container using your preferred method. We will demonstrate how to create an ECS service containing a Fargate task that uses Service Discovery with the AWS CLI.

Create a Cloud Map service discovery namespace

To set up a private Cloud Map service discovery namespace, you can utilize the CreatePrivateDnsNamespace API. This API allows you to define a custom name for your namespace and specify the VPC ID where your services will be locatedBefore proceeding, make sure to create the required VPC.

To create the private Cloud Map service discovery namespace, execute the following command:

$ awslocal servicediscovery create-private-dns-namespace \
      --name tutorial \
      --vpc <vpc-id>

Ensure that you replace <vpc-id> with the actual ID of the VPC you intend to use for the namespace. Upon running this command, you will receive an output containing an OperationId. This identifier can be used to check the status of the operation.

To verify the status of the operation, execute the following command:

$ awslocal servicediscovery get-operation \
      --operation-id <operation-id>

The output will consist of a NAMESPACE ID, which you will need to create a service within the namespace.

Create a Cloud Map service

After creating the private Cloud Map service discovery namespace, you can proceed to create a service within that namespace using the CreateService API This service represents a specific component or resource in your application.

To create a service within the namespace, execute the following command:

$ awslocal servicediscovery create-service \
      --name myapplication \
      --dns-config "NamespaceId="<Namespace-ID>",DnsRecords=[{Type="A",TTL="300"}]" \
      --health-check-custom-config FailureThreshold=1

Upon successful execution, the output will provide you with the Service ID and the Amazon Resource Name (ARN) of the newly created service. These identifiers will be useful for further operations or integrations.

Create an ECS cluster

To integrate the service you created earlier with an ECS (Elastic Container Service) service, you can follow the steps below.

Start by creating an ECS cluster using the CreateCluster API. Execute the following command:

$ awslocal ecs create-cluster \
      --cluster-name tutorial

Register a task definition

Next, you will register a task definition that’s compatible with Fargate. Create a file named fargate-task.json and add the following content:

{
    "family": "tutorial-task-def",
        "networkMode": "awsvpc",
        "containerDefinitions": [
            {
                "name": "sample-app",
                "image": "httpd:2.4",
                "portMappings": [
                    {
                        "containerPort": 80,
                        "hostPort": 80,
                        "protocol": "tcp"
                    }
                ],
                "essential": true,
                "entryPoint": [
                    "sh",
                    "-c"
                ],
                "command": [
                    "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' >  /usr/local/apache2/htdocs/index.html && httpd-foreground\""
                ]
            }
        ],
        "requiresCompatibilities": [
            "FARGATE"
        ],
        "cpu": "256",
        "memory": "512"
}

Register the task definition using the RegisterTaskDefinition API. Execute the following command:

$ awslocal ecs register-task-definition \
      --cli-input-json file://fargate-task.json

Create an ECS service

To create an ECS service, you will need to retrieve the securityGroups and subnets associated with the VPC used to create the Cloud Map namespace. You can obtain this information by using the DescribeVpcs API. Execute the following command to retrieve the details of all VPCs:

$ awslocal ec2 describe-vpcs

The output will include a list of VPCs. Locate the VPC that was used to create the Cloud Map namespace and make a note of its VpcId value.

Next, execute the following commands to retrieve the securityGroups and subnets associated with the VPC:

$ awslocal ec2 describe-security-groups --filters Name=vpc-id,Values=vpc-<ID> --query 'SecurityGroups[*].[GroupId, GroupName]' --output text

$ awslocal ec2 describe-subnets --filters Name=vpc-id,Values=vpc-<ID> --query 'Subnets[*].[SubnetId, CidrBlock]' --output text

Replace <VpcId> with the actual VpcId value of the VPC you identified earlier. Make a note of the GroupId and SubnetId values.

Create a new file named ecs-service-discovery.json and add the following content to it:

{
    "cluster": "tutorial",
    "serviceName": "ecs-service-discovery",
    "taskDefinition": "tutorial-task-def",
    "serviceRegistries": [
       {
          "registryArn": <ARN_OF_THE_SERVICE_DISCOVERY>
       }
    ],
    "launchType": "FARGATE",
    "platformVersion": "LATEST",
    "networkConfiguration": {
       "awsvpcConfiguration": {
          "assignPublicIp": "ENABLED",
          "securityGroups": [ "sg-*" ], // Add the security group IDs here
          "subnets": [ "subnet-*" ] // Add the subnet IDs here
       }
    },
    "desiredCount": 1
}

Create your ECS service using the CreateService API. Execute the following command:

$ awslocal ecs create-service \
      --cli-input-json file://ecs-service-discovery.json

Verify the service

You can use the Service Discovery service ID to verify that the service was created successfully. Execute the following command:

$ awslocal servicediscovery list-instances \
       --service-id <service-id>

The output will consist of the resource ID, and you can further use the DiscoverInstances API. This API allows you to query the DNS records associated with the service and perform various operations.

To explore the DNS records of your service and perform other operations, refer to the AWS CLI documentation for comprehensive instructions and examples.

Using filters

Filters can be used to narrow down the results of a list operation. Filters are supported for the following operations:

Using list-namespaces you can filter for the parameters TYPE, NAME, HTTP_NAME. Using list-services it is only possible to filter for NAMESPACE_ID. Both list-services and list-namespaces support EQ (default condition if not specified) and BEGINS_WITH as conditions. Both conditions and only support a single value to match by. The following examples demonstrate how to use filters with these operations:

$ awslocal servicediscovery list-namespaces \
    --filters "Name=HTTP_NAME,Values=['example-namespace'],Condition=EQ"
$ awslocal servicediscovery list-services \
    --filters "Name=NAMESPACE_ID,Values=['id_to_match']"

The command discover-instance supports parameters and optional parameters as filter criteria. Conditions in parameters must match return values, while if one ore more conditions in optional parameters match, the subset is returned, if no conditions in optional parameters match, all unfiltered results are returned.

This command will only return instances where the parameter env is equal to fuu:

$ awslocal servicediscovery discover-instances \
    --namespace-name example-namespace \
    --service-name example-service \
    --query-parameters "env"="fuu"

This command instead will return all instances where the optional parameter env is equal to bar, but if no instances match, all instances are returned:

$ awslocal servicediscovery discover-instances \
    --namespace-name example-namespace \
    --service-name example-service \
    --optional-parameters "env"="bar"