This is a small project that demonstrates how to deploy a lightweight, serverless REST microservice using AWS CDK, AWS SAM, AWS API Gateway V2, and AWS Lambda.
Ultimately, it deploys a REST endpoint in Lambda that returns a simple JSON message:
{
"message": "Automation for the people!",
"timestamp": 1625868715
}
The message is always the same. The timestamp is the number of seconds since the UNIX epoch at the time of execution.
A presentation summarizing this project is available at CDK and SAM-local Are Your Friends
AWS Lambda is used to create a simple Python application that returns a message and a timestamp.
AWS SAM CLI is used to provide a way to test the Lambda in your local environment (CDK support is in beta).
AWS API Gateway V2 is used to create a RESTful HTTP interface to the Lambda.
AWS CDK is used to define the Lambda and API Gateway infrastructure using a minimal amount of code and enable deploying them to AWS.
GNU Make is used to provide a simple interface to many of the commands.
Pylint is used for some simple Python syntax checking.
Pytest is used for some simple unit testing of the Lambda code.
Goss is used for deployment validation -- useful for local and AWS deployments. ✊ Goss Rocks!
Pyenv and pyenv-virtualenv are used to manage Python on the Mac.
Docker enables SAM to run local containers with your Lambda.
aws-vault for AWS credential management with good MFA support.
% make help
make targets:
* local: invoke the Lambda locally
* local-api: run the API locally
* request req: submit a request to the local API service
* dependencies deps: install dev dependencies
* virtualenv: install python 3 and create virtualenv
* requirements reqs: install python3 requirements
* lint: check syntax of python code
* test: run local tests
* unittest: run pytest
* goss-local: run goss local checks (requires `make start-api` running elsewhere)
* goss-remote: run goss remote checks (requires `make deploy` to complete successfully)
* bootstrap: initialize CDK resources in AWS
* build: build local SAM container
* deploy: deploy resources to AWS with CDK
* validate: test the deployed service
* endpoint: Show the Lambda's HTTP endpoint URL
The instructions and Makefile targets here assume development on a Mac with Homebrew installed.
For local development and eventual deployment, you'll need a handful of utilities and python packages.
make deps virtualenv reqs
Build the Lambda locally:
make build
Simple one-off test that invokes the latest Lambda code locally:
make local
Check the code with pylint, ensuring it's valid Python3 and doesn't have too many warnings:
make lint
Start the local version of the API service:
make local-api
With that running, check the local HTTP service with goss in another shell terminal:
make goss-local
You can use Control-C
to exit the make local-api
session.
Ensure you have AWS access credentials configured in an awscli profile.
It's handy to add all of this to a file, say env.sh
(see env.sh.example
):
export AWS_DEFAULT_REGION=_preferred_region_
export AWS_SECRET_ACCESS_KEY=_api_secret_
export AWS_ACCESS_KEY_ID=_api_key_id_
export CDK_DEFAULT_ACCOUNT=_aws_account_id_
export CDK_DEFAULT_REGION=_preferred_region_
and then source it:
source env.sh
Alternatively and arguably better, use 99designs' aws-vault to set up a profile for your chosen AWS environment. The included Makefile assumes you have aws-vault installed and set up. Define an AWS profile and the Makefile will do the rest:
export AWS_PROFILE=some-proile-that-aws-vault-knows-about
Next, prepare your account for deployment and then deploy:
make bootstrap deploy
To validate, query the URL provided as a CDK stack output and verify the response contains both a "message" and "timestamp" field:
make validate
When you're all done, tear it down:
make destroy
This is essentially a tech demo. Even at that level, there are opportunities for improvement:
- Add more documentation in the cdklib and lambda dirs to explain what is happening
- Add unit testing to the cdklib code; only the lambda code has tests now
- Add a GitHub Actions pipeline to deploy the stack to AWS
- Improve the installation and management of requirements. The toolchain required for CDK, SAM, and Python is a mess to install. The Makefile targets assume a Mac environment, but a GitHub Actions env won't target that. Doing everything within a Docker container would surely be simpler, and would probably still allow the use of SAM-local, but it wouldn't facilitate the use-case behind this exercise (breaking Lambda definitions out of CloudFormation templates embedded in Amazon Landing Zone add-ons), so I didn't choose that path initially.