亚马逊AWS官方博客

使用Terraform对Amazon IoT进行规则操作的自动化部署

随着物联网的发展,越来越多的设备接入到Amazon IoT物联网云平台中进行设备管理以及数据存储和处理。在实施中,客户可以使用 Amazon IoT 控制台手动创建和编辑规则操作,但在生产环境中,客户可能希望使用自动化来使规则操作部署可重复且更易于管理。Amazon提供了CloudFormation 服务使客户能够跨应用程序一致地部署IoT规则规则。但另一方面,客户也可能另外使用了其他IT基础架构自动化编排工具比如Terraform来总体管理维护IT资源,需要使用Terraform来自动化部署Amazon IoT规则操作。

在这篇博文中,我们将向您介绍如何帮助客户解决上面这些挑战,详细介绍如何使用Terraform来对Amazon IoT进行规则操作的自动化部署。本博文的内容主要包括下面三个部分:

  • 利用Amazon IoT规则操作来存储数据以及使用Lambda进行数据处理
  • 如何利用Terraform来对IoT规则操作进行自动化部署
  • Terraform部署模版的示例展现

概述

在生产环境中,我们需要使用自动化来部署Amazon IoT的规则操作,有效的提高了部署的可重复性,同时也更加易于管理。Amazon提供了CloudFormation云资源配置和更新服务,使得开发人员和系统管理员轻松有序地创建、管理和更新相关 Amazon云资源模板,当然也包括了Amazon IoT的资源模版,关于如何用CloudFormation来创建IoT规则操作可以参考https://aws.amazon.com/blogs/iot/bites-of-iot-creating-aws-iot-rules-with-aws-cloudformation/。另外对于一些客户可能已另外使用了其他IT基础架构自动化编排工具比如Terraform来总体管理维护IT资源,可以参考https://aws.amazon.com/cn/blogs/china/aws-china-region-guide-series-terraform1/。本文将详细介绍如何利用Terraform来对Amazon IoT的规则操作进行创建和自动化部署。

Amazon IoT规则引擎对发布到Amazon IoT的入站消息,根据业务规则转换这些消息并传输到适当的终端节点。需要重度的分析查询,使用Kinesis Firehose + S3,后期通过Amazon EMR分析。需要快速的查询写到DynamoDB,必要时加上索引。外部终端节点可以通过Lambda和Simple Notification Service (SNS)进行访问。本博文主要针对下面架构中的三个规则操作进行Terraform自动化部署示例,这三个规则操作覆盖了上面所述的三个主要数据路由操作,也就是用Kinesis Data Firehose+S3来保存IoT设备上传的原始数据,用DynamoDB来保存即时数据,以及用Lambda来处理一些特殊的数据。保存在S3的原始数据可以供大数据分析以及机器学习,而DynamoDB的数据以及通过Lambda发送则可以供第三方系统及时获取作进一步的处理和呈现。

Amazon IoT规则操作和权限要求

Amazon IoT提供规则引擎用于物联网数据的处理和路由,通过定义IoT规则操作可以使设备能够与 Amazon云服务进行交互。这些规则是基于 MQTT 主题流来进行规则的分析和执行,在本博文中使用下面规则来完成对设备原始数据的保存,对设备即时数据的保存,以及对设备信息的处理。

  • 将设备原始数据通过Kinesis Data Firehose保存到S3存储桶
  • 将设备即时数据保存到 Amazon DynamoDB中
  • 调用 Lambda 函数对设备信息的处理

将设备原始数据通过Kinesis Data Firehose保存到S3存储桶

Amazon IoT规则操作中的Kinesis Data Firehose (firehose) 操作可将 MQTT 消息中的数据发送至 Amazon Kinesis Data Firehose 流,然后再Firehose中通过定义直接目的地将流数据保存在S3存储桶。此规则操作要求Amazon IoT 可以承担以执行 firehose:PutRecord 操作的 IAM 角色。对于使用 Kinesis Data Firehose 将数据发送到 Amazon S3 存储桶,Kinesis Data Firehose 必须具有对存储桶的访问权限。

  • 创建一个Amazon S3存储桶以及Kinesis Data Firehose数据流,将Firehose数据流的数据发送到S3存储桶。
  • 创建一个规则操作将收取到的相关MQTT主题的数据消息发送至Kinesis Data Firehose中,通过Firehose将数据保存在S3存储桶中。

将设备即时数据保存到 Amazon DynamoDB中

Amazon IoT规则操作中的DynamoDB (dynamoDB) 操作可将所有或部分 MQTT 消息写入 Amazon DynamoDB 表。请注意此规则将非 JSON 数据作为二进制数据写入到 DynamoDB 中,DynamoDB 控制台以 Base64 编码文本格式显示数据。另外Amazon IoT可以承担以执行 dynamodb:PutItem 操作的 IAM 角色。

  • 创建一个DynamoDB表供设备数据存储之用
  • 创建一个规则操作将收取到的相关MQTT主题的数据消息保存至DynamoDB中

调用 Lambda 函数对设备信息的处理

Amazon IoT规则操作中的Lambda (lambda) 操作调用 AWS Lambda 函数,传入 MQTT 消息。 AWS IoT 异步调用 Lambda 函数,Lambda函数将处理从IoT Core中路由过来的数据然后对数据进行处理,然后可以将这些设备信息通过接口调用发送到该第三方系统中做进一步的处理。使用 Amazon IoT 调用 Lambda 函数,则必须配置一个策略,以便向 Amazon IoT 授予 lambda:InvokeFunction的权限。另外为了更高效的让Lambda调用第三方系统,这里假定了Lambda调用了在同一个VPC里面部署的第三方系统。

  • 创建一个Lambda函数,用于对IoT Core路由过来的设备连接或断开连接信息进行处理
  • 创建一个规则操作将收取到的相关MQTT主题的数据消息路由至Lambda函数进行操作处理

利用Terraform来对Amazon IoT规则操作进行自动化部署

本博文针对上述规则操作进行Terraform模版的实现,便于进行Amazon IoT规则操作的自动化部署。关于如何管理维护通用的IT资源,可以参考https://aws.amazon.com/cn/blogs/china/aws-china-region-guide-series-terraform1/,本文主要讲述Amazon IoT规则操作及其相关服务的自动化部署。

在使用下面的Terraform部署模版前,首先请配置好AWS Provider登录信息以及定义好相关的变量,比如S3存储桶的名称等。

# Configure the AWS Provider
provider "aws" {
  region  = "cn-north-1"
  profile = "default"
}

# Variables
variable "iotdemo_bucket_name" {
  description = "S3 Bucket Name"
  type        = string
  default     = "iotdemo-s3-test-xxxxxx"
}

利用Terraform将设备原始数据通过Kinesis Data Firehose保存到S3存储桶

通过Amazon IoT规则引擎,将数据路由至Kinesis Data Firehose,通过Firehose将数据S3来保存IoT设备上传的原始数据,保存在S3的原始数据可以供大数据分析以及机器学习。下面是Terraform部署Kinesis Data Firehose以及S3模版的部分代码:

  • 创建Kinesis Data Firehose以及S3

创建一个S3存储桶,并配置S3存储桶不能为外部公开访问,另外在Kinesis Data Firehose中创建一个Delivery Stream传输流,选择目的地为S3,用于流式实时数据的传输。

# Create Kinesis Data Firehose Delivery Stream
resource "aws_kinesis_firehose_delivery_stream" "iotdemo_firehose_s3_stream" {
  name        = "iotdemo_firehose_s3_stream_test"
  destination = "extended_s3"
  extended_s3_configuration {
    role_arn   = aws_iam_role.iotdemo_firehose_role.arn
    bucket_arn = aws_s3_bucket.iotdemo_s3_bucket.arn
  }
}

# Create S3 Bucket
resource "aws_s3_bucket" "iotdemo_s3_bucket" {
  bucket = "${var.iotdemo_bucket_name}"
}
resource "aws_s3_bucket_public_access_block" "iotdemo_bucket_public_access" {
  bucket = aws_s3_bucket.iotdemo_s3_bucket.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
  • 创建IoT规则以及IAM权限到Firehose

在Amazon IoT规则引擎中创建一个IoT规则操作,将原始数据路由到Kinesis Data Firehose,通过Firehose将这些实时流数据保存在S3存储桶中。在这里作为示例,我们在原始数据的基础上添加了MQTT主题名以及云端当前时间戳等信息,同时使用“\n (newline)”来作为分割符。

# IoT Rule to Kinesis Firehose and S3
resource "aws_iot_topic_rule" "iotdemo_rule_kinesis_firehose" {
  name        = "iotdemo_rule_kinesis_firehose_test"
  description = "Rule to Kinesis Firehose for raw data of report"
  enabled     = true
  sql         = "SELECT *, topic() AS topic, timestamp() AS timestamp FROM 'dt/iotdemo/+/+'"
  sql_version = "2016-03-23"
  firehose {
    delivery_stream_name  = aws_kinesis_firehose_delivery_stream.iotdemo_firehose_s3_stream.name
    role_arn              = aws_iam_role.iotdemo_iot_kinesis_role.arn
    separator             = "\n"
  }
}

利用Terraform将设备即时数据保存到DynamoDB中

通过Amazon IoT规则引擎,将数据路由至Amazon DynamoDB来保存即时数据, DynamoDB的数据则可以供第三方系统及时获取作进一步的快速查询、处理和呈现。

  • 创建DynamoDB表

首先创建一个DynamoDB表。作为示例,在表中我们使用时间信息timestamp作为主键值,使用设备信息deviceId来二级索引。

# Create DynamoDB table
resource "aws_dynamodb_table" "iotdemo_dynamodb_table" {
  name           = "iotdemo_dynamodb_table_test"
  billing_mode   = "PROVISIONED"
  read_capacity  = 5
  write_capacity = 5
  hash_key       = "timestamp"
  range_key      = "deviceId"
  attribute {
    name = "timestamp"
    type = "S"
  }
  attribute {
    name = "deviceId"
    type = "S"
  }
}
  • 创建IoT规则到DynamoDB

然后在Amazon IoT规则引擎中创建一个IoT规则操作,将设备相关数据路由到DynamoDB中将这些设备数据保存在DynamoDB表中。作为示例,在这里我们将云端当前时间戳作为DynamoDB表中主键timestamp,用MQTT主题信息中的设备信息作为二级索引deviceId,以及将设备发送消息作为payload存入到DynamoDB表中。

# IoT Rule to DynamoDB
resource "aws_iot_topic_rule" "iotdemo_rule_dynamodb" {
  name        = "iotdemo_rule_dynamodb_test"
  description = "Rule to DynamoDB"
  enabled     = true
  sql         = "SELECT * FROM 'dt/iotdemo/+/+'"
  sql_version = "2016-03-23"
  dynamodb {
    table_name            = aws_dynamodb_table.iotdemo_dynamodb_table.name
    role_arn              = aws_iam_role.iotdemo_iot_dynamodb_role.arn
    hash_key_field        = "timestamp"
    hash_key_value        = "$${timestamp()}"
    range_key_field       = "deviceId"
    range_key_value       = "$${topic(3)}"
    payload_field         = "payload"
  }
}

利用Terraform将设备数据发送至 Lambda 函数以对设备信息进行处理

通过Amazon IoT规则引擎将数据路有发布到Lambda来处理一些特殊的数据,Lambda则可以进行数据处理以及将相关数据进一步发送至可以供第三方系统及时获取作进一步的处理和呈现。

  • 创建Lambda函数

首先创建Lambda函数。在创建Lambda函数时,我们假定Lambda同时也会调用在同一个VPC上部署的第三方系统内部服务,事先需要知道访问该VPC内部服务的相关子网信息和安全组信息。另外也需要准备Lambda功能函数代码,该代码将通过压缩打包的方式存入到压缩文件“iotdemo_lambda_function.zip”中。

# Lambda with VPC
resource "aws_lambda_function" "iotdemo_lambda" {
  filename      = "iotdemo_lambda_function.zip"
  function_name = "iotdemo_lambda_test"
  role          = aws_iam_role.iotdemo_lambda_role.arn
  handler       = "lambda_function.lambda_handler"
  source_code_hash = filebase64sha256("iotdemo_lambda_function.zip")
  runtime = "python3.7"
  vpc_config {
    subnet_ids         = ["${var.iotdemo_subnet_ids}"]
    security_group_ids = ["${var.iotdemo_security_group_ids}"]
  }
  environment {
    variables = {
      HTTP_API_URL = "https://xxx.xxx.xxx/xxx"
    }
  }
}
  • 创建IoT规则到Lambda

然后在Amazon IoT规则引擎中创建一个IoT规则操作,将数据路由到Lambda中来处理这些数据,并将相关数据发送至第三方系统作进一步的处理。作为示例,在Lambda中我们只是将设备发送来的数据通过HTTP POST的方式发送至第三方系统如https://xxx.xxx.xxx/xxx,具体逻辑请查看Lambda代码。

# IoT Rule to Lambda Function
resource "aws_iot_topic_rule" "iotdemo_rule_lambda" {
  name        = "iotdemo_rule_lambda_test"
  description = "Rule to Lambda"
  enabled     = true
  sql         = "SELECT *, topic(3) AS deviceId FROM 'dt/iotdemo/+/+'"
  sql_version = "2016-03-23"
  lambda {
    function_arn     = aws_lambda_function.iotdemo_lambda.arn
  }
}

本博文详细Terraform部署模版代码可以参考https://github.com/shouwu/iot-rule-tf。更多的IoT规则操作,也可以参考https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iot_topic_rule 里面的内容。

在Amazon IoT平台测试Terraform部署模版

在自动化部署完上述Terraform模版后,我们可以在Amazon IoT自带的MQTT测试客户端来进行测试:

点击发布后,上述MQTT主题的信息将发布出去,并且通过Terraform部署的三个IoT测试操作将该信息分布数据路由至Kinesis+S3,DynamoDB,以及Lambda进行数据存储和处理。进入S3、DynamoDB,以及CloudWatch的“/aws/lambda/iotdemo_lambda_test”的Log Group可以看到相关信息纪录和log信息。

总结

本博文介绍如何使用Terraform来对Amazon IoT进行规则操作的自动化部署。详细介绍了如何利用Amazon IoT规则操作在DynamoDB,通过Kinesis Data Firehose在S3来存储数据,以及使用Lambda进行数据处理。另外也提供了具体的Terraform部署模版的示例代码,供大家参考,从而更好的让大家能通过Terraform部署模版来自动化部署相关IoT规则操作,更好的便于管理以及可重复应用。

本篇作者

张守武

AWS专业服务团队物联网顾问。负责基于AWS IoT的解决方案咨询和项目交付,同时负责物联网行业解决方案的开发和推广,在物联网、网络、视频等领域有着广泛的设计和实践经验。

高业坤

AWS专业服务团队IoT架构师。负责基于AWS IoT的解决方案咨询,架构与交付,深度参与过智慧工厂、智慧供热等行业的IoT解决方案的咨询与交付。在智能家居、智慧安防、智能硬件等IoT行业拥有十年以上软件研发管理经验。