本文档就如何为在环境边缘运行的设备设计和实现可靠的自动化预配和配置流程提供了一些最佳做法建议,例如:
如果您为边缘设备、裸机系统和服务器设计预配和配置流程,或者您想要详细了解预配和配置这些设备类型的最佳实践,请阅读本文档。
本文档未列出预配和配置边缘和裸机系统及服务器的所有可能的最佳实践,并且它不保证您可以成功。但是,它可以帮助您促进对预配和配置流程的潜在更改和改进的讨论。
本文档是系列文档中的一篇,该系列介绍了 Google Cloud 上的 IoT 架构。本系列中的其他文档包括以下内容:
- Google Cloud 上的关联设备架构概览
- Google Cloud 上的独立 MQTT 代理架构
- Google Cloud 上的 IoT 平台产品架构
- 将 Pub/Sub 架构上的设备迁移到 Google Cloud
- 在 Google Cloud 上运行 IoT 后端的最佳做法
- 自动预配和配置边缘与裸机系统和服务器的最佳实践(本文档)
- 从 IoT Core 迁移环境
手动预配和配置大量设备容易出现人为错误,并且无法随着设备的增加而自行扩容。例如,您可能会忘记运行关键的预配或配置任务,或者您可能会部分或完全依赖于非正式流程。您可以借助可靠的全自动预配和配置流程来解决这些问题。此外,您还可以利用此类流程来管理每个设备的生命周期,包括从制造到停用再到处置的整个过程。
术语
以下术语对于了解如何为您的设备实现和构建自动预配和配置流程非常重要:
- 边缘设备:部署在环境的边缘处、靠近您要处理的数据的设备。
- 预配流程:为准备设备配置而必须完成的一组任务。
- 配置流程:为使设备准备好在特定环境中运行而必须完成的一组任务。
- 配置管理:持续执行的一组任务,用于管理环境和设备的配置。
- 基础映像:由您的公司或者由设备或操作系统制造商生产的最小单位的正常工作的操作系统 (OS) 或固件映像。
- 黄金映像:您为设备创建的或从基础映像准备的不可变操作系统或固件映像。黄金映像包含设备完成被分配的任务所需的所有数据和配置信息。您可以准备各种黄金映像来完成不同的任务。黄金映像类型的同义词包括变种、Spin 和原型。
- 白银映像:通过对黄金映像或基础映像应用最小更改来为设备准备的操作系统映像或固件映像。运行白银映像的设备在首次启动时会完成预配和配置,具体取决于这些设备必须支持的用例需求。
- 种子设备:在没有外部依赖项的情况下引导环境的设备。
- 网络启动:可让设备从网络而不是从连接到设备的存储系统获取软件和任何相关配置信息的技术集合。
为了帮助您设置目标并避免常见问题,请应用以下部分中介绍的预配和配置的最佳实践。
自动执行预配和配置流程
在首次启动期间或者在任何必要的时候,您的设备都应能够仅使用其内安装的软件映像进行预配和配置。
为了避免在预配和配置流程期间实现所需的逻辑,您可以使用一些工具来为您提供编排和实现这些流程所需的原语。例如,您可以将 cloud-init 及其 NoCloud 数据源与脚本或配置管理工具(例如针对本地主机运行的 Ansible、Puppet 或 Chef)搭配使用。
如需设计可靠的预配和配置流程,请确保在这些流程中执行的所有步骤和任务都有效(尽可能采用自动化方式)。例如,您可以使用自动化合规性测试框架(例如 InSpec)来验证您的预配和配置流程是否按预期运行。
此最佳做法可以帮助您避免单点故障,并且在完成设备预配和配置的过程中无需进行人工干预。
避免使用特殊用途设备
在设计边缘设备时,应尽量减少这些设备在用途和专业方面的差异。这一建议并不是说您的所有边缘设备必须完全相同或者具有完全相同的用途,但它们应尽可能同构。例如,您可以按设备需要支持的工作负载类型来定义设备原型。然后,您可以根据这些原型的属性来部署和管理设备。
为确保遵循此最佳做法,请验证是否可以从给定原型的设备中随机选择一个设备,然后执行以下操作:
- 像处理其他相同原型的设备一样处理该设备。这样做表明您具有较高的运营效率。
- 将设备替换为其他相同原型的设备,而无需进行额外的自定义操作。这样做表明您已正确实现这些原型。
这项最佳做法可以确保降低设备舰队中的差异,从而减少环境以及预配和配置流程中的碎片化情况。
使用种子设备引导您的环境
预配和配置设备时,您可能会遇到循环依赖项问题:您的设备需要借助辅助基础架构来对其自身进行预配和配置,但该基础架构并未准备就绪,因为您也需要预配和配置该基础架构。
您可以借助种子设备来解决此问题。种子设备具有临时性特殊用途。在完成所设计的特殊用途的任务后,设备的行为和状态会与相关原型相符。
例如,如果您使用 cloud-init 自动初始化您的设备,则可能需要通过以下方式配置 cloud-init NoCloud 数据源:
- 通过文件系统向种子设备提供 NoCloud 数据源数据。
等待种子设备完成其自身特殊用途的预配和配置,这包括通过网络向其他设备提供 NoCloud 数据源数据。
然后种子设备上的预配和配置流程会等待,直到满足丢弃种子设备的临时性特殊用途的条件为止。下面是这些条件的一些示例:
- 环境中是否还有其他设备通过网络提供 NoCloud 数据源数据?
- 集群中是否有足够的节点?
- 首次备份是否已完成?
- 灾难恢复站点是否已准备就绪?
预配和配置其他通过网络从种子设备下载 NoCloud 数据源数据的设备。某些设备要求必须能够通过网络提供 NoCloud 数据源数据。
由于满足了下述丢弃种子设备特殊用途的条件,系统会恢复种子设备的预配和配置流程:舰队中有其他设备通过网络提供 NoCloud 数据源数据。
种子设备上的预配和配置流程会丢弃特殊用途,从而使得种子设备与同一原型的其他设备没有区别。
这项最佳做法可以确保即使没有辅助基础架构,您也可以在不违反避免使用特殊用途设备最佳做法的情况下引导您的环境。
最大限度地减少设备的有状态性
在设计边缘设备时,应尽量减少存储有状态信息的需求。边缘设备可能硬件资源有限,或者部署在恶劣的环境中。尽量减少正常运行所需的有状态信息,以便您可以同构处理此类设备,从而简化预配、配置、备份和恢复流程。例如,如果某个无状态边缘设备出现故障且不可恢复,那么您可以将其与同一原型的其他设备进行交换,以最大限度地减少中断或数据丢失。
此项最佳做法可帮助您避免因数据丢失或因流程过于复杂而导致意外问题。大多数的复杂性来自于支持异构设备舰队的需要。
自动构建操作系统和固件映像
为了避免在设备首次启动时进行昂贵的预配和配置任务以及为了节省设备资源,请在提供操作系统映像和固件映像之前先对其进行自定义。例如,您可以直接在映像中安装依赖项,而不是在每个设备首次启动时安装这些依赖项。
为设备准备操作系统映像和固件映像时,您需要从基础映像开始。自定义基础映像时,您可以执行以下操作:
- 生成黄金映像。黄金映像包含映像中的所有依赖项,这样您的设备就无需在首次启动时安装这些依赖项。虽然生成黄金映像可能是一项复杂的任务,但它们可以让设备在预配和配置期间节省时间和资源。
- 生成白银映像。与黄金映像不同,运行白银映像的设备会在首次启动期间完成所有预配和配置流程。虽然生成白银映像可能比生成黄金映像要简单一些,但运行白银映像的设备在预配和配置期间将需要花费更多的时间和资源。
您可以在持续集成和持续部署 (CI/CD) 流程中自定义操作系统映像和固件映像,并在进行验证后自动将自定义映像提供给您的设备。您使用诸如 Cloud Build、GitHub Actions、GitLab CI/CD 或 Jenkins 等工具实现的 CI/CD 流程可以执行以下任务序列:
- 对自定义映像执行自动验证。
- 将自定义映像发布到可供设备获取的代码库中。
如果您的 CI/CD 环境以及需要构建映像的操作系统或固件使用的是不同的硬件架构,那么您可以使用 QEMU 等工具来模拟这些架构。例如,您可以在 x86_64 架构上模拟 ARM 系列的硬件架构。
如需自定义操作系统映像或固件映像,您需要能够修改它们并在测试环境中验证这些修改,然后再将其安装到边缘设备中。借助 chroot 等工具,您可以在运行命令之前虚拟更改根目录,而非实际更改。
此项最佳做法可帮助您在将操作系统映像和固件映像提供给设备之前先自定义这些映像。
可靠地编排设备上运行的工作负载
如果您的设备支持异构工作负载,那么您可以使用以下工具编排这些工作负载并管理其生命周期:
- 工作负载编排系统:使用 Kubernetes 等工作负载编排系统适用于具有复杂的编排或生命周期管理要求的工作负载。这些系统也适用于跨多个组件的工作负载。这意味着在这两种情况下,您无需自行实现编排和工作负载生命周期管理逻辑。如果您的设备资源受限,那么您可以安装所需资源少于规范资源的轻量级 Kubernetes 发行版,例如 MicroK8s、K3s 或使用边缘配置文件安装的 Google Distributed Cloud。
init 系统:使用 init 系统(如 systemd)适用于具有以下特性的工作负载:
- 编排要求简单
- 缺少资源来支持工作负载编排系统
- 工作负载无法放置在容器中
在准备好用于编排工作负载的系统之后,您还可以使用该系统来运行预配和配置流程中的任务。例如,如果您需要在预配和配置流程中运行配置管理工具,则您可以像使用任何其他工作负载一样使用工作负载编排系统。
这项最佳做法有助于确保您能够编排设备上运行的工作负载。
对设备予以验证、完成身份验证并进行连接
如果您需要验证设备是否需要连接到外部系统(例如其他设备或后端),请考虑以下小节中的建议。
此项最佳做法可以帮助您:
- 为设备设计安全的通信通道。
- 避免绕过设备安全边界的潜在后门。
- 验证您的设备是否未公开任何攻击者可能会利用的未经授权的接口。
应实施的连接做法
- 在交换任何信息之前,均应先对发出信息请求的其他方进行身份验证。
- 验证所传输的信息是否没有在意外的通道之间传输。
- 依靠可信执行环境来处理密文,如加密密钥、身份验证密钥和密码。
- 在使用前,验证任何操作系统或固件映像的完整性和真实性。
- 验证用户提供的任何配置的有效性、完整性和真实性。
- 不安装非必要软件并移除设备上已存在的任何非必要软件,限制受攻击面。
- 限制特权操作和账号的使用。
- 验证设备外壳的完整性,以防范物理操作和篡改。
应避免的连接做法
- 请勿通过未加密的通道传输敏感信息。
- 避免将特权访问通道保持打开状态,例如:
- 避免使用具有更高权限的虚拟或物理串行端口和串行控制台,即使只有在有人实际篡改设备时才能访问此类端口也是如此。
- 避免使用响应来自网络的请求并且可以运行特权操作的端点。
- 不要依赖于操作系统映像、固件映像、配置或源代码中的硬编码凭据。
- 不要泄露任何可能帮助攻击者收集信息来获取更高权限的信息。例如,您应该加密设备上的数据,并关闭生产设备上不需要的跟踪和日志记录系统。
- 不要让用户和工作负载执行任意代码。
监控您的设备
在没有人工干预的情况下,收集设备状态的相关信息对于环境的可靠性而言至关重要。确保您的设备自动报告所需的所有数据。收集和监控数据有两个主要原因:
- 帮助您确保设备能够按预期运行。
- 主动发现问题并执行预防性维护。
例如,您可以使用 Cloud Monitoring 收集监控指标和事件。
为了帮助您调查和解决问题,我们建议您设计和实现流程以收集高分辨率诊断数据,例如详细的监控、跟踪和调试信息,而不是在正常运行期间监控您的设备的流程。使用设备资源(例如计算、数据存储和电力)收集高分辨率诊断数据并通过网络传输这些数据的成本可能很高。因此,我们建议您仅在必要时启用进程以收集高分辨率诊断数据,且仅适用于需要进一步调查的设备。例如,如果您的某个设备无法按预期运行,并且设备报告的常规监控数据不足以全面诊断问题,您可以为该设备启用高分辨率数据收集,以便该设备将报告更多信息,从而帮助您调查问题的原因。
这项最佳做法可确保您不会使设备处于未知状态,并且您拥有足够的数据来确定设备的运行和性能状况。
支持无人参与的启动和升级
在设计预配和配置流程时,请确保设备能够支持无人参与的启动,并且具备必要的基础架构。通过实现无人参与的启动机制来支持首次启动及后续通过无线下载进行的升级,您可以提高基础架构的可维护性。借助无人参与的启动机制,您无需在启动或升级每个设备时进行人工干预。人工干预大型设备舰队比较容易出错,因为操作者可能会错过或错误地执行某些操作,或者可能没有足够的时间来针对设备舰队中的每个设备执行所需的操作。
此外,您不必提前准备每个设备来启动正确的操作系统或固件映像。例如,您可以发布新版本的操作系统或固件映像,并将该版本作为设备在从网络获取其启动指令时可以选择的选项之一。
此项最佳做法有助于确保您的设备能够执行无人参与的自动启动和升级。
设计和实现弹性流程
即使采用完全自动化的预配和配置流程,仍可能会出现一些错误,导致这些流程无法正确完成,从而使设备处于不一致的状态。通过实现重试和回退机制,帮助确保您的设备能够从此类故障中恢复。例如,当设备无法完成预配和配置流程中的某个任务时,它应该自动尝试从该故障恢复。在设备从故障中恢复或回退到工作状态后,便可以从流程故障点恢复正在运行的流程。
此项最佳做法可帮助您设计和实现弹性预配和配置流程。
支持设备的整个生命周期
在设计预配和配置流程时,请确保这些流程可以管理整个设备生命周期。有效管理设备生命周期也涉及规划终止和处置,即使您的设备计划运行相对较长时间也应进行此类规划。
如果不对设备的生命周期进行管理,则可能会出现诸如以下问题:
- 持续的高昂费用:在预配和配置流程完成之后再引入生命周期管理支持会增加费用。通过在设计阶段尽早规划该项支持,可以降低这些费用。例如,如果您的预配和配置流程不支持设备的整个生命周期,那么您可能需要在每个设备上进行人工干预,才能正确处理其生命周期的每个阶段。人工干预的成本可能很高,并且在这种情况下系统通常不会自行扩缩。
- 不够灵活:如果不支持生命周期管理,最终可能会导致您无法更新或管理设备。例如,如果您缺少一种机制来高效安全地关闭设备,那么可能会难以管理设备的服务终止和最终处置。
后续步骤
- 了解 Google Cloud 上的已连接的设备架构。
- 如需查看更多参考架构、图表和最佳做法,请浏览云架构中心。 搭配使用。
贡献者
作者:Marco Ferrari | 云解决方案架构师