This document discusses serverless computing on AWS using AWS Lambda and AWS Fargate. It provides an overview of the anatomy of an AWS Lambda function, including the handler function, event and context objects, dependencies and common helper functions. It also describes how to structure serverless applications using Lambda functions and how AWS Lambda layers can be used to share common code between functions. Finally, it outlines the architecture of running serverless containers on AWS Fargate without having to manage servers or clusters.
10. Security
Ensuring the security of the infrastructure that is underlying customer containers is
our primary tenet
Availability and scalability
This includes maintaining both uptime of running containers and elasticity of the
platform to support rapid scale-out and scale-in of containers with high reliability
Operational efficiency
Maintain high resources utilization of the underlying fleet to reduce operational
costs for the business
AWS Fargate design tenets
11. AWS Fargate data plane
Container runtime
Fargate agent
Physical server
Amazon EC2 instance
12. AWS Fargate control plane
Cluster
tasks
Available &
checked-out
instances
Front-end
service
Cluster manager
subsystem
Capacity manager
subsystem
Entry point
data plane and drives
14. Amazon EKS on AWS Fargate architecture
podagents
pod as
running
capacity
scheduler scheduler
scheduler
name
profile
pod
cluster
server
15. AWS Fargate VPC integration
172.31.0.0/16
Subnet
172.31.1.0/24
Internet
Other entities in VPC
EC2 LB DB etc.
Private IP
172.31.1.164
Launch your Fargate tasks into subnets
Under the hood
• We create an elastic network interface
• The network interface is allocated a
private IP from your subnet
• The network interface is attached to your task
• Your task now has a private IP from your subnet
You can assign public IPs to your tasks
Configure security groups to control inbound and
outbound traffic
Network interface Fargate
taskPublic /
208.57.73.13 /
VPC
16. Cluster
permissions
Application
permissions
Task
housekeeping
permissions
Cluster
Fargate task
Cluster permissions
Control who can launch/describe tasks in your cluster
Application permissions
Allows your application containers to access AWS
resources securely
Housekeeping permissions
Allows us to perform housekeeping activities around
your task
• Amazon ECR image pull
• Amazon CloudWatch Logs pushing
• Network interface creation
• Register/deregister targets into ELB
AWS Fargate IAM permission types
18. Anatomy of an AWS Lambda function
Your function
Language runtime
Execution environment
Lambda service
Compute substrate
19. Anatomy of an AWS Lambda function
Your function
Language runtime
Execution environment
Lambda service
Compute substrate
20. Anatomy of an AWS Lambda function
Handler() function
Function to be executed
upon invocation
Event object
Data sent during Lambda
function invocation
Context object
Methods available to
interact with runtime
information (request ID,
log group, more)
import json
def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello World!')
}
21. Serverless applications
Event source Function
Node.js
Python
Java
C#
Go
Ruby
Runtime API
Changes in
data state
Requests to
endpoints
Changes in
resource state
22. Anatomy of an AWS Lambda function
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Your handler
23. Anatomy of a Lambda functionImport sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Your handler
24. Anatomy of a Lambda functionImport sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Your handler
Dependencies, configuration information,
common helper functions
25. Pre-handler code, dependencies, variables
• Import only what you need
• Where possible, trim down SDKs and other
libraries to the specific bits required
• Pre-handler code is great for
establishing connections, but be
prepared to then handle
reconnections in further executions
• Remember – execution
environments are reused
• Lazily load variables in the global scope
• Don’t load it if you don’t need it – cold starts
are affected
• Clear out used variables so you don’t run into
leftover state
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event,
context) {
....
26. Anatomy of a Lambda functionImport sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Your handler
Dependencies, configuration information,
common helper functions
27. Anatomy of a Lambda functionImport sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionB(thing){
## logic here
}
Business logic sub-functions
Your handler
Dependencies, configuration information,
common helper functions
Common helper functions
28. Anatomy of a serverless application
/orders
/forums
/search
/lists
/user
/...
Amazon API
Gateway
AWS Secrets
Manager /
Parameter Store
Amazon
DynamoDB
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
29. Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Pre-handler-secret-getter() {
}
Function Pre-handler-db-connect(){
}
Function subFunctionA(thing){
## logic here
}
Function subFunctionA(thing){
## logic here
}
Dependencies, configuration
information, common helper functions
Common helper functions
Business logic sub-functions
Your handler
AWS Secrets
Manager /
Parameter Store
Amazon
DynamoDB
Anatomy of a serverless application
Amazon API
Gateway
/orders
/forums
/search
/lists
/user
/...
There could be a lot of
duplicated code here!
30. AWS Lambda layers
Lets functions easily share code: Upload layer
once, reference within any function
Layer can be anything: Dependencies, training
data, configuration files, etc.
Promotes separation of responsibilities, lets
developers iterate faster on writing business logic
Built-in support for secure sharing by ecosystem
31. Using AWS Lambda layers
• Put common components in a ZIP
file and upload it as a Lambda layer
• Layers are immutable and can be
versioned to manage updates
• When a version is deleted or
permissions to use it are revoked,
functions that used it previously
will continue to work, but you
won’t be able to create new ones
• You can reference up to five layers,
one of which can optionally be a
custom runtime
Lambda
layers
arn:aws:lambda:region:accountId:layer:shared-lib :1
Lambda
layers
arn:aws:lambda:region:accountId:layer:shared-lib:2
Lambda
layers
arn:aws:lambda:region:accountId:layer:shared-lib:3
32. AWS Secrets
Manager /
Parameter Store
Amazon
DynamoDB
Anatomy of a serverless application
/orders
/forums
/search
/lists
/user
/...
Amazon API
Gateway
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Dependencies, configuration information,
common helper functions
Common helper functions
Business logic sub-functions
Your handler
Your handler
Your handler
Your handler
Your handler
Your handler
33. AWS Secrets
Manager /
Parameter Store
Amazon
DynamoDB
Anatomy of a serverless application
/orders
/forums
/search
/lists
/user
/...
Amazon API
Gateway
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Import sdk
Import http-lib
Import ham-sandwich
Pre-handler-secret-getter()
Pre-handler-db-connect()
Function myhandler(event, context) {
<Event handling logic> {
result = SubfunctionA()
}else {
result = SubfunctionB()
return result;
}
Function
Dependencies, configuration information,
common helper functions
Common helper functions
Business logic sub-functions
Your handler
Your handler
Your handler
Your handler
Your handler
Your handler
34. Learn to build modern applications on AWS
Enable rapid innovation by developing your skills in designing,
building, and managing modern applications
Resources created by the experts at AWS to help you build and validate developer skills
Validate expertise with the AWS Certified DevOps –
Professional or AWS Certified Developer – Associate exams
Learn to modernize your applications with free digital training and
classroom offerings, including Architecting on AWS, Developing on
AWS, and DevOps Engineering on AWS
Visit the developer learning path at aws.amazon.com/training/path-developing
Title/description: Application-first with containers and AWS Lambda
Target audience: Developers, Infrastructure engineers
Services covered: AWS Fargate, AWS Lambda
1/ Our customers tell us that most of their effort goes into characterizing the low-level scaling and operating characteristics of the infrastructure.
2/ If you’re building in small teams and these teams have ownership of the pieces of software they’re working on, then they may end up with large number of infrastructure components they need to manage. How should you think about running your applications on such a distributed architecture?
3/ We spend a lot of time thinking about how can we help remove this complexity? These days the question we increasingly ask ourselves is “what do developers really need to build their applications?”
What does this mean? Based on what we’ve learnt from our customers it means identifying the right abstractions at every layer of the stack and removing accidental complexity wherever we can. Specifically this means
1. Hiding infrastructure abstractions. You want to build your business logic, not have entire teams trying to figure out how to manage infrastructure
2. You want to focus on the desired behavior of the application and let us manage the undifferentiated heavylifting of the infrastructure.
3. You don’t want to spend time thinking about how applications should be deployed onto your infrastructure, which ones should run next to each other, etc.
1/ If it isn’t abundantly clear by now, we believe serverless is the one of the key answers to that question, at least from an operational perspective.
2/ With Fargate and Lambda there are no cluster pets, no decisions around how to pack applications onto nodes, no decisions around the number of nodes in a cluster or how you may want to set up clusters of machines for each team, and you don’t have to figure out your optimal placement strategy. These are all decisions that the service makes based on goals.
3/ That’s what you pay for, put in an auto scaling groups, and have to think about which kind of instance, etc. Some people start with Fargate from day 1.
4/ We see more than 40% of new customers who use our container services start with Fargate.
So we talked about ECS, Fargate, and Lambda and so the serverless operations model looks like this
1/ You can start at the very bottom with EC2 and have access to all the knobs you want to manage or you could go completely serverless with lambda and Fargate where you’re focusing just on your application.
2/ So the layers of abstractions available to you with AWS is super empowering because your teams have the choice to pick the layer of abstraction they’re most comfortable with and we will provide you the tools, services, and APIs necessary to help you build your application
1/ AWS Fargate is a serverless compute engine for containers that works with both Amazon Elastic Container Service (ECS) and Amazon Elastic Kubernetes Service (EKS).
2/ Fargate makes it easy for you to focus on building your applications. Fargate removes the need to provision and manage servers, lets you specify and pay for resources per application, and improves security through application isolation by design.
3/ Fargate allocates the right amount of compute, eliminating the need to choose instances and scale cluster capacity. You only pay for the resources required to run your containers, so there is no over-provisioning and paying for additional servers.
4/ Fargate runs each task or pod in its own kernel providing the tasks and pods their own isolated compute environment. This enables your application to have workload isolation and improved security by design. This is why customers such as Vanguard, Accenture, Foursquare, and Ancestry have chosen to run their mission critical applications on Fargate.
Fargate design tenets
Security: Ensuring the security of the infrastructure underlying customer containers is our priority tenet
Availability and Scalability: Both maintaining uptime of running containers and elasticity of the platform to support rapid scale-up and scale-down of container with high reliability
Operational efficiency: Maintain high resource untiliztion of the underlying fleet to reduce operational costs for the business
1/ When you run container on Fargate they run on EC2 instances that live in a Fargate account within a Fargate VPC. We don’t launch these instances in the runtime workflow itself because it’ll take too long to bootup which is unacceptable for startup times
2/ We keep a pool of EC2 instances that are already up and running and as your tasks come in, we put them on one of these
3/ there is a Fargate agent that runs on each Ec2 instance and its task is to communicate with the control plane. And there is a container runtime which is docker which spins up the container.
4/ Networking wise – the primary networking interface for this EC2 instance – eth0 – is in the Fargate VPC because the instance was launched in the Fargate VPC.
5/ when instance gets selected to host a task, we create an elastic network interface – ENI – in your VPC and we attach it to this instance as a secondary network interface.
1/ there are different services that are responsible for different areas of the Fargate control plane system
2/ Frontend service - the public endpoint that you hit when you call run task is hosted by this service responsible for entry point tasks such as authentication, authorization etc.
3/ Cluster manager – keeps track of the cluster and tasks that are running in them. This si the sub-service on the control plane side that communicates with the data plane
4/ capacity manager – responsible of instances – so keeps track of unused available instances in our warmpool and instances that are checked out and hosting tasks.
Lets see how this all comes together
1/ run task comes in and hits frontend service which performs authentication and authorization
2/ Frontend forwards the call to the cluster manager service which adds a record in the database for the new task and mark it as pending
3/ this will then call out to the capacity system to acquire capacity for this task. Capacity manager will find an available instance and reserve it for this task and return capacity ID back to cluster manager
4/ same time, capacity manager service reaches down to the instance that was selected through the Fargate ENI and activates the Fargate agent. The agent then registers with the cluster manager service
5/ Cluster manager send down the task definition and other instructions
6/ Agent bootstraps task containers and send task definition and issue instructions to run.
1/ We recently launched EKS/Fargate. Lets look at the architecture
2/ this also has the control plane and data plane just that the control plane is your EKS cluster that is running the K8s control plane under the hood
3/ Data plane is just a bunch of EC2 instances that are running in a Fargate VPC
4/ Introduced the concept of and EKS Fargate profile – which gives us additional information to launch your EKS pods on Fargate
1/ When you launch your task/pods in Fargate, you specify the subnets within your VPC where you want to launch your tasks
2/ the network interface we provision for your task belongs to that particular subnet so that ensures that your network policies apply as is. Under the hood, we provision an ENI which gets allocated a private IP from your subnet.
3/ You can assign public Iss to your task
4/ Configure security groups to control inbound and outbound traffic
1/ There are 3 different layers of IAM permission types
2/ Cluster permissions: Control who can launch/describe tasks in your cluster
3/ Application permissions: Allows your application containers to access AWS resources securely
4/ Housekeeping permissions: Allows us to perform housekeeping activities around your task
there are different layers - the lambda compute substrate, the execution envrionment, and the code. the substrate is invisible to customers, but the execution environment and runtime is instantiated on demand for scale events, and the function is instantiated for every request. In this case, everything inside the handler is considered part of the function, and everything outside the handler is considered an “initialization call’ and run along with the container initialization.
there are different layers - the lambda compute substrate, the container, and the code. the substrate is invisible to customers, but the container and runtime is instantiated on demand for scale events, and the function is instantiated for every request. In this case, everything inside the handler is considered part of the function, and everything outside the handler is considered an “initialization call’ and run along with the container initialization.
Lambda layers starts allowing developers to upload once, and reuse multiple times. Lambda already lets you package your dependencies, but required you to duplicate it across every function you wrote. We also see customers adopt the pattern of thin wrappers around their core functionality across functions, and layers makes it very easy for customers to reuse code within Lambda. This also lays the foundation for us to do innovate further on behalf of the customer, with how function code gets initialized and loaded.
If you’re ready to continue learning: Live instructor-led courses offer accredited AWS instructors who teach using a mix of presentations, discussion, and hands-on labs
Learn to modernize your applications with courses like Architecting on AWS, Developing on AWS, Advanced Developing on AWS, and DevOps Engineering on AWS
Visit the learning path tailored specifically for the developer role