Skip to content

afr5/lambda-resize-image

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lambda-resize-image

Image generation workflow

클라우드 프론트에 이미지 요청시 S3의 이미지를 가져와 리사이징 하여 반환하는 람다 함수입니다. 자세한 설명은 아래 글을 참고해주세요.

Build & Deployment

이미지 리사이징 모듈인 Sharp는 바이너리를 포함합니다. 그리고 AWS Lambda 인스턴스는 운영체제가 다릅니다. Sharp 모듈을 이용한 람다 함수가 정상적으로 동작하기 위해서는 람다 인스턴스가 사용하는 OS에서 빌드한 모듈이 필요합니다. (과거에는 EC2를 띄워서 Sharp 모듈을 얻었으나...) 다행히 도커가 아마존 리눅스 인스턴스 환경을 제공할 수 있습니다. 도커의 볼륨 공유를 이용하여 amazonlinux OS에서 빌드한 Sharp 모듈을 로컬에 설치할 수 있습니다.

Dockerfile

FROM amazonlinux:2023

WORKDIR /tmp
#install the dependencies
RUN yum -y install gcc-c++ findutils tar gzip make

RUN touch ~/.bashrc && chmod +x ~/.bashrc

RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.5/install.sh | bash

RUN source ~/.bashrc && nvm install 22.13.1

WORKDIR /build

위의 Dockerfile은 AWS Lambda가 동작하는 OS인 amazonlinux:2023에 람다 런타임 nodejs22.x 환경을 제공합니다. 아래의 명령어를 통해서 Docker 이미지를 만드세요.

docker build --tag amazonlinux2023 .

위 도커 이미지를 이용하면 amazonlinux2023 용 sharp 모듈을 빌드 할 수 있고, 볼륨 공유를 통해 로컬에 node_modules를 얻을 수 있습니다.

docker run --rm --volume ${PWD}:/build amazonlinux2023 /bin/bash -c \
  "source ~/.bashrc; npm init -f -y; npm install --cpu=x64 --os=linux sharp --save; npm install; npm install"

이후 아래 명령어를 실행하면 로컬에 생성된 node_modules 를 패키징하여 새 버전의 람다가 배포됩니다.

sls deploy

serverless.yml

provider:
  name: aws
  runtime: nodejs22.x
  region: us-east-1
  endpointType: Edge
  memorySize: 256
  timeout: 10
  logRetentionInDays: 7
  stage: ${self:custom.stage}
  deploymentBucket:
    name: com.example.lambda-edge
    blockPublicAccess: true
  • region: CloudFront는 Edge 서비스입니다. us-east-1으로 지정해야 합니다.
  • logRetentionInDays: 로그 보관 기간은 7일입니다.
  • deploymentBucket: 패키지를 업로드하는 S3는 com.example.lambda-edge입니다. us-east-1 리전에 있는 S3 버킷입니다.
resources:
  Resources:
    LambdaEdgeRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-role
        Path: /service-role/
        ManagedPolicyArns:
          - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
          - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
        AssumeRolePolicyDocument:
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
                  - edgelambda.amazonaws.com
              Action:
                - sts:AssumeRole
        Policies:
          - PolicyName: ${self:service}-policy
            PolicyDocument: 
              Version: "2012-10-17"
              Statement: 
                - Effect: Allow
                  Action:
                    - lambda:GetFunction
                    - lambda:EnableReplication
                    - iam:CreateServiceLinkedRole
                    - cloudfront:UpdateDistribution
                    - s3:GetObject
                    - s3:PutObject
                    - s3:PutObjectAcl
                  Resource: arn:aws:lambda:${self:provider.region}:${self:custom.account}:function:${self:service}-${self:provider.stage}:*:*

함수를 동작시킬 IAM Role을 생성합니다.

  • ManagedPolicyArns: AWS가 관리하는 정책을 붙여줍니다.
  • AssumeRolePolicyDocument: IAM Role에 Trust relationship을 설정합니다.
  • Policies: 인라인 정책을 추가합니다.
package:
  excludeDevDependencies: true
  individually: true
  patterns:
    - node_modules/**
    - handler.js

배포 패키지를 만드는 내용입니다.

  • excludeDevDependencies: package.json의 devDependencies 모듈은 포함하지 않습니다.
  • individually: 값을 true로 설정하면 함수별로 패키징합니다.
  • patterns: 배포 패키지에 포함할 내용입니다.
functions:
  resizeImage:
    name: ${self:service}-${self:provider.stage}
    handler: handler.handler
    role: LambdaEdgeRole
    events:
      - preExistingCloudFront: 
          distributionId: ${self:custom.distributionId}
          eventType: origin-response
          pathPattern: /images/*
          includeBody: false
          stage: prod

함수 정의 부분입니다.

  • role: 위에서 만든 IAM Role을 지정합니다.
  • events: 이미 존재하는 CloudFront에 이 함수를 지정합니다. images/* 폴더 하위에 대해서만 동작합니다.
plugins:
  - serverless-lambda-edge-pre-existing-cloudfront

serverless-lambda-edge-pre-existing-cloudfront는 이미 존재하는 CloudFront에 함수를 연결하는 일을 도와줍니다.

Serverless commands

본 serverless.yaml에서는 옵션을 받고 있습니다.

  • stage: 필요에 따라서 dev 혹은 prod 값으로 구분할 수 있습니다.
  • awsAccountId: 람다 함수를 업로드하고자 하는 AWS의 숫자로 된 값 입니다 IAM에서 찾을 수 있습니다.
  • distributionId: 클라우드 프론트를 이미 구성했다면 클라우드 프론트 메뉴에서 distributionId를 찾을 수 있습니다.

sls는 serverless의 축약어로 등록되어 있습니다.

Deploy

sls deploy --stage dev --awsAccountId <AWS_ACCOUNT_ID> --distributionId <DISTRIBUTION_ID>

만약 aws profile이 default가 아니라면 --aws-profile 옵션을 추가할 수 있습니다.

sls deploy --aws-profile PROFILE_NAME

Usage

람다 함수가 정상적으로 배포되었고 클라우드 프론트와 연결이 잘 되었다면 다음과 같이 요청했을 때 이미지 변환이 이루어져 반환됩니다.

eg. https://cdn.example.com/images/example.png?w=100&h=100&f=jpg&q=90

사용가능한 쿼리는 다음과 같습니다.

  • w: width
  • h: height
  • f: format
  • q: quality

Trobleshootings

Test event

테스트 이벤트를 통해 람다 함수를 검증할 수 있습니다. 클라우드 프론트 오리진 응답 이벤트

Delete CloudFront caches

캐시를 무효화 하려면 다음과 같이 할 수 있습니다.

$ aws cloudfront create-invalidation --distribution-id $CDN_DISTRIBUTION_ID --paths "/*"

--path 옵션에는 파일의 경로를 지정할 수 있으며, 예와 같이 와일드 카드를 이용할 수 있습니다. (단, 월별로 1,000개를 초과하는 각 무효화 경로에 대해서 요금을 지불합니다.)

자세한 내용은 다음 항목을 참고하세요. 파일 무효화

Delete Lambda@Edge

serverless remove 명령어로는 람다 엣지 함수를 삭제할 수 없습니다. 다음 문서를 참고하여 삭제하세요.

References

About

Resizing images with CloudFront & Lambda@Edge

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published