Amazon TimestreamとIoT Core RuleアクションをCloudFormationで作成する

Amazon TimestreamとIoT CoreのRuleアクションをCloudFormationで作成してみました。
2021.05.25

CloudFormationを使って、Amazon Timestreamを作ってみました。 IoT Coreのルールアクションも作成し、とあるMQTTトピックに来たデータをAmazon Timestreamに格納する仕組みです。

システム概要図

CloudFormationテンプレートの作成

作成したCloudFormationテンプレートは下記です。IoT Coreで受け取ったメッセージをAmazon Timestreamに格納しています。

timestream.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description: Amazon Timestream Sample

Resources:
  IoTDataTimestreamDatabase:
    Type: AWS::Timestream::Database
    Properties:
      DatabaseName: CfnSampleDatabase

  IoTDataTimestreamTable:
    Type: AWS::Timestream::Table
    Properties:
      DatabaseName: !Ref IoTDataTimestreamDatabase
      RetentionProperties:
        MemoryStoreRetentionPeriodInHours: 24
        MagneticStoreRetentionPeriodInDays: 7
      TableName: iot-data-sample-table

  IoTDataRule:
    Type: AWS::IoT::TopicRule
    Properties:
      TopicRulePayload:
        RuleDisabled: false
        Actions:
          - Timestream:
              RoleArn: !GetAtt IoTDataRuleRole.Arn
              DatabaseName: !Ref IoTDataTimestreamDatabase
              TableName: !Select [1, !Split [ "|", !Ref IoTDataTimestreamTable ] ]
              Dimensions:
                - Name: deviceId
                  Value: ${topic(2)}
              Timestamp:
                Unit: MILLISECONDS
                Value: ${timestamp}
        Sql: SELECT temperature FROM 'sample/+/temperature'

  IoTDataRuleRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: iot.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: iot-data-timestream-rule-policy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action: timestream:WriteRecords
                Resource: !GetAtt IoTDataTimestreamTable.Arn
              - Effect: Allow
                Action: timestream:DescribeEndpoints
                Resource: "*"

テーブル名は直接参照できないので加工する

AWS::Timestream::Table!Refで参照すると、次のような値が得られます。

  • CfnSampleDatabase|iot-data-sample-table
    • データベース名|テーブル名

IoT Ruleアクションにはテーブル名のみを渡すので、!Splitで分割し、!Selectでテーブル名のみを取得しています。

  • !Select [1, !Split [ "|", !Ref IoTDataTimestreamTable ] ]

timestampの指定について補足

CloudFormationのドキュメントを見ても、Actions.Timestream.TimestampUnitValueの設定すべき内容が不明ですが、下記ドキュメントを参考にしてください。

Timestream - AWS IoT Core

  • Unitに指定する内容
    • SECONDS
    • MILLISECONDS (default)
    • MICROSECONDS
    • NANOSECONDS
  • Valueに指定する内容

Actions.Timestream.Timestamp自体が無い場合は、処理された時刻がAWSによって付与されます。

デプロイする

まだ東京リージョンには来ていないため、us-west-2にデプロイします。

aws cloudformation deploy \
    --region us-west-2 \
    --template-file timestream.yaml \
    --capabilities CAPABILITY_NAMED_IAM \
    --stack-name AmazonTimestreamSampleStack

動作確認

データをPublishする

  • トピック: sample/d0001/temperature
{
    "temperature": 12.3,
    "timestamp": 1621918928959
}
{
    "temperature": 22.2,
    "timestamp": 1621928216789
}

IoT Coreにデータを送信する

Amazon Timestreamを確認する

10件のデータを取得してみます。

SELECT *
FROM "CfnSampleDatabase"."iot-data-sample-table"
ORDER BY time DESC
LIMIT 10

バッチリ格納されていました!!

Amazon Timestreamにデータが存在する

timeは、IoT Ruleアクションで指定したとおり、「JSONデータ内のタイムスタンプ」が格納されています。

さいごに

Amazon TimestreamがGAした当初は、CloudFormationで「IoT Coreのルールアクション(to Amazon Timestream)」が非対応でしたが、いつの間にか対応していました。早く東京リージョンに来てほしいです。

参考