GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - ql4b/lambda-microvm-dev: A workspace to experiment with AWS Lambda MicroVMs

BranchesTags
Open more actions menu

Latest commit

 

History

26 Commits
26 Commits

Folders and files

NameName
Last commit message
Last commit date
app
app
 
 
infra
infra
 
 
.env.example
.env.example
 
 
.gitignore
.gitignore
 
 
Makefile
Makefile
 
 
README.md
README.md
 
 
activate
activate
 
 
tf
tf
 
 

Repository files navigation

lambda-microvm-dev

A workspace to experiment with AWS Lambda MicroVMs — Firecracker-isolated, snapshot-resumable compute environments that run a container inside a microVM.

  • AWS guide: https://docs.aws.amazon.com/lambda/latest/dg/lambda-microvms-guide.html
  • Getting started: https://docs.aws.amazon.com/lambda/latest/dg/microvms-getting-started.html

Contents

  • What's here
    • How the pieces fit
  • Infrastructure (infra/)
    • Provision
  • Prerequisites
  • Using the Makefile
    • Lifecycle hooks
  • Workflow

What's here

.
├── app/            # the application packaged into the MicroVM image
│   ├── app.js      #   minimal Node HTTP server on :8080
│   ├── Dockerfile  #   FROM node:24-alpine — the container base image
│   └── app.zip     #   built artifact (Dockerfile + app), uploaded to S3
└── infra/          # Terraform: the AWS resources behind the workflow below

How the pieces fit

A MicroVM image is built from two independent layers:

  • Container base image — your Dockerfile's FROM (here node:24-alpine). This is what your app runs on inside the MicroVM.
  • Managed base image — the Lambda-managed MicroVM platform layer (arn:aws:lambda:<region>:aws:microvm-image:al2023-1), supplied separately as base_image_arn. It provides the Firecracker snapshot/boot/resume machinery and the MicroVM OS environment.

Lambda compiles the Dockerfile on top of the managed base, boots the app, and captures a snapshot. run-microvm launches instances from that snapshot.

Infrastructure (infra/)

Terraform provisions, using Cloud Posse modules and the null-label naming convention (<namespace>-<name>-<attributes>):

Resource File Purpose
S3 bucket (…-artifacts) artifacts.tf Stores the zipped app artifact. Private, versioned, SSE-AES256, encrypted-uploads-only.
IAM build role (…-lambda-build) iam.tf Assumed by Lambda MicroVMs at image build time. Trust: lambda.amazonaws.com (sts:AssumeRole + sts:TagSession). Permissions: s3:GetObject on the bucket + CloudWatch Logs.
IAM execution role (…-microvm-exec) iam.tf Assumed by the running MicroVM at runtime. Trust: lambda.amazonaws.com (sts:AssumeRole + sts:TagSession). Permissions: CloudWatch Logs scoped to the runtime log group. Required when runtime logging is enabled.
MicroVM image (aws_lambdamicrovms_image) microvm.tf Built from the S3 artifact + managed base image, CPU arch ARM_64.

Packaging is in Terraform. microvm.tf zips app/ (archive_file) and uploads it (aws_s3_object) on apply — no manual zip/upload needed. The code_artifact.uri pins the uploaded object's versionId, so changing the app source triggers an in-place image rebuild (a new image version, major bump 1.0 → 2.0 → …) rather than a destroy/recreate.

Logging. Two CloudWatch streams, both under /aws/lambda-microvms/<namespace>-<name> (e.g. /aws/lambda-microvms/ql4b-microvm-dev): build logs (image creation, written via the build role) and runtime logs (the app's stdout/stderr). Runtime logging is enabled on run-microvm (--logging), which requires an execution role — hence the …-microvm-exec role above. Tail with aws logs tail /aws/lambda-microvms/ql4b-microvm-dev --follow.

Provision

cp .env.example .env   # then edit: set AWS_PROFILE/AWS_REGION, NAMESPACE, NAME
source ./activate      # loads .env and puts the `tf` wrapper on PATH
tf init
tf apply               # creates the bucket, build role, execution role, image

tf is a thin wrapper (on PATH after source ./activate) that runs terraform -chdir=infra with .env loaded — so run it from the repo root, no cd infra needed.

Per the repo's IaC delivery rule, applies in a shared/graduated stack go through the environment branch, not a local working copy. For this dev stack (local state, no traffic) a hand-apply from a pushed PR is fine.

Prerequisites

  • Terraform ~> 1.15, AWS provider ~> 6.71
  • AWS credentials with permission to create S3/IAM/Lambda-MicroVM resources (set AWS_REGION, or a profile)
  • aws CLI with Lambda MicroVMs support, plus jq
  • The MicroVM artifact bucket and image must be in the same region

Use terraform output -json microvm_image | jq to get the current image ARN.

Using the Makefile

A Makefile at the repo root wraps the whole workflow. Copy .env.example to .env and fill it in, then load the environment (source activate reads .env: AWS_PROFILE, AWS_REGION, the TF_VAR_* values) and drive everything with make:

cp .env.example .env # first time only: set AWS_PROFILE/AWS_REGION, NAMESPACE, NAME
source activate      # sets AWS_PROFILE / AWS_REGION / TF_VAR_* from .env
make help            # list all targets

make init            # terraform init
make plan            # preview infra + image changes
make image           # terraform apply: package app/, upload, build/update image
make image-info      # show the current image (arn, version, state)
make hooks-enable    # enable lifecycle hooks on the image (out-of-band)
make logs            # tail the MicroVM log group (LOG_ARGS="--follow ...")

make run             # run a MicroVM (refuses if one is already tracked; FORCE=1 to override)
make state           # get the running MicroVM's state
make suspend         # suspend the tracked MicroVM (RUNNING -> SUSPENDED)
make resume          # resume the tracked MicroVM (SUSPENDED -> RUNNING)
make list            # list MicroVMs (RUNNING by default; STATE=ALL for all)
make token           # mint an auth token (TOKEN_MINUTES=30 by default)
make call            # curl the endpoint (mints a short-lived token)
make terminate       # terminate the tracked MicroVM (or MICROVM=<id>) + clear state

The lifecycle targets are stateful: make run records the microvmId and endpoint in a gitignored .microvm/ directory, so state, token, call and terminate operate on it without passing IDs around. make run refuses if AWS_REGION isn't set (i.e. you forgot source activate), and also refuses if a tracked MicroVM is still live — pass FORCE=1 to launch another anyway, or make terminate the current one first. make terminate MICROVM=<id> terminates a specific MicroVM (handy for orphans shown by make list); it only clears the local .microvm/ state when that id matches the tracked one.

make run's idle policy is overridable — tweak a single field or replace the whole blob:

make run MAX_IDLE=60                        # maxIdleDurationSeconds
make run AUTO_RESUME=false SUSPENDED=120    # autoResumeEnabled + suspendedDurationSeconds
make run IDLE_POLICY='{"autoResumeEnabled":true,"maxIdleDurationSeconds":10,"suspendedDurationSeconds":5}'

Likewise LOG_GROUP= overrides the runtime log group and TOKEN_MINUTES= the auth-token lifetime.

make run enables runtime logging: it reads the execution role ARN from the execution_role_arn Terraform output and passes it as --execution-role-arn alongside --logging (required together). App logs go to /aws/lambda-microvms/<namespace>-<name>; override the group with make run LOG_GROUP=/my/group (the execution role's permissions are scoped to the default group, so a custom group may need the policy widened).

Lifecycle hooks

Reference: microvms-launching-lifecycle-hooks

The app (app/app.js) runs a second HTTP server on port 9000 that answers the MicroVM lifecycle hook paths (/aws/lambda-microvms/runtime/v1/{ready,validate, run,resume,suspend,terminate}), logs each call, and returns 200. Hooks let the app react to build/run/suspend/resume/terminate transitions.

Enable them on the image (then exercise and observe via the logs):

make hooks-enable                          # re-submit the image with --hooks (new version)
make run RUN_PAYLOAD='{"session":"abc"}'   # /run fires with this payload
make suspend                               # /suspend fires
make resume                                # /resume fires
make terminate                             # /terminate fires
make logs LOG_ARGS="--since 15m"           # each hook logs a line

Notes:

  • RUN_PAYLOAD requires hooks — run-microvm rejects a runHookPayload unless the image has the run hook enabled (run make hooks-enable first), otherwise: ValidationException: The run hook must be enabled ....
  • Enabling any runtime hook requires /ready — the default HOOKS config enables it; the app answers it, so the build succeeds.
  • Out-of-band, by necessity. The Terraform provider's aws_lambdamicrovms_image has no hooks/logging/resources arguments yet (hashicorp/terraform-provider-aws#49821), so hooks are applied with update-microvm-image. Terraform doesn't track them: a no-op tf apply preserves them, but a rebuild driven by a changed code_artifact.uri (i.e. editing app/) resets them to null — re-run make hooks-enable after such a rebuild.

Typical loop:

make image && make run && make call
# ... iterate on app/ ...
make image && make run && make call
make terminate

Workflow

The end-to-end loop, using the make targets. Run source ./activate once per shell first.

  1. Build / update the image — package app/, upload, and build (or rebuild) the MicroVM image:

    make image
    make image-info        # arn, version, state
  2. Run a MicroVM — launch an instance from the current image (with runtime logging + execution role wired in automatically); the id and endpoint are saved under .microvm/:

    make run
    make state             # poll until state is RUNNING
  3. Call it — hit the endpoint (mints a short-lived auth token for you):

    make call | jq
    # {
    #   "status": "ok",
    #   "path": "/",
    #   "microvm": { "image_name": "ql4b-microvm-dev", "image_version": "3.0" }
    # }

    The GET <url> banner prints to stderr, so piping stdout to jq parses the response cleanly (use make call 2>/dev/null | jq to hide the banner too). Need a longer-lived token (e.g. for your own curl)? make token.

  4. Inspect logs — application stdout/stderr (and build logs) in CloudWatch. make logs tails the log group; append CLI flags via LOG_ARGS:

    make logs                                    # tail recent events
    make logs LOG_ARGS="--follow"                # live tail
    make logs LOG_ARGS="--since 3h --format short"
  5. Tear down — terminate the MicroVM and clear local state:

    make terminate

Iterating on the app is just steps 1–3 again (make image && make run && make call).

About

A workspace to experiment with AWS Lambda MicroVMs

Resources

Readme
Activity
Custom properties

Stars

0 stars

Watchers

0 watching

Forks

0 forks
Report repository

Releases

Packages

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.