使用无服务器部署 AWS Lambda 函数在需要外部模块时不会部署

Posted

技术标签:

【中文标题】使用无服务器部署 AWS Lambda 函数在需要外部模块时不会部署【英文标题】:Deploying an AWS Lambda function using serverless does not deploy when external modules are required 【发布时间】:2020-06-07 14:51:49 【问题描述】:

我目前正在尝试使用无服务器部署 AWS lambda 函数。如果我不包含任何外部模块,我可以获得正确部署和响应的功能,但是一旦我尝试包含 dynogels 和 Joi:

const dynogels = require("dynogels");
const Joi = require("@hapi/joi");

serverless deploy 命令不会通过“打包外部模块”

包含外部模块时的完整输出:

❯ sls deploy
 addHandler: './addHandler.js' 
Serverless: Bundling with Webpack...
   1 module
Serverless: No external modules needed
Serverless: Packaging service...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service game-data-service.zip file to S3 (1.9 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..............
Serverless: Stack update finished...
Service Information
service: game-data-service
stage: dev
region: ap-southeast-2
stack: game-data-service-dev
resources: 11
api keys:
  None
endpoints:
  POST - XXXXXXXXXXX/endpoint
functions:
  addData: game-data-service-dev-addData
layers:
  None
Serverless: Updated basepath mapping.
Serverless Domain Manager Summary
Domain Name
  XXXXXXXXXXX.com
Distribution Domain Name
  Target Domain: XXXXXXXXXXX
  Hosted Zone Id: XXXXXXXXXXX
Serverless: Removing old service artifacts from S3...
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.

包含外部模块时的完整输出:

❯ sls deploy
 addHandler: './addHandler.js' 
Serverless: Bundling with Webpack...
   3 modules
Serverless: Package lock found - Using locked versions
Serverless: Packing external modules: dynogels@^9.1.0, @hapi/joi@^17.1.0

软件包已安装。我不明白为什么这没有部署。有什么方法可以让我从部署中看到一些错误? --verbose 似乎没有提供太多额外信息。感谢您的帮助!

编辑 serverless.yml

service: game-data-service

provider:
  name: aws
  runtime: nodejs12.x
  stage: dev
  region: ap-southeast-2
  environment:
    SERVICE_NAME: $self:service
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:DescribeTable
        - dynamodb:DescribeTable
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
        - dynamodb:BatchGetItem
      Resource: "arn:aws:dynamodb:ap-southeast-2:*:*"
    - Effect: Allow
      Action:
        - codepipeline:StartPipelineExecution
      Resource: "arn:aws:codepipeline:ap-southeast-2:*:*"
    - Effect: Allow
      Action:
        - s3:PutObject
        - s3:PutObjectAcl
      Resource: "arn:aws:s3:::XXXXXXXXXXX-assets-bucket/*"

plugins:
  - serverless-domain-manager
  - serverless-webpack

custom:
  stage: $opt:stage, self:provider.stage
  admin_arn: XXXXXXXXXX
  user_arn: XXXXXXXXXXX
  domains:
    prod: XXXXXXXXXXX.com
    staging: XXXXXXXXXXX.com
    dev: XXXXXXXXXXX.com
  webpack:
    webpackConfig: "webpack.config.js"
    includeModules: true # Node modules configuration for packaging
    packagePath: "../package.json"

  customDomain:
    basePath: gameData
    domainName: $self:custom.domains.$self:custom.stage
    stage: "$self:custom.stage"
    createRoute53Record: true

##############################################################
# Functions
##############################################################

functions:
  addData:
    handler: addHandler.hello
    events:
      - http: POST add

webpack.config.js

const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
var path = require("path");
function resolve(dir) 
  return path.join(__dirname, dir);


console.log(slsw.lib.entries);
module.exports = 
  entry: slsw.lib.entries,
  target: "node",
  // Since 'aws-sdk' is not compatible with webpack,
  // we exclude all node dependencies
  externals: [nodeExternals()],
  resolve: 
    alias: 
      "@": resolve("../lib"),
      "=": resolve("../db")
    
  ,
  optimization: 
    minimize: false
  ,
  mode: slsw.lib.webpack.isLocal ? "development" : "production",
  stats: "minimal"
;

addHandler.js

"use strict";

import  success, failure  from "@/response";
// import schema from "=/schema";
// import gameSchema from "=/gameSchema";

// const dynogels = require("dynogels");
// const Joi = require("@hapi/joi");
const cowsay = require("cowsay");


export const hello = (event, context, callback) => 
  console.log("Running ADD");
  console.log(cowsay.say( text: "Mooodule" ));
  const body = JSON.parse(event.body);

  const table = body["table"];
  const data = body["data"];
  if (body["table"] == null) 
    callback(
      null,
      failure(
        error: "You must provide the table name in the body"
      )
    );
  
  console.log(`Body recieved for table $table:`, data);
  callback(null, success( message: `Data added to $table` ));
  // try 
  //   gameSchema[event.pathParameters.table].create(body, (err, res) => 
  //     if (err) 
  //       callback(null, failure( error: err ));
  //       return;
  //     

  //     callback(null, success(res));
  //   );
  //   callback(null, success(res));
  //  catch (err) 
  //   callback(null, failure( error: err ));
  //   return;
  // 
;

【问题讨论】:

哪里出错了? @hephalump - 没有错误消息,它显示“打包外部模块”,这是我收到的最后一个输出。然后它不会部署该功能。 很奇怪。您使用的是什么版本的无服务器?我从未听说过这种行为。除非手动退出,否则它始终会产生输出。您是否尝试将其隔离为单个依赖项?所以只做 Joi 或 dynogels,而不是两者兼而有之。是否可以包含任何其他依赖项? @hephalump 我试过只使用 dynogels 和 Joi,同样的问题。我尝试从 npm 安装和保存 cowsay 并使用完全不同的依赖项 - 同样的问题。我试过包含我自己的 js 文件,这似乎工作正常...... 您使用的是哪个版本的SLS?另外,您使用的是什么包管理器? 【参考方案1】:

尝试将Lambda Layers 用于您的 SAM 应用程序。

【讨论】:

以上是关于使用无服务器部署 AWS Lambda 函数在需要外部模块时不会部署的主要内容,如果未能解决你的问题,请参考以下文章

AWS攻略——使用CodeBuild进行自动化构建和部署Lambda(Python)

无服务器AWS Lambda:没有名为`secret_manager`的模块

使用 graphql、aws lambda 和无服务器框架的多个 url 路径选项错误

如何在本地测试 aws lambda 函数

将 Apollo 服务器调试为 AWS Lambda 函数

AWS lambda 无服务器网站会话维护