PHP ON LAMBDA
WITH CUSTOM RUNTIMES
PHP UK Conference 2023
Ian Littman / @ian@phpc.social / @iansltx
Follow along at https://ian.im/lambuk23
Questions We'll Answer
- Why you'd use Lambda, and what caveats come with using it
- How Lambda works with Custom Runtimes (including PHP)
- How to build an email reply bot with Lambda, SES, S3, and PHP
- How to build a Lambda-powered API via
- API Gateway
- Function URLs
- Bonus: How to build API Gateway endpoints with Bref
Topics We won't cover
- A deep dive into Bref or Serverless Framework
- Building Lambda applications via AWS's CLI
- AWS SAM
- Laravel Vapor
WHY LAMBDA?
- No servers to manage
- No worrying about concurrency within an app instance
- Quick automatic scaling + high levels of concurrency
- Millisecond-level billing + fair-sized free tier
- Stateless per-request, shared-nothing-ish
thanks to Firecracker microVMs - Integrates with other AWS components
What kinds of integrations?
- Trigger events from S3, SNS, SQS...and a lot more
- Application Load Balancer (billed for capacity + time)
- API Gateway (billed per request)
- You can also call a function...
- directly via AWS's APIs
- over HTTP with Function URLs
Shared-nothing-ish?
- AWS keeps Lambda containers around for a bit
to avoid "cold start" penalties - /tmp storage available per-instance; can use as a cache
- 512 MB by default
- Up to 10 GiB if you pay for it
- Instances != invocations
- Instances == concurrency
A note on performance
- CPU time allocation (speed) scales with RAM allotment
- Minimum: 128 MB
- Maximum:
3008 MB10240 MB - Increment size: 64 MB
- At 1792 MB you have one full core (stop there)
- Up to 6 cores
- Using Serverless Framework (e.g. via Bref)? Default is 1024 MB
- There are a few other limits to keep in mind
A note on Billing
- Billed per GB/s, rounded to the nearest ms
- Includes init (for custom runtimes) and execution,
including I/O wait - Init phase gets you two
- arm64 is cheaper than x86
Virtual Private Caveats
- No internet connectivity by default
-
NAT Gateway is £££ (5¢/hr + 5¢/GB in London region)
- Yes, AWS prices in the London region are in USD cents
- Workaround: split functionality between functions
- Internet-connected, outside VPC (external APIs)
- Internet-disconnected, inside VPC (internal resources)
- Pass info between via queues, S3, etc.
- Cold start times No longer an issue as of late 2019
So, what about PHP on Lambda?
- Custom runtime support has been available since 2018
- Build the file system needed to run your function code
- Store the file system as one or more (up to 5) Layers
- Worker-based, long-polling-esque model
- NOT HTTP request based without additional abstractions
Layers
- Built on top of Amazon Linux 2
- Extracted to /opt (function code is in /var/task)
- Versioned
- Can include library dependencies (e.g. /vendor)
- Zipped + submitted to AWS API (like functions)
- Function specifies inclusion order
Custom runtime lifecycle
- Bootstrap (cold start)
- Task execution (warm start)
- Lambda decides when to kill the instance
- Inactivity timeout
- Task deadline (configurable, up to 15 minutes)
- Initialize runtime
- Prep function for execution
- Pass env vars including file/method for handler function
- If there's an error init-ing, make an API call
Task execution (warm start) Phase
- Call APIs to process work
-
Next invocation (GET)
- Request ID and more in headers
- Task data in response body, JSON-encoded
-
Invocation response (POST)
- Request ID in URL
- Response in body
- Consuming services may require specific format
- Can perform (billed) cleanup between calling response
endpoint and requesting the next invocation
Logging & Errors
- Invocation error (POST)
- STDOUT -> CloudWatch Logs
- Metrics available via CloudWatch (or in function UI)
- Lambda Telemetry API for more advanced metrics
- Slower to start
- Images can be up 10 GB total
-
Still need to interact with the Lambda runtime API
- AWS base images include the Lambda Runtime Interface Client
- AWS provides Runtime Interface Clients for some languages
- ...but not PHP...
- ...and not Node >= 17
- ...so just use the bootstrap files we already have
- You can test with the Runtime Interface Emulator
- No function URL support
What might this look like from AWS's Side?
- Are any workers for target function waiting on work?
- If so, skip to step 3; if not...
- Build a new instance (container or layers + function code)
- Run /opt/bootstrap (or /var/task/bootstrap,
or container entrypoint) - Wait for it to do one of the following
- Return nonzero from the bootstrap (init failure)
- Call the init error API endpoint
- Call the task request API endpoint
- Respond to the next invocation endpoint with event
- Wait for API calls to invocation success/failure or timeout,
whichever comes first
- SES rule pushes email to S3
- S3 triggers Lambda
- Lambda function executes...
- Grabs email from S3
- Parses using MIME parser
- RaNdOMlY CaPiTaLiZeS LEtTerS
- Sends email reply via SES
- HTTP request hits API Gateway
- Lambda function executes...
- Grabs query string parameter if there is one
- RaNdOMlY CaPiTaLiZeS LEtTerS
- Sends a JSON response
- API Gateway turns the Lambda payload into an HTTP response
- HTTP request hits function URL
- Lambda function executes...
- Grabs query string parameter if there is one
- RaNdOMlY CaPiTaLiZeS LEtTerS
- Sends a JSON response
...but you should probably use Bref in prod
For Bref questions, find this guy (@matthieunapoli, @mnapoli@phpc.social)
...or go to bref.sh/docs
...or Vapor, if you're using Laravel
Thanks! Questions?
- https://ian.im/lambuk23 - this presentation
- https://github.com/iansltx/spongebot - sample code
- https://phpc.social/@ian - me
- https://twitter.com/iansltx - also me
- https://github.com/iansltx - my code
PHP on Lambda with Custom Runtimes - PHP UK 2023
By Ian Littman
PHP on Lambda with Custom Runtimes - PHP UK 2023
At re:invent 2018, Amazon released custom runtime support and Layers for their Lambda function-as-a-service runtime. With this release, the fact that the company still doesn't have an official PHP Lambda runtime becomes more or less irrelevant, since we as developers can create our own without undue overhead. This talk will show you how Lambda custom runtimes work, how to build one that speaks PHP, and how to use pre-built custom runtime layers for either one-off job processing or behind a load balancer or API Gateway to serve web traffic with extreme infrastructure elasticity.
- 1,227