AWS Developer Tools Blog
Serverless Service Discovery – Part 1: Get Started
AWS provides a lot of features and services for writing serverless architectures with Python. In this four-part series, we will show how you can use Python to manage and implement Amazon API Gateway, AWS Lambda, and Amazon DynamoDB. We will use a common use case, service discovery, to showcase a simple way to do this with Python and boto3. Service discovery is a foundational service for microservices. There are many implementations running on servers or in containers, including Consul by HashiCorp and ZooKeeper from Apache.
This four-part series will cover the following topics:
- Part 1: Get Started: Using Python and Swagger to Deploy to Amazon API Gateway and AWS Lambda
- Part 2: Lookup: Looking Up Service Information in Amazon DynamoDB from AWS Lambda
- Part 3: Registration: Using Signature Version 4 Authentication to API Gateway and AWS Lambda
- Part 4: Registrar: Using a Registrar Agent in AWS Lambda to Manage Service Registration
By the end of the series, we will have built the system shown in this diagram:
Then we will be able to use a client that can look up a Hello World service in the discovery service, and call the Hello World service. We will also implement a registrar agent with the Hello World service that will keep the information about the Hello World service up-to-date in the discovery service.
Today’s post will cover these areas of our overall design:
We will create the basics of setting up a service running on API Gateway and Lambda. So we can do something easy to get us started, for this first step, we will return hard-coded values in the service.
We will create a few functions to make it easy to manage our serverless architecture. These are all of the imports used by management functions in this series:
We set the log level to INFO:
Creating an AWS Lambda Function
We start with a couple of utility methods that will help us package a list of files or directories into a zip file that can be used with AWS Lambda:
The next function will use the package we just created to create the Lambda function:
We read the package into memory and provide it directly to the create_function method that creates our Lambda function. You might want to put a large package in Amazon S3 and then submit a reference to the package.
We need to give permissions to API Gateway to call our Lambda function. We do that using the AWS Lambda resource policies, adding the ARN of the API Gateway service for our account to the Lambda permissions.
Creating an API with Swagger
We again start with a couple of utility methods.
The replace_instances_in_file function allows us to take Lambda function ARNs and put them into specific places in the Swagger file. We will put in a marker string in the Swagger file. This function finds the marker and replaces it with the Lambda ARN.
The get_rest_api_name function allows us to get the name of the REST API specified in the Swagger file so we can use it with calls to the API Gateway API.
In the following function, we are using the newly released API function to import an API defined in Swagger:
Like the creation of the Lambda function, we read the Swagger file into memory and submit it directly to the function.
The last management function deploys the API to an API Gateway stage so we have a public host name that we can use to access the API:
Deploying a Skeleton Service
We are now ready to test the functions with a simple skeleton of our service lookup function. The function is minimal and includes hard-coded values:
Given a service name and a service version, the function will return three values:
- The endpoint URL from which the service can be accessed.
- The time to live (TTL) for this information so that a client knows for how long to cache this information and can avoid unnecessary calls to the service.
- The status of the service, either healthy or unhealthy.
We define the API in a Swagger file for the preceeding Lambda function:
We define our service method as a GET method that will take the service name and service version as part of the path. We have also defined a response model (CatalogServiceModel) that specifies our return properties as the endpoint URL, the TTL, and the status.
The x-amazon-apigateway-integration element specifies how Amazon API Gateway will be integrated with AWS Lambda. The marker $catalog_serviceARN$ will be replaced with the AWS Lambda function ARN when this service is deployed.
We can now use all of the above to deploy our service to Lambda and API Gateway:
We can use this to test our new deployment:
That should give us the following results: