Amazon S3 trigger Lambda to create thumbnail images

Amazon S3 trigger Lambda to create thumbnail images

avatar

Phong Nguyen

2024.03.26

Bài lab này sẽ hướng dẫn cách tạo 1 Lambda function, Lambda này sẽ nhận event từ việc upload 1 image lên source bucket, Lambda sẽ thực hiện resize image và lưu trữ ở destination bucket.

Lab Details

  1. Duration: 30 minutes
  2. AWS Region: US East (N. Virginia) us-east-1

Introduction

  • AWS Lambda is a Serverless Compute service.
  • Lambda cho phép bạn chạy chương trình chỉ bằng cách chuẩn bị code và config nó ở Lambda
  • Ưu điểm của Serverless là bạn không cần quản lý máy chủ, giảm chi phí vận hành.
  • Lambda có cơ chế Auto scaling phù hợp với workload của bạn
  • Lambda có thể liên kết được với vất nhiều server khác ví dụ như
    • API gateway backend bởi Lambda function
    • S3 event notification trigger lambda
    • DynamoDB Stream trigger Lambda
    • EventBridge trigger lambda
    • etc
  • RẺ: miễn phí 1 triệu request đầu tiên
  • Tốc độ thực thi nhanh chóng
  • Support nhiều ngôn ngữ lập trình: Pytho, .NET, Java, NodeJS, Ruby
  • Tăng perfomance bằng cách tăng RAM (up to 10G)

Architecture Diagram

Task Details

  1. Create source and destination Amazon S3 buckets
  2. Create a Lambda function
  3. Configure a S3 event Notification to trigger Lambda function
  4. Test your function

1. Create source and destination Amazon S3 buckets

1.1 Create S3 source bucket

Lưu ý bucket không được trùng tên trong Region, nên hãy đặt tên phù hợp.

  • AWS Region: US East (N. Virginia) us-east-1
  • Bucket name: d-s3-[your-name]-dva-image-source-bucket (Ex: d-s3-cmp-dva-image-source-bucket)

1.2 Create S3 destination bucket

Lưu ý destination bucket name: {source bucket name}-resized

  • AWS Region: US East (N. Virginia) us-east-1
  • Bucket name: {source bucket name}-resized (Ex: d-s3-cmp-dva-image-source-bucket-resized)

Kết quả:

1.3 Upload a test image to your source bucket

Upload 1 image bất kỳ lên source bucket, để lát nữa chúng ta sẽ thực hiện test code lambda với image này

2. Create a Lambda function

2.1 Create a permissions policy

Lambda cần có quyền Access đến S3 (Get và Put), đồng thời phải có các permissions cơ bản như tạo log group, ghi log.

  • Policy name: DVAS3AccessForLambdaPolicy
  • Policy JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:PutLogEvents",
                "logs:CreateLogGroup",
                "logs:CreateLogStream"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::*/*"
        }
    ]
}

2.2 Create an execution role for Lambda

Create Role cho Lambda

  • Trusted entity type: AWS service
  • Use case: Lambda
  • Permissions policies: DVAS3AccessForLambdaPolicy
  • Role name: DVAS3AccessForLambdaRole

2.3 Create the function deployment package

Thực hiện 1 trong 2 cách sau:

  1. Download file .zip Tại đây
  2. Làm theo hướng dẫn sau để đóng gói code và dependencies
  • Tạo file lambda_function.py có nội dung sau:

    import boto3
    import os
    import sys
    import uuid
    from urllib.parse import unquote_plus
    from PIL import Image
    import PIL.Image
                
    s3_client = boto3.client('s3')
                
    def resize_image(image_path, resized_path):
    with Image.open(image_path) as image:
        image.thumbnail(tuple(x / 2 for x in image.size))
        image.save(resized_path)
                
    def lambda_handler(event, context):
    for record in event['Records']:
        bucket = record['s3']['bucket']['name']
        key = unquote_plus(record['s3']['object']['key'])
        tmpkey = key.replace('/', '')
        download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)
        upload_path = '/tmp/resized-{}'.format(tmpkey)
        s3_client.download_file(bucket, key, download_path)
        resize_image(download_path, upload_path)
        s3_client.upload_file(upload_path, '{}-resized'.format(bucket), 'resized-{}'.format(key))
    
  • Trong cùng thư mục với file lambda_function.py tạo thư mục tên package sau đó cài đặt thư viện Pillow (PIL) và AWS SDK for Python (Boto3). Sử dụng git bash để thực thi

    mkdir package
    pip install \
    --platform manylinux2014_x86_64 \
    --target=package \
    --implementation cp \
    --python-version 3.9 \
    --only-binary=:all: --upgrade \
    pillow boto3
    
  • Ở bước này chúng ta sẽ tạo file lambda_function.zip như sau:

  • Copy file lambda_function.py vào trong thư mục package

  • Ctr + A và Thực hiện zip với tên lambda_function.zip

2.4 Create the Lambda function

Tại Lambda Console -> Menu Function -> Create function

  • Author from scratch
  • Basic information
    • Function name: d-lam-nonvpc-dva-generate-thumbnai-images
    • Runtime: Python 3.9
    • Architecture: x86_64
    • Execution role: Use an existing role -> DVAS3AccessForLambdaRole
    • Create function

Thực hiện test function:

Kết quả chạy function như bên dưới

2.5 Upload code

Chọn file lambda_function.zip mà bạn đã download về hoặc đã tạo ở bước trên.

Upload thành công và bạn cũng nhận được thông tin rằng package khá lớn nên không thể show code được

3. Configure a S3 event Notification to trigger Lambda function

Vào S3 Console -> Chọn source bucket -> Properties -> Event notifications

4. Test your function

4.1 Test your Lambda function with a dummy event

  • Tại Lambda Console -> Chọn lambda: d-lam-nonvpc-dva-generate-thumbnai-images
  • Select tab Test
  • Copy nội dung bên dưới và thay thế các giá trị sau:
    • Thay example-bucket bằng tên source bucket của bạn
    • Thay test%2Fkey bằng tên file image bạn đã upload lên source bucket trước đó
{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "us-east-1",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "EXAMPLE"
      },
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "EXAMPLE123456789",
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": {
          "name": "example-bucket",
          "ownerIdentity": {
            "principalId": "EXAMPLE"
          },
          "arn": "arn:aws:s3:::example-bucket"
        },
        "object": {
          "key": "test%2Fkey",
          "size": 1024,
          "eTag": "0123456789abcdef0123456789abcdef",
          "sequencer": "0A1B2C3D4E5F678901"
        }
      }
    }
  ]
}

Nếu bạn gặp lỗi Task timed out như bên dưới, thì lý do là Lambda đang default 3s, mình cần tăng số này lên.

Vào Configuration của Lambda -> General configuration -> Click Edit

Update timeout lên 10s

Lưu và thực hiện test lại

Lần test này sẽ thành công và bạn có thể confirm xem Thumbnail đã được tạo ở destimation bucket chưa

Bạn có thể download về để kiểm tra size ảnh đã nhỏ lại chưa.

4.2 Test your function using the Amazon S3 trigger

Thực hiện upload 1 file ảnh khác lên source bucket và confirm nhận được ảnh thumbnail bên destination bucket

  • Source bucket

  • Destination bucket

Để xem log của Lambda bạn có thể truy cập Cloudwatch Log

Clean up

  1. Delete the Lambda function: d-lam-nonvpc-dva-generate-thumbnai-images
  2. Delete the policy: DVAS3AccessForLambdaPolicy
  3. Delete the execution role: DVAS3AccessForLambdaRole
  4. Empty and delete the S3 bucket
    • d-s3-cmp-dva-image-source-bucket
    • d-s3-cmp-dva-image-source-bucket-resized