Closed10

lambda 50MBの壁を越えたい

yakoyakoyakoyako

初期環境

  • lambda
  • serverless framework
  • typescript

serverless-layersは使用済み

背景

Lambdaにデプロイするにはzipにして50MBまでの容量でないといけない。
仕事のプロジェクトでは開始早々、デプロイすると48.6MBになる。
そのため50MBの制限を回避する方法を調べた結果、ECRを使用すると上限突破できるという記事を
見つけた。

参照:
https://zenn.dev/xxpiyomaruxx/articles/d7419ec1138d6a
https://aws.amazon.com/jp/blogs/news/new-for-aws-lambda-container-image-support/

yakoyakoyakoyako

ECR導入

まずはECRを導入していく

その前にaws cliを導入していなかったので、下記記事を参考に導入
https://udemy.benesse.co.jp/development/system/aws-cli.html

aws cliで作成

$ aws ecr create-repository --repository-name <リポジトリ名> --image-scanning-configuration scanOnPush=true

エラー

An error occurred (AccessDeniedException) when calling the CreateRepository operation: User: arn:aws:iam::429663746063:user/optemo-weel is not authorized to perform: ecr:CreateRepository on resource: arn:aws:ecr:ap-northeast-1:429663746063:repository/serverless-lambda-nestjs because no identity-based policy allows the ecr:CreateRepository action

アクセス権限がないとのことなので、使用しているポリシーを作成してアタッチ(とりあえず、ecrはフルアクセスにした)

再度コマンド実行!

{
    "repository": {
        "repositoryArn": "arn:aws:ecr:${リージョン}:${registryId}:repository/${リポジトリ名},
        "registryId": ${レジストリーID},
        "repositoryName": ${リポジトリ名},
        "repositoryUri": "${レジストリーID}.dkr.ecr.ap-northeast-1.amazonaws.com/${リポジトリ名}",
        "createdAt": "2022-03-20T17:45:11+09:00",
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": true
        },
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }
    }
}

無事作成できた♪

参照
https://zenn.dev/qazx7412/articles/fddbdd5bd6379e4587a3

yakoyakoyakoyako

ECR設定

ログイン

$ aws ecr get-login-password --region <リージョン>                                               |
$ docker login --username AWS --password-stdin <アカウントID>.dkr.ecr.<リージョン>.amazonaws.com
Login Succeeded

いい感じ!二つのコマンド同時に実行したら良いっぽい!

参照
https://zenn.dev/qazx7412/articles/fddbdd5bd6379e4587a3

yakoyakoyakoyako

Dockerfile作成

先にこれを作ってもよかったのかも

Dokerfile
# AWS ベースイメージを使用
FROM public.ecr.aws/lambda/nodejs:14

# ソースコードを関数のルートディレクトリにコピーします。
COPY package.json package-lock.json /dist/
RUN npm install

# CMD にハンドラを設定します。
CMD ["index.handler"]

今回僕はnestjsを使用しているので、build後のディレクトリ/distをcopyに入れておく。
認識あっているかは不安。。。

参考
https://zenn.dev/kou_pg_0131/articles/lambda-container-image

yakoyakoyakoyako

今回僕はnestjsを使用しているので、build後のディレクトリ/distをcopyに入れておく。
認識あっているかは不安。。。

違った。変更後は後述

yakoyakoyakoyako

Docker イメージをプッシュする

ビルド

$ docker build -t ${リポジトリー名} .

タグをつける

$ docker tag ${リポジトリー名}:latest ${レジストリーID}.dkr.ecr.${リージョン}.amazonaws.com/serverless-lambda-nestjs:latest

プッシュ

$ docker push ${レジストリーID}.dkr.ecr.${リージョン}.amazonaws.com/${リポジトリー名}:latest
The push refers to repository 
3d5d030acacf: Pushed 
ed7a3fdccd0d: Pushed 
6b7df015875a: Pushed 
9d3bb0756fb6: Pushed 
5f96311c404e: Pushed 
90578680ae78: Pushed 
9c58b1736bc5: Pushed 
edc0c3a324d0: Pushed 
latest: digest: sha256:9a226e6a3d344566b4a12a6d2f78b48a4b0d1f06cjofc8f62924k95bb25eb346 size: 1995

sha256:9a226e6a3d344566b4a12a6d2f78b48a4b0d1f06cjofc8f62924k95bb25eb346は後で使うので保存しとく

コマンドはAmazon ECRの作成したリポジトリないから確認できる

yakoyakoyakoyako

sha256:9a226e6a3d344566b4a12a6d2f78b48a4b0d1f06cjofc8f62924k95bb25eb346は後で使うので保存しとく

僕の実装の仕方的に結局使わなくてよかった。

yakoyakoyakoyako

デプロイ

$ sls deploy
Resource handler returned message: "Invalid request provided: Updating PackageType is not supported" 
(RequestToken: 92c94c08-86c8-deea-f965-989b7351cabe, HandlerErrorCode: InvalidRequest)

その後

Error:
CREATE_FAILED: IndexLogGroup (AWS::Logs::LogGroup)
Resource handler returned message: "Resource of type 'AWS::Logs::LogGroup' with identifier '{"/properties/LogGroupName":"/aws/lambda/${lambda関数名}"}' already exists." (RequestToken: 2c0809s79-79s2c-87s9a-d443-ce36b18f22422, HandlerErrorCode: AlreadyExists)

わからない。。。
原因調査はまだ後日

yakoyakoyakoyako

エラー原因調査

1つ目のエラーはすでに同じ名前の関数をzip形式で作成していたので、そのタイプをimageに後から変更することはできないとエラーが出ていたと判断した。
そのため、serverless.ymlのserviceを変更して対応!

解決した!

2つ目のエラーは同じ名前のロググループがすでに存在するというエラーだったため、そのロググループを作成して対応!

解決した!

しかし、更なるエラーが出てきた。

Resource handler returned message: "Lambda layers are not supported for functions created with container images. 
(Service: Lambda, Status Code: 400, Request ID: 353ab0fd-f5a0-4b92-a6d8-2287cf6cc154, Extended Request ID: null)" (RequestToken: 552cafdd-72df-b683-f3be-3ab8ebdb35dc, HandlerErrorCode: InvalidRequest)

docker imageでのデプロイの際はLambdaレイヤーを使えないというエラーぽい。
ブラグインのserverless-layersをコメントアウトし、対応!

できたーーーーー!!!

yakoyakoyakoyako

Nestが動かなかった

デプロイはできたがnestが動かなかったので、色々試した。
これが一番詰まった。。

結果下記の修正で動いた!

  • Dockerfile修正
  • serverless.yml修正

Dockerfile修正

# AWS ベースイメージを使用
FROM public.ecr.aws/lambda/nodejs:14

# ソースコードを関数のルートディレクトリにコピーします。
COPY . .

RUN npm install

# CMD にハンドラを設定します。
CMD ["dist/index.handler"]

全部コピーするように変更した!
yarn installにするとダメだった。

serverless.yml修正

  ecr:
    images:
      ${tag_name}:
        path: ./
...
functions:
  index:
    image:
      name: ${tag_name}

これでNestの軌道まで確認できた!!!
完成!!

意外と長い道のりだった。

おかしな箇所、もっとこうしたら良いなどありましたら、ぜひコメントください!

このスクラップは2022/03/22にクローズされました