【问题标题】:How do I use CloudFormation resources in a Lambda function?如何在 Lambda 函数中使用 CloudFormation 资源?
【发布时间】:2016-09-03 15:17:00
【问题描述】:

我已将 Redis ElastiCache 部分添加到我的 s-resource-cf.json(CloudFormation 模板)中,并选择其主机名作为输出。

"Resources": {
    ...snip...
    "Redis": {
        "Type": "AWS::ElastiCache::CacheCluster",
        "Properties": {
            "AutoMinorVersionUpgrade": "true",
            "AZMode": "single-az",
            "CacheNodeType": "cache.t2.micro",
            "Engine": "redis",
            "EngineVersion": "2.8.24",
            "NumCacheNodes": "1",
            "PreferredAvailabilityZone": "eu-west-1a",
            "PreferredMaintenanceWindow": "tue:00:30-tue:01:30",
            "CacheSubnetGroupName": {
                "Ref": "cachesubnetdefault"
            },
            "VpcSecurityGroupIds": [
                {
                    "Fn::GetAtt": [
                        "sgdefault",
                        "GroupId"
                    ]
                }
            ]
        }
    }
},
"Outputs": {
    "IamRoleArnLambda": {
        "Description": "ARN of the lambda IAM role",
        "Value": {
            "Fn::GetAtt": [
                "IamRoleLambda",
                "Arn"
            ]
        }
    },
    "RedisEndpointAddress": {
        "Description": "Redis server host",
        "Value": {
            "Fn::GetAtt": [
                "Redis",
                "Address"
            ]
        }
    }
}

在运行 sls resources deploy 时,我可以让 CloudFormation 输出 Redis 服务器主机,但是如何从 Lambda 函数中访问该输出?

此入门项目模板中没有任何内容引用示例项目附带的 IamRoleArnLambda。根据docs,模板仅可用于项目配置,无法从 Lambda 函数中访问:

模板和变量仅用于配置

模板和变量仅用于项目的配置。此信息在您的 lambda 函数中不可用。要设置 lambda 函数可以使用的变量,请使用环境变量。

那么,在创建 ElastiCache 服务器后,如何将环境变量设置为 ElastiCache 服务器的主机名?

【问题讨论】:

    标签: aws-lambda amazon-cloudformation amazon-elasticache serverless-framework


    【解决方案1】:

    您可以在函数的s-function.json 文件的environment 部分中设置环境变量。此外,如果您想防止将这些变量放入版本控制中(例如,如果您的代码将发布到公共 GitHub 存储库),您可以将它们放在您的 _meta/variables 目录中的适当文件中,然后引用那些来自您的 s-function.json 文件。只需确保在 .gitignore 文件中添加 _meta 行即可。

    例如,在我的最新项目中,我需要连接到 Redis 云服务器,但不想将连接详细信息提交给版本控制。我将变量放入我的_meta/variables/s-variables-[stage]-[region].json 文件中,如下所示:

    {
      "redisUrl": "...",
      "redisPort": "...",
      "redisPass": "..."
    }
    

    …并在该函数的s-function.json 文件中引用了连接设置变量:

    "environment": {
      "REDIS_URL": "${redisUrl}",
      "REDIS_PORT": "${redisPort}",
      "REDIS_PASS": "${redisPass}"
    }
    

    然后我把这个redis.js 文件放在我的functions/lib 目录中:

    module.exports = () => {
      const redis = require('redis')
      const jsonify = require('redis-jsonify')
      const redisOptions = {
        host: process.env.REDIS_URL,
        port: process.env.REDIS_PORT,
        password: process.env.REDIS_PASS
      }
    
      return jsonify(redis.createClient(redisOptions))
    }
    

    然后,在任何需要连接到该 Redis 数据库的函数中,我导入了redis.js

    redis = require('../lib/redis')()
    

    (有关我的 Serverless/Redis 设置的更多详细信息以及我在使其工作时遇到的一些挑战,请参阅我昨天发布的 this question。)

    【讨论】:

    • 这对我来说应该没问题,只要我手动创建 Elasticache 集群,并在键名前加上无服务器堆栈名称。每个项目一次性手动操作不是问题,我可能还会为生产创建一个单独的实例。令人惊讶的是,使用 CloudFormation 如此困难。这是我两天内第三次尝试使用它来简化基础架构初始化,只是放弃并退回到手动创建资源,并将它们记录在自述文件和私有配置文件中。
    【解决方案2】:

    更新

    自从问题跟踪器中发布了该评论以来,CloudFormation 的使用已有所简化。我已向http://docs.serverless.com/docs/templates-variables 提交了文档更新,并在gist 中发布了我的配置的缩短版本。

    可以在 s-function.json Lambda 配置文件中引用 CloudFormation 输出,以使这些输出可用作环境变量。

    s-resource-cf.json 输出部分:

    "Outputs": {
        "redisHost": {
            "Description": "Redis host URI",
            "Value": {
                "Fn::GetAtt": [
                    "RedisCluster",
                    "RedisEndpoint.Address"
                ]
            }
        }
    }
    

    s-function.json环境部分:

    "environment": {
        "REDIS_HOST": "${redisHost}"
    },
    

    在 Lambda 函数中的使用:

    exports.handler = function(event, context) {
        console.log("Redis host: ", process.env.REDIS_HOST);
    };
    

    旧答案

    似乎在无服务器问题跟踪器 (link) 中找到/实施了解决方案。引用HyperBrain


    CF 输出变量

    要让您的 lambda 访问 CF 输出变量,您必须在 lambda IAM 角色中为其授予 cloudformation:describeStacks 访问权限。

    CF.loadVars() 承诺会将所有 CF 输出变量添加到进程中' 环境为SERVERLESS_CF_OutVar 名称。它会增加几毫秒 lambda 的启动时间。

    如下更改您的 lambda 处理程序:

    // Require Serverless ENV vars
    var ServerlessHelpers = require('serverless-helpers-js');
    ServerlessHelpers.loadEnv();
    
    // Require Logic
    var lib = require('../lib');
    
    // Lambda Handler
    module.exports.handler = function(event, context) {
      ServerlessHelpers.CF.loadVars()
      .then(function() {
        lib.respond(event, function(error, response) {
          return context.done(error, response);
        });
      })
    };
    

    【讨论】:

      猜你喜欢
      • 2017-07-23
      • 1970-01-01
      • 2021-02-18
      • 2021-04-22
      • 2021-08-20
      • 2021-06-23
      • 2015-12-04
      • 2015-12-25
      • 1970-01-01
      相关资源
      最近更新 更多