AWS CloudFormationでAWS Lambda with VPCを作成してみた

2016.03.25

サーモン大好き、横山です。

今回はCloudFormationでAWS Lambda with VPCの作り方の紹介をしようと思います。

AWS 公式ドキュメントには記載されていない事項なのでご利用は自己責任でお願いします。(2016/03/25 執筆現在)

経緯

2016/3/25 執筆現在、CloudFormationのAWS::Lambda::Functionリソースの説明にAWS Lambda With VPCの設定するための VpcConfig の項目が無かったので困っていました。

lambda_in_vpc_02

フォーラムを眺めてたら「裏側でAPI叩いてるだけだから、CreateFunctionのパラメータいれたら出来るかも?」みたいなって記事があったのでそれを参考にやってみました。

https://forums.aws.amazon.com/thread.jspa?messageID=707644

AWS::Lambda::Functionリソース

CreateFunction

準備

以下の入ったCloudFormationのtemplateファイルを準備します。

  • VPC
  • Subnet
  • SecurityGroup
  • IAM Role
  • AWS Lambda

lambda_in_vpc_01

作成

今回、関係あるLambdaとIAM Roleの設定だけ説明します。

Template全文見たい方はこちら(Gist)

IAM Roleは、Lambda Functionを作成時の、IAM Roleを一緒に作成する Basic with VPC の設定を参考書きます。
Basic execution role との違いはActionに ec2:CreateNetworkInterface, ec2:DescribeNetworkInterfaces, ec2:DetachNetworkInterface, ec2:DeleteNetworkInterface, がActionに必要となってます。

以下、Properties項目の抜粋です。

{
  "Resources": {
    "IAMRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "Policies": [
          {
            "PolicyName": "LambdaWithVPCPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": "arn:aws:logs:*:*:*"
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DetachNetworkInterface",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            }
          }
        ],
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "",
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
      }
    }
  }
}

次にAWS Lambdaの方です。
こちらは、 CreateFunction にある、 VpcConfig の項目を追加します。 VpcConfigに追加する項目は、それぞれ SecurityGroupIdsSubnetIds の二項目有りますが両方共必須項目ではありません。今回はSubnetとSecurityGroup1個ずつ登録しています。

以下、Properties項目の抜粋です。

{
  "Resources": {
    "Lambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "VpcConfig": {
          "SecurityGroupIds": [
            {
              "Ref": "SecurityGroup"
            }
          ],
          "SubnetIds": [
            {
              "Ref": "Subnet"
            }
          ]
        },
        "Handler": "index.handler",
        "Role": {
          "Fn::GetAtt": [
            "IAMRole",
            "Arn"
          ]
        },
        "Runtime": "nodejs",
        "Timeout": "5",
        "Code": {
          "ZipFile": {
            "Fn::Join": [
              "",
              [
                "var response = require('cfn-response');",
                "exports.handler = function(event, context) {",
                "  var input = parseInt(event.ResourceProperties.Input);",
                "  var responseData = {Value: input * 5};",
                "  response.send(event, context, response.SUCCESS, responseData);",
                "};"
              ]
            ]
          }
        }
      }
    }
  }
}

実行結果

AWS Lambdaの Configuration - Advanced settings を見ると設定されているのがわかります。
今回Subnetsの設定を1つだけにしたので、高可用性が担保されませんよ、と警告が出ています。

lambda_in_vpc_03

まとめ

CloudFormationでのAWS Lambda with VPCの作成例となれば幸いです。

CloudWatch EventsもAPI提供されていますので、CloudFromationいけるかなと思い探しましたが、そもそもCloudWatch Eventsのリソースタイプが無さそうなのでおとなしくアップデートを待とうと思いました。