Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building services with Serverless, AWS Lambda a...

Building services with Serverless, AWS Lambda and DynamoDB

An introduction to Serverless architectures covering the following topics:

- Serverless architecture in general
- The Serverless framework
- AWS Lambda
- AWS DynamoDB
- AWS API Gateway

Torsten Heinrich

March 07, 2018
Tweet

More Decks by Torsten Heinrich

Other Decks in Programming

Transcript

  1. 3 Agenda 1. Serverless 2. AWS Lambda 3. AWS DynamoDB

    4. AWS API Gateway 5. Demo 6. Q&A
  2. 6 Serverless as an architecture • Serverless architecture is defined

    by stateless compute containers and modelled for an event-driven solution. (https://github.com/anaibol/awesome-serverless) • Serverless functions allow you to NOT think about servers. Which means you no longer have to deal with over/under capacity, deployments, scaling and fault tolerance, OS or language updates, metrics and logging. (https://github.com/anaibol/awesome-serverless) • Serverless functions are about running backend code without managing your own server systems or your own server applications. (https://martinfowler.com/articles/serverless.html)
  3. 7 Principles 1. No provisioning or managing of servers 2.

    No lock-in on a specific framework or library 3. Deployment can be as simple as uploading a zip file 4. Scaling is automatically handled by the provider 5. Functions are triggered by events (event-driven) 6. (Usually) easy integration with other services of the provider
  4. 8 Characteristics • Serverless functions are stateless • Simple transformation

    of input to output • Can use databases, caches or file storage (DynamoDb, Redis, S3) • Very short-lived • Usually only a couple hundred milliseconds or lower • There’s always some startup latency • Watch out for cold starts • Statically typed/compiled languages have a much higher startup time (up to 100x)
  5. 10 Characteristics • Often used to together with API gateways

    • The gateway maps HTTP requests and triggers the function with an event • Function call results are mapped to HTTP responses • You still need a good Ops culture • Debugging, monitoring and testing can be challenging • You only pay for what you actually use
  6. 12 Platforms • AWS Lambda (Java, Node.js, C#, Python, Go)

    • Google Cloud Functions (Node.js) • Azure Functions (C#, Node.js, F#, Java, experimental) • IBM Cloud Functions, based on Apache OpenWhisk (Node.js, Swift, Python, Java, PHP, Go) • Webtask.io (Node.js)
  7. 14 Serverless as a framework • Node.js CLI toolkit to

    create, deploy and operate serverless architectures • Supports multiple providers (AWS, Azure, IBM, Google Cloud) • Open-source (https://github.com/serverless/serverless) • Extensible with plugins (https://github.com/serverless/plugins) • Good community support (meetups, user groups, gitter, slack)
  8. 15 Services • Part of your project that defines functions,

    events and other resources • Defined in a serverless.yml template • Every project requires at least one service, more are possible • Initially created by running serverless create --template aws-nodejs --path sample • Every service translates to one CloudFormation template and stack with one API Gateway
  9. 16 Services service: serverless-test provider: name: aws runtime: nodejs6.10 region:

    eu-west-1 memorySize: 128 environment: DYNAMODB_APPS_TABLE: apps-${opt:stage, self:provider.stage} iamRoleStatements: - Effect: Allow Action: - dynamodb:Query - dynamodb:Scan - ... Resource: ...
  10. 17 Functions • Found in the functions section of the

    service template • The handler property defines the file and the module that gets executed • The signature of a function is module.exports.handler = function(event, context, callback) {} • It’s possible to override provider settings on a function level • Permissions are defined on a provider level using the iamRoleStatements or role properties • The environment property defines environment variables • The onError property defines a SNS/SQS Dead Letter Queue (DLQ)
  11. 18 Events • Found in the events section of each

    function • A function can be triggered by multiple events • Each event type requires specific information • An API Gateway http event requires path (/apps) and method (POST) • An S3 event requires bucket and event (s3:ObjectCreated:*)
  12. 19 Events functions: apps-create: handler: apps/create-mock.create events: - http: path:

    apps method: post cors: true apps-delete: handler: apps/delete-mock.delete events: - http: path: apps/{id}/releases/{release} method: delete cors: true
  13. 20 Deployment • Triggered by simply running serverless deploy •

    Creates a single CloudFormation templates • Runs the template to create a stack plus an S3 bucket for the functions • Functions are packaged (zip-compressed) and uploaded to the bucket • The template is updated with roles, functions, events and other resources • The stack is updated based on the final template • To show deployment progress, use serverless deploy —verbose • To force a deployment, use serverless deploy —force • To deploy a single function only, use serverless deploy function --function handler • To update the configuration only, use serverless deploy --update-config
  14. 21 Testing • Apply best practices during development • Separate

    business logic from infrastructure code • Use dependency injection • Use serverless invoke or serverless invoke local to test your functions • Requires a —function/-f argument for the function name • Provides a —data/-d or —raw argument for event data • Provides a —log/-l argument to output logging data • Mock of run AWS services locally • DynamoDB Docker images, Kinesalite (https://github.com/mhart/kinesalite), AWS SDK Mock (https://www.npmjs.com/package/aws-sdk-mock)
  15. 24 AWS Lambda • Serverless function in AWS • Available

    in all regions • Regional service • Supports Node.js (v4.3 and v6.10), Java (v8), Go (v1.x), C# (.NET Core v1.0 and v2.0) and Python (v2.7 and 3.6) • Use Lambda@Edge (AWS CloudFront plus Lambda) for global, latency-sensitive services (only Node.js) • Free tier includes 1M requests and 400k GB-s per month (128 MB ~ 900h, 1024 MB ~ 100h) • Execution duration is rounded up to the nearest 100ms
  16. 25 Environment • Based on container infrastructure similar to EC2

    • Containers based on Public Amazon Linux AMI, currently kernel version 4.9.75-25.55.amzn1.x86_64 • AWS SDK (JS, Python 2.7 and 3.6) and OpenJDK 8 available by default • Execution context is reused for some time (currently 30m, up from 5m) • Be aware of cold starts • Be aware of concurrent cold starts • Memory, language and package size affect cold start time
  17. 27 Execution • Asynchronously invoked Lambda function are retried twice

    before being discarded • Define a Dead Letter Queue (DLQ) to send unprocessed events to an AWS SQS queue or AWS SNS topic • Environment variables can dynamically configure your Lambda functions • Automatically encrypted with AWS KMS after deployment and decrypted on invocation • Custom encryption with AWS KMS before deployment possible
  18. 28 Anatomy • The handler function itself having three parameters

    • The event that triggered the Lambda function • The context containing information about the current runtime • context.getRemainingTimeInMillis() returns the remaining execution time before timeout • context.functionName holds the name of the function • context. memoryLimitInMB holds the memory limit • contect.logGroupName/logStreamName hold CloudWatch logs information • An optional callback to return information to the caller
  19. 29 Anatomy { "path": "/sample", "headers": { "Accept": "application/json", ...

    }, "pathParameters": { "proxy": "sample" }, "requestContext": { "stage": "test", ... }, "resource": "/{proxy+}", "httpMethod": "GET", "queryStringParameters": { "sample": "sample" } }
  20. 30 Anatomy const repository = require('repositories/apps') module.exports.create = (event, context,

    callback) => { // extract the request body const data = JSON.parse(event.body) // save to the database const app = repository.save(data) // return the response return callback(null, { statusCode: 201, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Credentials": true }, body: JSON.stringify(app) }) }
  21. 31 Default Limits • Disk capacity (/temp): 512 MB •

    Execution duration: 300s • Request/response body size: 6 MB • Deployment package size (.zip/.jar/.dll): 50 MB • Raw package size (uncompressed): 250 MB • Environment variables: 4 KB • Concurrent executions: 100
  22. 34 AWS DynamoDB • Managed NoSQL database in AWS •

    Not actually a database, just tables • Provides a HTTP RestAPI • Provides encryption at rest using AWS KMS (AES-256, us-east/west, eu-east) • Provides on-demand backups and restores (us-east/west, eu-east) • Provides TTL functionality • Runs on SSD and spread across multiple availability zones • Use global tables to keep them in sync across regions
  23. 35 Tables • Require the following information: • Name: unique

    for account and region, 3 to 255 characters (a-Z, 0-9, _, -, .) • Primary key: either single partition key or partition key and sort key • Throughout settings • Support the following data types: • Scalar: string, number (signed, 38 digits precision), binary, boolean, null • Document: lists (unordered) or maps (ordered), up to 32 levels deep • Sets: numbers, strings or binaries (unique type and values, ordered)
  24. 36 Tables { "TableDescription": { "AttributeDefinitions": [ { "AttributeName": "id",

    "AttributeType": "S" }, { "AttributeName": "release", "AttributeType": "N" } ], "TableName": "apps", "KeySchema": [ { "AttributeName": "id", "KeyType": "HASH" }, { "AttributeName": "release", "KeyType": "RANGE" } ], "ProvisionedThroughput": { "ReadCapacityUnits": 10, "WriteCapacityUnits": 5 } } }
  25. 37 Primary keys • Partition key as single primary key

    • Input to an internal hash function, determines the physical partition • Partition key value must be unique, allows efficient queries • Partition and sort key as composite primary key • Input to an internal hash function, determines the physical partition, sorted by sort key • Partition and sort key values combined must be unique, allow flexible queries • Can only be defined on table creation
  26. 38 Provisioned throughput • One read capacity is 1 strongly

    consistent read per second for 1 item up to 4 KB (2 for eventual consistent reads) • Eventual consistent read are enabled by default • One write capacity is 1 write per second for 1 item up to 1 KB • Item size is rounded up to the next 4/1 KB • Reads/writes exceeding the throughput are throttled (retries with exponential backoff) • Throughput can be changed automatically (auto-scaling) or manually (AWS Console, CLI, API) • 10 PRCU = 10 SCR/s = 20 ECR/s (items <= 4 KB) • 10 PRCU = 5 SCR/s = 10 ECR/s (items > 4kB, <= 8 KB)
  27. 39 Partitions • Tables are stored in multiple partitions, replicated

    across multiple availability zones • Table data should be spread uniformly across all partitions • Selection and uniformity of the primary key • Workload patterns • A single partition supports up to 3k read capacity units or 1k write capacity units • Initial number of partitions: (RCP / 3k) + (WCU / 1k), (6k / 3k) + (.5k / 1k) = 2.5 ~ 3 • Partitions are split once provisioned throughput or storage requirements are changed • Once split, data and throughput is evenly distributed across new partitions
  28. 40 Partitions 2k RCU, 1k WCU, 10GB 1k RCU, .5k

    WCU, 5GB 1k RCU, .5k WCU, 5GB
  29. 41 Secondary indexes • Global secondary indexes (GSI) • Partition

    key and (optional) sort key both different from the base table • Global as in spanning all the data of the base table • Local secondary indexes (LSI) • Partition key same as base table, sort key different • Local as in scoped to the partition of the partition key in the base table • Only string, number or binary attributes of the base table • Changes to the base table are distributed automatically • GSI requires additional attributes to be projected • GSI can be created on-the-fly
  30. 42 Default Limits • Provisioned throughput • us-east-1: 40k read/write

    capacity units per table, 80k per account • others: 10k read/write capacity units per table, 20k per account • Tables: 256 per account • Indexes: 5 local and global secondary indexes per table • Keys: • partition keys: 1 Byte to 2 KByte • sort keys: 1 Byte to 1 KByte
  31. 45 AWS API Gateway • A service to create, deploy

    and manage RESTful API • Exposes HTTP endpoints, AWS Lambda functions or other AWS services • API endpoints can be edge-optimised (default) or regional • Supports custom domain names • Supports versioning • Supports usage plans, API keys and custom authorisation
  32. 47 Method execution • Method request • Defines incoming HTTP

    method, path, headers and query strings • Supports models (JSON Schema) • Supports authorisation using AWS IAM, Amazon Cognito or custom authorisers • Supports validation of request parameters and body • Integration request • Supports different types (Mock, AWS Lambda, HTTP, AWS services) • Supports mapping templates • Can be pass-through or proxy
  33. 48 Method execution • Integration response • Maps status code

    patterns • Supports mapping templates • Method response • Defines outgoing status code and mapping of integration response headers and body • Supports mapping templates and models • Can be pass-through • Possible to define a designated error handling response
  34. 49 Deployment • A deployment makes the API accessible to

    the end user • Each deployment refers to a stage • Stages are snapshots including all resources and allow for proper versioning • Each stage enables caching, default throttling and SDK generation (Java, JavaScript, Objective-C, Swift and Ruby) • Supports canary releases (percentage-based)
  35. 50 Security • Custom authorisers support AWS Cognito user pools

    or a Lambda function • User pools authorisation excepts an identity token as a header • Custom Lambda functions offer two possibilities: • Token-based expecting a custom header (JWT, OAuth) • Request-based expecting a custom header, query string or context parameter • Policies returned by a Lambda function can be cached • Usage plans and API keys enforce rate limits and quota • API keys can be added to usage plans, usage plans can be added to stages
  36. 52 Swagger integration • Import a Swagger API definition by

    using the restapi:import API action or apigateway import-rest- api CLI command • Export a Swagger API definition by using apigateway get-export or the console • Update an API Gateway by using the restapi:put API action • Supports merge and overwrite modes • API Gateway defines various different Swagger extensions • x-amazon-apigateway-authorizer • x-amazon-apigateway-gateway-responses • x-amazon-apigateway-integration
  37. Q&A

  38. 55 References • https://serverless.com/ • https://github.com/serverless/guide • https://docs.aws.amazon.com/lambda/latest/dg/welcome.html • https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html

    • https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html • https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html