





















This repository is an end-to-end demonstration of how to build OCI container images for deployment to AWS Lambda, as well as OpenTofu workspaces to provision the AWS resources. The container images can also run under Docker for local testing. It is designed to be a "concept sketch" of what real infrastructure might look like: more than a ClickOps guide that won't scale, but not a full end-to-end deployment where it's too hard to understand all the moving parts. The idea is that you will be able to map each part of this demonstration onto your IaC and CI/CD processes in a way that makes sense for your tools.
To deploy a Lambda Function to AWS using containers, Lambda needs to told to reference a container image existing in an ECR repository. The cleanest separation I've found for this is to have two distinct workspaces connected by an image build/push step:
scripts/build-and-push-image is the image build/push step. It stands
in for a CI/CD system by building the container images, pushing them
to ECR, and updating a .tfvars.json file with the image tags.
YYYYMMDD-HHMM-abcdef12(-dirty)that
includes date/time information as well as git SHA, so you know
when the image was built, as well as what code it was built
from.
dirty tags immutable so people don't overwrite
them by accident and change behaviour of existing functions;dirty tags and keep them mutable, in case
developers need to push from a dirty worktree in development; and.zip files), to avoid having to
figure out static linking or troubleshoot linker issues in the
Lambda environment.hal library
to interface with Lambda's API; andx86_64-linux onlyTo avoid a rabbit hole of Nix remote-building, cross-compiling, or
other build-system wrangling (QEMU/binfmt_misc, etc.), the
Haskell-based Lambda Functions are built for x86_64-linux
only. aarch64-linux Lambda Functions are about 30% cheaper than
x86_64-linux ones, so when you have enough scale for that to matter,
it might be worth exploring how to do that.
Your infrastructure-as-code workspaces should have their own
permissions to manipulate AWS resources, while the
build-and-push-image script (or your CI/CD system) should only be
allowed to log into ECR and push images. The ECR User Guide has a page
on IAM permissions for pushing an image to an Amazon ECR private
repository.
The image_tags.auto.tfvars.json file only contains image tags, which
are read by the 03-lambda-functions workspace. This makes it easy to
answer "what is this Lambda Function configured to run?" as well as
"what code revision was built, and when was it built?", but if you
need to harden your container workflows (e.g. you are required to use
signed images or audited supply chains) then you'll need to use
digests instead.
Lambda Versions allow you to snapshot function configurations on deploy. Aliases let you create a mutable named reference to one or two Versions (with traffic splitting), and avoids redeploying every integration when you release a new Version. AWS CodeDeploy allows controlled rollouts and rollbacks of Alias changes, by listening to pre- and post-traffic hooks and CloudWatch Alarms. A more mature deployment may want to use one or more of these features.
This means your storage costs will grow slowly but without bound
(e.g., $0.10/GB-month in us-east-1). You should implement some kind
of garbage collection process. I recommend implementing a scheduled
task to do this, perhaps a Lambda Function triggered from EventBridge
Scheduler.
The garbage-collection task might want to look for images that are not referenced by anything and were pushed more than 30 days ago.
$LATEST version);Although the code in this repo works, it's mostly intended to be
read. I've commented everything heavily. Begin by reading workspaces
02-ecr-repositories and 03-lambda-functions, as well as
scripts/build-and-push-image.
If you want to run it yourself, you will need Nix to build the container images and to enter the development shell:
$ nix develop $ <...set up your AWS credentials, however you do that...> $ tofu -chdir=workspaces/02-ecr-repositories apply $ scripts/build-and-push-image server $ tofu -chdir=workspaces/03-lambda-functions apply
Although these resources are not expensive, cleaning them up will prevent AWS from charging you:
$ nix develop $ <...set up your AWS credentials, however you do that...> $ tofu -chdir=workspaces/03-lambda-functions destroy $ tofu -chdir=workspaces/02-ecr-repositories destroy
nix: Nix helpersNix is used to prepare the container images, but your pipeline can use
Docker or whatever else makes sense to you. Two supporting AWS
utilities, the Runtime Interface Emulator
and the Lambda Web Adapter,
are packaged into a nixpkgs overlay so that we can include them in
built images. make-lambda-container.nix packages a binary into a
container while making it invokable locally (via the Lambda API) for
testing. make-lambda-web-container.nix is similar, but packages a
web server instead of a binary that speaks the Lambda APIs.
server: Demo Haskell serverA simple Cabal package that defines a normal Haskell web server (using
servant) and
warp with two endpoints:
/hello will return a static "hello world" JSON blob; and/crash will raise an exception. Useful for testing.simple: Simple AWS Lambda FunctionUses the hal (Haskell AWS
Lambda) package to Implement
a Lambda Function taking requests of the form {"n": "6"} to
{"n_factorial": "720"}. To work on large numbers, they are parsed
and returned as strings in the JSON.
workspaces: OpenTofu workspaces01-your-first-lambdaA simple workspace that creates a JS-based Lambda Function, to show the major moving parts of declaring a Lambda Function in OpenTofu: its log group, the execution role, and the function itself.
02-ecr-repositoriesI believe that uploading container images to Amazon ECR is the best way to use Haskell as the implementation language for AWS Lambda Functions. This workspace declares the ECR Repositories that other workspaces in this repo rely upon.
Each repository will hold the images for a single Lambda Function, and
images will be tagged with the date/time of push (in UTC) as well as a
git short SHA (e.g. 20260520-0919-abcdef12(-dirty)).
Images in these repositories persist forever unless removed.
03-lambda-functionsA workspace that declares Lambda Functions which use OCI images as
their code source. If you are running this locally, you will need to
use scripts/build-and-push-image to build and upload the container
images and populate the
workspaces/03-lambda-functions/image_tags.auto.tfvars.json file
that tells OpenTofu exactly which images to deploy for each function.
scripts: Build/deploy/testing scriptsbuild-and-launch-imageBuild an image and launch it using docker run. You can then test it
locally and terminate it with Ctrl-C.
build-and-push-imageThis script stands in for the build-and-push steps of a CI/CD
pipeline. It reads repository names from the
workspaces/02-ecr-repositories OpenTofu state and passes the computed
image tags down to the workspaces/03-lambda-functions state.
invoke-haskell-lambda-simple-awsInvoke the factorial-computing lambda once it has been deployed to AWS.
invoke-haskell-lambda-simple-localUse curl to invoke the factorial-computing lambda from a locally
running container.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。