A simple AWS CloudFormation example with Lambda and Kinesis

I finally took the plunge and played around with creating a CloudFormation template. It was actually easier than I thought it would be. So that's a plus. Most CloudFormation scripts are very daunting to view... so I'll explain some of the fun stuff I learned along the way.

Lets start with a template, then I'll break it down.

{
  "Resources": {
    "HelloWorldFn": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Handler": "index.handler",
        "Role": "arn:aws:iam::551473449163:role/lambda_kinesis_role",
        "Code": {
          "ZipFile": {
            "Fn::Join": [
              "\n",
              [
                "exports.handler = function(event, context) {",
                "  console.log('hello world!');",
                "};"
              ]
            ]
          }
        },
        "Runtime": "nodejs4.3"
      }
    },
    "GreetingStream": {
      "Type": "AWS::Kinesis::Stream",
      "Properties": {
        "Name": "GreetingStream",
        "ShardCount": 1
      }
    },
    "GreetingStreamEventSource": {
      "Type": "AWS::Lambda::EventSourceMapping",
      "Properties": {
        "FunctionName": {
          "Ref": "HelloWorldFn"
        },
        "Enabled": true,
        "EventSourceArn": {
          "Fn::GetAtt": [
            "GreetingStream",
            "Arn"
          ]
        },
        "StartingPosition": "TRIM_HORIZON"
      }
    }
  }
}

Lambda

The first part of this template is automating creation of the actual Lambda function, so lets break that down:

"HelloWorldFn": {
  "Type": "AWS::Lambda::Function",
  "Properties": {
    "Handler": "index.handler",
    "Role": "arn:aws:iam::551473448333:role/lambda_execution_role",
    "Code": {
      "ZipFile": {
        "Fn::Join": [
          "\n",
          [
            "exports.handler = function(event, context) {",
            "  console.log('hello world!');",
            "};"
          ]
        ]
      }
    },
    "Runtime": "nodejs4.3"
  }
}

This section follows the CloudFormation Lambda API. To define a Lambda, we must provide four properties:

  • Handler - the entrance point to your Lambda
  • Role - the role that the Lambda executes under
  • Runtime - the Runtime to execute the Lambda with
  • Code - how you want to load the code into your Lambda function

All of these properties are things you would supply to a Lambda function if you were creating it through the UI.

In my example above, I am directly passing in a Role based on the ARN found in the UI. This should just be your Lambda execution Role.

The Code property in this example uses the Fn::Join property to concatinate lines together as the code of your Lambda function. This is sufficient for the simple example I'm showing you here. In reality, you would likely point to an S3 location for your code.

Kinesis

Configuring the Kinesis stream is actually very straighforward:

"GreetingStream": {
  "Type": "AWS::Kinesis::Stream",
  "Properties": {
    "Name": "GreetingStream",
    "ShardCount": 1
  }
},

This block of JSON follows the CloudFormation Kinesis Stream API and requires two properties:

  • Name - the name of your stream
  • ShardCount - the number of shards you want

EventSourceMapping

The last piece is creating the EventSourceMapping to link the Lambda to the Kinesis stream. This requires a bit more scripting than the previous sections.

"GreetingStreamEventSource": {
  "Type": "AWS::Lambda::EventSourceMapping",
  "Properties": {
    "FunctionName": {
      "Ref": "HelloWorldFn"
    },
    "Enabled": true,
    "EventSourceArn": {
      "Fn::GetAtt": [
        "GreetingStream",
        "Arn"
      ]
    },
    "StartingPosition": "TRIM_HORIZON"
  }
}

This section follows the CloudFormation Lambda EventSourceMapping API and requires the following properties:

  • FunctionName - the name or ARN of the lambda
  • Enabled - true to enable the source
  • EventSourceArn - the ARN of the event source
  • StartingPosition - TRIM_HORIZON or LATEST

From the above, we will create a reference using the logical name of the Lambda function.

The logical name is the name used inside the CloudFormation template, in this case HelloWorldFn.

The reference resolves to the physical ID of the Lambda, which is it's name.

The last component here is getting the ARN of the event source. This uses another script Fn::GetAtt which simply retreieves the specified attribute from the resource in the template.

We use the logical name of Kinesis Stream, GreetingStream and retrieve the Arn property.

Hopefully that provides a bit of a starting point for working with CloudFormation.

comments powered by Disqus