如何在serverless.yml中为lambda函数使用条件配置?

5
我需要通过 serverless.yml 配置一个 Lambda 函数,使其在不同的环境下使用不同的预配并发量。以下是我的 Lambda 配置:
 myLambda:
   handler: src/lambdas
   name: myLambda
   provisionedConcurrency: ${self:custom.pc}

...

custom:
  pc: ${env:PC}

从环境变量中加载变量PC的值,对于大于0的值有效,但我无法在一个环境中设置值为0。我想要做的是在dev环境中禁用预配并发。
我已经阅读了这篇文档https://forum.serverless.com/t/conditional-serverless-yml-based-on-stage/1763/3,但它似乎对我的情况没有帮助。
如何基于环境条件设置provisionedConcurrency
4个回答

4

方法一:通过默认值实现阶段变量

这是一个相当简单的技巧,使用级联值变量。第一个值是您想要的值,第二个值是默认值或备用值。也称为级联变量。

// serverless.yml
provider:
  stage: "dev"

custom:
  provisionedConcurrency:
    live: 100
    staging: 50
    other: 10

 myLambda:
   handler: src/lambdas
   name: myLambda
   provisionedConcurrency: ${self:custom.provisionedConcurrency.${self:provider.stage}, self:custom.provisionedConcurrency.other}

如果将stage设置为dev,则默认值为“other”,值为10,但如果通过serverless deploy --stage live设置stage,则会使用值为100的live。

更多细节请参见:https://www.serverless.com/framework/docs/providers/aws/guide/variables#syntax

方法2:通过Javascript实现异步值

您可以使用js include并在其中放置条件逻辑。这被称为“异步值支持”。基本上,它允许您在包含的javascript文件中放置逻辑,并且根据各种因素(例如,您所在的AWS帐户或是否设置了某些变量等)返回不同的值。基本上,它允许您执行以下操作...

provisionedConcurrency: ${file(./detect_env.js):get_provisioned_concurrency}

如果您在此文件夹中创建一个名为detect_env.js的JavaScript文件,并且它的内容类似于...

module.exports.get_provisioned_concurrency = () => {
  if ("put logic to detect which env you are deploying to, eg for live") {
    return Promise.resolve('100');
  } else {
    // Otherwise fallback to 10
    return Promise.resolve('10');
  }
}

请参阅更多信息:https://www.serverless.com/framework/docs/providers/aws/guide/variables#with-a-new-variables-resolver 我觉得即使这是几个月前问的问题,我还是必须在这里回复,因为没有一个答案甚至接近正确答案,我真的很为作者或任何来到这里的人感到难过。

1

对于非常棘手的问题,我发现去查看Cloudformation脚本并使用Cloudformation内在函数是有用的。

对于这种情况,如果您知道所有环境,可以使用Fn :: FindInMap

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html

如果只有生产环境需要0,您可以在Cloudformation模板中使用条件Fn::If和布尔值Condition测试来测试环境是否等于生产环境,如果是,则使用0,否则使用SLS模板中的值。请注意,保留HTML标签,不涉及解释。以下是需要翻译的内容:

Potential SLS:

resources:
  Conditions:
    UseZero: !Equals ["production", ${provider.stage}]
  Resources:
    myLambda:
      ProvisionedConcurrency: !If [UseZero, 0, ${self:custom.pc}]

你也可以明确地删除ProvisionedConcurrency属性,如果你想的话:
resources:
  Conditions:
    UseZero: !Equals ["production", ${provider.stage}]
  Resources:
    myLambda:
      ProvisionedConcurrency: !If [UseZero, AWS::NoValue, ${self:custom.pc}]

编辑:您仍然可以使用SLS进行部署;它只是编译成Cloudformation JSON模板,您可以在SLS的资源字段中明确修改它。

那么意味着我不能使用“无服务器”来部署Lambda吗?这可能是一个重大的变化。 - Joey Yi Zhao
我尝试过这种方法,但是它编译时会出现“CloudFormation模板无效:无效的模板资源属性'provisionedConcurrency'”的错误。它在“function”部分中使用相同的语法吗? - Joey Yi Zhao
当您启动CLI时,是SLS在抱怨吗?还是在部署时CF在抱怨? - Tobin
请注意:像这样突破CloudFormation来解决这种情况是相当疯狂的。Serverless在其框架中有许多处理此类问题的方法。 - Farley

0

在部署/打包期间,只需使用一个空值变量来跳过开发环境中的属性:

provisionedConcurrency: ${self:custom.variables.provisionedConcurrency}

FYI:这不是作者要求的。他们要求不同环境下的不同值,而不是可能只有一个值或没有值。 - Farley

0
Serverless Framework 提供了一个非常有用的仪表板工具,其中包含一个名为 Parameters 的功能。实际上,它允许您将服务连接到仪表板,然后您可以为不同的阶段设置不同的值,然后在 serverless.yml 中使用这些值,并使用类似 ${param:VARAIBLE_NANE_HERE} 的语法进行替换,在部署时用正确的值替换当前正在部署的任何阶段的值。超级方便。仪表板还有其他一些功能,例如监控和故障排除。

您可以在官方文档中了解有关 Parameters 的更多信息:https://www.serverless.com/framework/docs/guides/parameters/

以及如何开始使用仪表板:https://www.serverless.com/framework/docs/guides/dashboard#enabling-the-dashboard-on-existing-serverless-framework-services


我没有使用无服务器仪表板。我只有命令行。有解决方案吗? - Joey Yi Zhao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接