AWS IoT Greengrass
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

如何使用 AWS 命令行界面配置本地资源访问

此功能适用于 AWS IoT Greengrass Core 1.3 及更高版本。

要使用本地资源,您必须在部署到 Greengrass 核心设备的组定义中添加资源定义。该组定义还必须包含一个 Lambda 函数定义,以便在其中向 Lambda 函数授予本地资源的访问权限。有关更多信息(包括要求和约束),请参阅使用 Lambda 函数和连接器访问本地资源

本教程介绍了使用 AWS 命令行界面 (CLI) 创建本地资源并配置其访问权限的过程。要执行本教程中的步骤,您必须已创建一个 Greengrass 组,如AWS IoT Greengrass 入门 中所述。

有关使用 AWS 管理控制台的教程,请参阅如何使用 AWS 管理控制台配置本地资源访问

创建本地资源

首先,您使用 CreateResourceDefinition 命令创建一个资源定义以指定要访问的资源。在此示例中,我们创建两个资源(TestDirectoryTestCamera):

aws greengrass create-resource-definition --cli-input-json '{ "Name": "MyLocalVolumeResource", "InitialVersion": { "Resources": [ { "Id": "data-volume", "Name": "TestDirectory", "ResourceDataContainer": { "LocalVolumeResourceData": { "SourcePath": "/src/LRAtest", "DestinationPath": "/dest/LRAtest", "GroupOwnerSetting": { "AutoAddGroupOwner": true, "GroupOwner": "" } } } }, { "Id": "data-device", "Name": "TestCamera", "ResourceDataContainer": { "LocalDeviceResourceData": { "SourcePath": "/dev/video0", "GroupOwnerSetting": { "AutoAddGroupOwner": true, "GroupOwner": "" } } } } ] } }'

资源:Greengrass 组中的 Resource 对象列表。一个 Greengrass 组最多可包含 50 个资源。

Resource#Id:资源的唯一标识符。该 ID 用于在 Lambda 函数配置中引用资源。最大长度为 128 个字符。模式:[a-zA-Z0-9:_-]+。

Resource#Name:资源的名称。资源名称显示在 Greengrass 控制台中。最大长度为 128 个字符。模式:[a-zA-Z0-9:_-]+。

LocalDeviceResourceData#SourcePath:设备资源的本地绝对路径。设备资源的源路径只能引用 /dev 中的字符设备或块储存设备。

LocalVolumeResourceData#SourcePath:Greengrass 核心设备上的卷资源的本地绝对路径。此位置位于函数在其中运行的容器之外。卷资源类型的源路径不能以 /sys 开头。

LocalVolumeResourceData#DestinationPath:Lambda 环境中的卷资源的绝对路径。此位置位于函数在其中运行的容器之内。

GroupOwnerSetting:允许您为 Lambda 进程配置额外的组权限。此字段为可选项。有关更多信息,请参阅 组所有者文件访问权限

GroupOwnerSetting#AutoAddGroupOwner:如果为 true,则 Greengrass 自动将资源的指定 Linux 操作系统组所有者添加到 Lambda 进程权限。因此,Lambda 进程具有添加的 Linux 组的文件访问权限。

GroupOwnerSetting#GroupOwner:指定将权限添加到 Lambda 进程的 Linux 操作系统组的名称。此字段为可选项。

CreateResourceDefinition 将返回一个资源定义版本 ARN。在更新组定义时,应使用该 ARN。例如:

{ "LatestVersionArn": "arn:aws:greengrass:us-west-2:012345678901:/greengrass/definition/resources/ab14d0b5-116e-4951-a322-9cde24a30373/versions/a4d9b882-d025-4760-9cfe-9d4fada5390d", "Name": "MyLocalVolumeResource", "LastUpdatedTimestamp": "2017-11-15T01:18:42.153Z", "LatestVersion": "a4d9b882-d025-4760-9cfe-9d4fada5390d", "CreationTimestamp": "2017-11-15T01:18:42.153Z", "Id": "ab14d0b5-116e-4951-a322-9cde24a30373", "Arn": "arn:aws:greengrass:us-west-2:123456789012:/greengrass/definition/resources/ab14d0b5-116e-4951-a322-9cde24a30373" }

创建 Greengrass 函数。

在创建资源后,请使用 CreateFunctionDefinition 命令创建 Greengrass 函数,并为该函数授予资源访问权限:

aws greengrass create-function-definition --cli-input-json '{ "Name": "MyFunctionDefinition", "InitialVersion": { "Functions": [ { "Id": "greengrassLraTest", "FunctionArn": "arn:aws:lambda:us-west-2:012345678901:function:lraTest:1", "FunctionConfiguration": { "Pinned": false, "MemorySize": 16384, "Timeout": 30, "Environment": { "ResourceAccessPolicies": [ { "ResourceId": "data-volume", "Permission": "rw" }, { "ResourceId": "data-device", "Permission": "ro" } ], "AccessSysfs": true } } } ] } }'

ResourceAccessPolicies:包含授予 Lambda 访问资源权限的 resourceIdpermission。Lambda 函数最多可以具有 10 个资源。

ResourceAccessPolicy#Permission:指定 Lambda 对资源具有哪些权限。可用的选项为 rw(读/写)或 ro(只读)。

AccessSysfs:如果为 true,则 Lambda 进程对 Greengrass 核心设备上的 /sys 文件夹具有读取访问权限。这在 Greengrass Lambda 需要从 /sys 读取设备信息的情况下使用。

同样,CreateFunctionDefinition 返回一函数定义版本 ARN。应在组定义版本中使用该 ARN。

{ "LatestVersionArn": "arn:aws:greengrass:us-west-2:012345678901:/greengrass/definition/functions/3c9b1685-634f-4592-8dfd-7ae1183c28ad/versions/37f0d50e-ef50-4faf-b125-ade8ed12336e", "Name": "MyFunctionDefinition", "LastUpdatedTimestamp": "2017-11-22T02:28:02.325Z", "LatestVersion": "37f0d50e-ef50-4faf-b125-ade8ed12336e", "CreationTimestamp": "2017-11-22T02:28:02.325Z", "Id": "3c9b1685-634f-4592-8dfd-7ae1183c28ad", "Arn": "arn:aws:greengrass:us-west-2:123456789012:/greengrass/definition/functions/3c9b1685-634f-4592-8dfd-7ae1183c28ad" }

将 Lambda 函数添加到组

最后,使用 CreateGroupVersion 将该函数添加到组中。例如:

aws greengrass create-group-version --group-id "b36a3aeb-3243-47ff-9fa4-7e8d98cd3cf5" \ --resource-definition-version-arn "arn:aws:greengrass:us-west-2:123456789012:/greengrass/definition/resources/db6bf40b-29d3-4c4e-9574-21ab7d74316c/versions/31d0010f-e19a-4c4c-8098-68b79906fb87" \ --core-definition-version-arn "arn:aws:greengrass:us-west-2:123456789012:/greengrass/definition/cores/adbf3475-f6f3-48e1-84d6-502f02729067/versions/297c419a-9deb-46dd-8ccc-341fc670138b" \ --function-definition-version-arn "arn:aws:greengrass:us-west-2:123456789012:/greengrass/definition/functions/d1123830-da38-4c4c-a4b7-e92eec7b6d3e/versions/a2e90400-caae-4ffd-b23a-db1892a33c78" \ --subscription-definition-version-arn "arn:aws:greengrass:us-west-2:123456789012:/greengrass/definition/subscriptions/7a8ef3d8-1de3-426c-9554-5b55a32fbcb6/versions/470c858c-7eb3-4abd-9d48-230236bfbf6a"

返回新组版本:

{ "Arn": "arn:aws:greengrass:us-west-2:012345678901:/greengrass/groups/b36a3aeb-3243-47ff-9fa4-7e8d98cd3cf5/versions/291917fb-ec54-4895-823e-27b52da25481", "Version": "291917fb-ec54-4895-823e-27b52da25481", "CreationTimestamp": "2017-11-22T01:47:22.487Z", "Id": "b36a3aeb-3243-47ff-9fa4-7e8d98cd3cf5" }

您的 Greengrass 组现在包含 lraTest Lambda 函数,该函数可以访问两个资源:TestDirectory 和 TestCamera。

以下示例 Lambda 函数 (lraTest.py) 是使用 Python 编写的,它写入到本地卷资源:

# Demonstrates a simple use case of local resource access. # This Lambda function writes a file "test" to a volume mounted inside # the Lambda environment under "/dest/LRAtest". Then it reads the file and # publishes the content to the AWS IoT "LRA/test" topic. import sys import greengrasssdk import platform import os import logging # Create a Greengrass Core SDK client. client = greengrasssdk.client('iot-data') volumePath = '/dest/LRAtest' def function_handler(event, context): client.publish(topic='LRA/test', payload='Sent from AWS IoT Greengrass Core.') try: volumeInfo = os.stat(volumePath) client.publish(topic='LRA/test', payload=str(volumeInfo)) with open(volumePath + '/test', 'a') as output: output.write('Successfully write to a file.\n') with open(volumePath + '/test', 'r') as myfile: data = myfile.read() client.publish(topic='LRA/test', payload=data) except Exception as e: logging.error("Experiencing error :{}".format(e)) return

这些命令由 Greengrass API 提供,用于创建和管理资源定义及资源定义版本:

故障排查

  • 问:为什么我的 Greengrass 组部署失败,错误类似于:

    group config is invalid: ggc_user or [ggc_group root tty] don't have ro permission on the file: /dev/tty0

    答:此错误表明该 Lambda 进程没有访问指定资源的权限。解决方案是更改资源的文件权限,以便 Lambda 可以访问该资源。(请参阅组所有者文件访问权限以了解详细信息。)

  • 问:/var/run 配置为卷资源时,为什么 Lambda 函数无法启动,且 runtime.log 中包含错误消息:

    [ERROR]-container_process.go:39,Runtime execution error: unable to start lambda container. container_linux.go:259: starting container process caused "process_linux.go:345: container init caused \"rootfs_linux.go:62: mounting \\\"/var/run\\\" to rootfs \\\"/greengrass/ggc/packages/1.3.0/rootfs_sys\\\" at \\\"/greengrass/ggc/packages/1.3.0/rootfs_sys/run\\\" caused \\\"invalid argument\\\"\""

    答:AWS IoT Greengrass Core 当前不支持将 /var/var/run/var/lib 配置为卷资源。一种解决办法是首先在不同的文件夹中挂载 /var/var/run/var/lib,然后将该文件夹配置为卷资源。

  • 问:/dev/shm 配置为具有只读权限的卷资源时,为什么 Lambda 函数无法启动并在 runtime.log 中显示错误:

    [ERROR]-container_process.go:39,Runtime execution error: unable to start lambda container. container_linux.go:259: starting container process caused "process_linux.go:345: container init caused \"rootfs_linux.go:62: mounting \\\"/dev/shm\\\" to rootfs \\\"/greengrass/ggc/packages/1.3.0/rootfs_sys\\\" at \\\"/greengrass/ggc/packages/1.3.0/rootfs_sys/dev/shm\\\" caused \\\"operation not permitted\\\"\""”

    答:/dev/shm 只能配置为读/写。将资源权限更改为 rw 以解决该问题。