对象存储
平台保存的某些内容既不是数据行,也不是时序数据点,例如目前的租户徽标,以及未来的固件包。这些是不透明的二进制资源,不应放入关系数据库。DeviceChain 将它们保存在可插拔对象存储中:共享核心库提供统一接口,由配置选择存储后端。
对象存储与加密密钥存储并列,采用相同设计:一个接口、多种后端,以及带类型的配置。未知或无效后端会在启动时被拒绝,而不是静默忽略。两者分工严格:对象存储只保存非密钥二进制资源;凭据和其他密钥只保存在信封加密的密钥存储中,绝不保存在这里。
目前可用:对象存储接口及两个后端:文件系统(默认)和可直接替换的 S3 兼容后端(AWS S3 或 MinIO)。第一个使用方是租户白标(租户专属品牌徽标)。
**计划中:**Google Cloud Storage 后端、更大的品牌图像(例如登录背景)、固件/OTA 包和租户数据导出,全部使用同一接口。本仓库是判断当前哪些功能能够构建的权威依据。
一个接口,多种后端
任何存储二进制资源的功能都通过同一接口操作。没有功能直接调用存储 SDK。
- 文件系统(默认):对象保存在挂载卷上(Kubernetes 中为 PVC),无需云依赖。设置
blob.directory并启用 Chart 的blobStorage.persistence(在该路径挂载 PVC)后,它可以运行于本地 kind 集群或自行托管部署。Chart 默认不配置它。读取通过执行授权的 API 代理提供,没有直接访问文件的公开路径。 - S3 / S3 兼容:AWS S3 或自行托管的 MinIO,通过一个 API 覆盖两者。选择它只需修改配置,不需要修改代码。云后端还可以生成用于读取的预签名、有有效期的 URL。凭据来自标准云凭据链(环境变量、工作负载身份),绝不来自明文配置值。
每个已保存句柄都绑定到写入它的后端。已经在某个后端保存对象的实例,切换时必须迁移或重新上传这些对象。
由于所有使用方都通过统一接口操作,新增后端会同时惠及所有使用方。切换后端是部署决策,而不是逐功能迁移:只需迁移一次数据,不必为每个使用方分别迁移。
对象通过句柄引用
存储对象由不透明引用标识。使用方将句柄保存到自己的记录中(例如租户的 branding logo 字段),需要字节内容时解析引用。句柄不携带数据,字节内容只存在于存储中。
对象键带有实例和租户前缀,使每个租户的资源与其他租户分隔在不同命名空间。所有键片段都经过严格验证,因此基于路径的后端中,键绝不可能越过自身命名空间。
默认没有公开存储桶。 每次读取都通过 API 代理授权,或使用所属服务有意生成的短期签名 URL。
哪些内容进入对象存储
| 数据 | 存储位置 |
|---|---|
| 目前的品牌徽标;未来提供的固件包及其他二进制资源 | 对象存储(本页) |
| SMTP 密码、webhook 令牌、连接器凭据 | 加密密钥存储,采用信封加密、只写接口,并通过句柄解析 |
| 设备遥测数据和事件 | 通过 event-management 写入 TimescaleDB 超表 |
| 实体(设备、配置文件、仪表板等) | 关系数据库 |
关系型权威数据存储有意保持单一且不可插拔。二进制存储才适合做成可插拔,因为徽标或固件镜像的实际保存位置是部署偏好,而不是数据模型决策。
部署
默认文件系统后端只需要持久卷。设置 blob.directory 并启用 blobStorage.persistence,Helm Chart 就会创建 PVC,并挂载到存储资源的服务中。无需安装或维护额外基础设施。
选择 S3 后端只需修改实例配置。端点和存储桶属于非密钥配置。访问凭据从部署的凭据链解析,例如来自实例 Kubernetes Secret 的环境变量,或云集群中的工作负载身份。
与 DeviceChain 的所有配置接口一样,对象存储配置带类型且严格验证:拼错后端名称会导致启动错误,而不是静默回退。没有目录的文件系统后端视为“未配置对象存储”。服务仍然启动,徽标上传与读取端点返回 503,内联和 URL 徽标仍然可用。
第一个使用方:白标
租户白标是第一个基于对象存储构建的功能。租户徽标上传到存储中,并在租户品牌配置中通过句柄引用。没有配置存储的部署仍可以内联提供极小的资源(受大小限制的 data-URI),但真正的图像资源使用对象存储。品牌记录的 background 是十六进制颜色,不是图像。
固件/OTA 分发是大型二进制文件的主要场景,计划使用同一接口。