AWS IoT Core使用rule将消息转发到Kafka

744 阅读6分钟

简介

当我们的IoT设备使用MQTT协议接入到AWS IoT Core后,它们会实时的上报一些信息,比如一个环境温度传感器会以分钟为单位定时的上报自己周围的环境温度,当一个城市里面数万个温度传感器都进行环境温度的检测时,这些大量的数据就变得非常有价值,我们可以精确的绘制出该城市的市区温度热力图等。

IoT设备对数据的上报是一个必备的基础功能,接下来我们需要高效的将这些设备上报的大量的有价值的数据扭转其他的后端服务上去,比如传送到后端大数据平台做进一步的分析等,才能充分的发挥IoT领域数据的价值。对于这个场景AWS IoT解决方案提供了AWS IoT Core Rule,我们可以通过rule(规则)将消息做一个转发,比如转发到AWS SQS,AWS Lambda等,详情可以看rule actions,这样下游的服务就可以消费转发来的消息了。

参考rule actions,我们以AWS MSK(AWS托管的Kafka)为例来演示,怎么通过AWS IoT Core Rule功能将消息转发到Kafka中去。详细的架构图如下:

image.png

集成AWS IoT 与 AWS MSK

本次的演练的AWS MSK是运行在AWS VPC中的并且位于private subnet中,private subnet里面的服务可以通过NAT Gateway访问外部的互联网。

设置AWS IAM Role

让AWS IoT Core执行消息转发的操作,必须指导正确的权限,这里我们是转发到AWS MSK所以我创建了一个AWS IAM role并给了一个自定义的名称PoC_iot_rule_role,我给这个role附加了2个关键性的policy,其中一个是AWS托管的AWSIoTRuleActions,例外一个是我们自建的inline policy,名称为iot_rule_inline_kafka,它专门负责管理AWS IoT Core rule操作AWS MSK相关的权限。

image.png

我的iot_rule_inline_kafka的如下:

你需要将<your-aws-region><your-aws-account-id>替换为你自己的aws区域和账户id。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateNetworkInterface",
                "ec2:DescribeNetworkInterfaces",
                "ec2:CreateNetworkInterfacePermission",
                "ec2:DeleteNetworkInterface",
                "ec2:DescribeSubnets",
                "ec2:DescribeVpcs",
                "ec2:DescribeVpcAttribute",
                "ec2:DescribeSecurityGroups"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "secretsmanager:DescribeSecret"
            ],
            "Resource": [
                "arn:aws:secretsmanager:<your-aws-region>:<your-aws-account-id>:secret:kafka_client_truststore-*",
                "arn:aws:secretsmanager:<your-aws-region>:<your-aws-account-id>:secret:kafka_keytab-*",
                "arn:aws:secretsmanager:<your-aws-region>:<your-aws-account-id>:secret:AmazonMSK_*",
                "arn:aws:secretsmanager:<your-aws-region>:<your-aws-account-id>:secret:*",
                "arn:aws:secretsmanager:<your-aws-region>:<your-aws-account-id>:AmazonMSK_*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "ec2:CreateNetworkInterfacePermission",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/VPCDestinationENI": "true"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:CreateAction": "CreateNetworkInterface",
                    "aws:RequestTag/VPCDestinationENI": "true"
                }
            }
        }
    ]
}

设置AWS KMS和AWS Secrets Manager

我后续搭建的Kafka是使用SCRAM/SASL授权并开启了数据加密,所以我先需要使用AWS KMSAWS Secrets Manager,其中AWS Secrets Manager做Kafka的username/password管理,AWS KMS做AWS MSK数据加密和对AWS Secrets Manager数据的加密。

设置AWS KMS

首先,我们打开AWS KMS控制台,请注意选择自己的服务区。

这是我的AWS KMS控制台

image.png

我们点击Customer managed keys,创建自己管理的key

image.png

选择symmetric key,按照我画红色方框的部分来设置,其他的默认,直接Next image.png

填写下描述,然后Next

image.png

这里的Key administrators暂时先别写,全部用默认设置即可,直接Next image.png

这里Define key usage permissions也是,使用默认设置,直接Next

image.png

接着我们直接创建KMS

image.png

创建完后我们可以看到自己的KMS Key,如红色方框部分

image.png

关联AWS IAM Role和AWS KMS

image.png

设置AWS Secrets Manager

我们接着打开AWS Secrets Manager,为AWS MSK提前设置好密码。

这是我的界面,我们直接创建

image.png

image.png

接下来选择Other type of secret

image.png

填入自己的username/password并选择使用上一步创建的KMS key,名称为kms-2022,然后点击Next

image.png

我们填入名字和描述,其中名字必须以AmazonMSK_开头

image.png

其余的保持默认配置

image.png

创建好后的样子如下

image.png

设置AWS MSK

前面创建好了AWS KMS和AWS Secrets Manager后,我们接着创建AWS MSK

这是我的界面,我们直接创建

image.png

我们选择Custom create并给一个名称 image.png

我们选择Provisioned类型,版本我选择kafka 3.2.0 image.png

为了节约成本,我选择使用t3.small实例并设置数量为2 image.png

设置Number of brokers per zone=1,Storage=100G

image.png

其余的保持默认 image.png

我们接着指定AWS MSK的网络,这里我选择了一个VPC,并选择了First Zone位于us-east-1a可用区中的private subnet里面。 image.png

我们接着为自己的Second zone选择位于us-east-1b的private subnet里面。 image.png

通过将MSK分布在不同的可用区,可以显著的提升MSK的可用性。

我们接着为自己的MSK设置安全组 image.png

安全组的规则为

image.png

接下来我们选择MSK使用SASL/SCRAM认证 image.png

接下来我们使用前面创建的KMS Key,名称为kms-2022

image.png

其余的保持默认配置,直接创建,等待15min左右就会创建完成。

AWS MSK关联AWS Secrets Manager

当我们的MSK创建完成后,需要继续关联AWS Secrets Manager

当AWS MSK创建完成后,进入到详情页会看到一个提示,我们直接将这个MSK和前面创建好的AWS Secrets Manager关联 image.png

效果如下 image.png

设置AWS IoT Core

设置destination

我们到AWS IoT Core的控制界面 image.png

然后创建destination

image.png

选择VPC,子网,安全组和AWS IAM Role。其中VPC,子网,安全组建议和MSK的保持一致,AWS IAM Role是前面我们已经创建过的PoC_iot_rule_role

image.png

然后直接创建,效果如下

image.png

设置rule

我们最后来创建rule

直接点击创建 image.png

接着填入rule的名称 image.png

然后编写自己的rule语句 image.png

选择action为AWS MSK

image.png

选择VPC并给一个kafka topic image.png

将AWS MSK的Private endpoint填入AWS IoT core的bootstrap.servers中 image.png

image.png

SSL和SASL设置如下 image.png

为AWS IoT Core rule填入username/password,其中这些消息是从AWS Secrets Manager获取的。 image.png

我这里填入的字符如下,其中AmazonMSK_iot_rule为前面创建的Secret的名称,arn:aws:iam::843xxx41269:role/PoC_iot_rule_role是role的ARN

username: ${get_secret('AmazonMSK_iot_rule', 'SecretString', 'username', 'arn:aws:iam::843xxx41269:role/PoC_iot_rule_role')}

password: ${get_secret('AmazonMSK_iot_rule', 'SecretString', 'password', 'arn:aws:iam::843xxx41269:role/PoC_iot_rule_role')}

然后保存即可

调试与检查

我们接着可以使用一台AWS EC2,SSH远程连接到EC2,并使用EC2订阅AWS MSK,查看里面的消息是否由AWS IoT core转发到了AWS MSk,详情可以参考How to integrate AWS IoT Core with Amazon MSK中Testing the AWS IoT rule章节

生产者:

image.png

消费者:

image.png

本文参考