RGW Metadata Search
我最近一直在致力于为 rgw 添加元数据搜索功能。它还没有完成,也没有完全准备好。但我认为它已经达到了一个可以获得一些反馈的阶段。此功能建立在另一个功能之上,几个月前我在 CDM 上讨论过该功能,即“同步模块”(以前称为“同步插件”)功能。当前代码可以在以下 PR 中找到
https://github.com/ceph/ceph/pull/10731
元数据搜索(通过 elasticsearch)所依赖的“同步模块”功能提供了一个框架,允许将数据(和元数据)转发到外部层。它扩展了当前的多区域功能,使得当前的同步过程使用默认同步模块。同步模块是一组回调函数,这些函数会在单个区域组中的数据(以及潜在的元数据,例如,bucket 创建、新用户等;请注意:对象元数据的更改被视为数据中的更改)发生更改时被调用。rgw 多区域系统是最终一致的,因此更改不会同步应用。
同步模块与一个区域相关联。每个区域都有负责处理跨区域数据同步的模块。同步模块定义了该区域是否可以导出数据(例如,常规 rgw 数据),或者只能消化在另一个区域修改的数据(例如,日志区域、元数据搜索等)。
区域组配置中的区域定义具有一个新的 'tier_type' 字段。此参数控制将用于处理跨区域数据同步的同步模块。区域私有配置(未暴露给其他区域)具有一个新的部分,可用于传递同步模块特定的配置参数。一个这样的参数示例是模块将使用的 elasticsearch 服务器的端点。
同步模块与一个区域相关联。每个区域都有负责处理跨区域数据同步的模块。同步模块定义了该区域是否可以导出数据(例如,常规 rgw 数据),或者只能消化在另一个区域修改的数据(例如,日志区域、元数据搜索等)。
区域组配置中的区域定义具有一个新的 'tier_type' 字段。此参数控制将用于处理跨区域数据同步的同步模块。请参阅此处
$ mrun c1 radosgw-admin zonegroup get { ... "zones": [ { "id": "cc602d3a-de81-4682-ad51-59765acad32c", "name": "us-west", "endpoints": [ "https://:8001" ], "log_meta": "false", "log_data": "true", "bucket_index_max_shards": 0, "read_only": "false", "tier_type": "elasticsearch" }, { "id": "cde6b332-5bb8-4dc0-8219-b68932565ea1", "name": "us-east-1", "endpoints": [ "https://:8000" ], "log_meta": "true", "log_data": "true", "bucket_index_max_shards": 0, "read_only": "false", "tier_type": "" } ], ... }
区域私有配置(未暴露给其他区域)具有一个新的部分,可用于传递同步模块特定的配置参数。一个这样的参数示例是模块将使用的 elasticsearch 服务器的端点。
$ mrun c2 radosgw-admin zone get { ... "metadata_heap": "us-west.rgw.meta", "tier_config": [ { "key": "endpoint", "val": "https://:9200" } ], ... }
同步模块的一个简单实现示例是日志模块,它将需要同步的每个对象转储到 rgw 调试日志中,以及与之关联的操作(创建、删除、删除标记)。请注意,对于对象创建,它仅提供需要同步的对象的名称,而不提供有关该对象的任何额外信息(例如对象的大小和元数据)。我们还具有一种不太简单的实现,它从源区域获取与需要同步的对象关联的所有元数据。这为元数据索引模块奠定了基础。
通过 elasticsearch 进行元数据搜索 ¶
我们讨论的解决方案是使用 elasticsearch 索引元数据。当这里说元数据时,我指的是与数据对象关联的所有元数据。这些元数据包括对象名称、包含的 bucket 名称、大小、内容类型、用户指定的元数据、ACL 等。我们还将能够索引与区域关联的其他类型的元数据,例如现有用户和 bucket 名称。
Elasticsearch 是一个索引框架,它提供了对数据进行索引和对数据执行查询的简单机制。通过 RESTful api 对数据进行索引,允许通过 HTTP PUT 和 POST json 结构来描述数据。通过简单的 GET 操作来查询索引。
一个元数据索引 rgw 区域由一个 ceph 集群组成(可以 piggy-back 在另一个现有区域上,或者可以驻留在自己的 ceph 集群中),该集群需要保存同步和 rgw 元数据信息。它还包括一个 elasticsearch 服务器。该区域需要配置 tier_type 设置为 'elasticsearch',并且区域私有配置应指向指定的 elasticsearch 服务器。当区域组中发生更改时(或通过初始完全同步过程),同步模块会使用与对象关联的元数据更新 elasticsearch,或者在需要时完全删除对象的元数据。一旦数据被索引,就可以访问 elasticsearch 并通过不同的索引键查询元数据。
一个悬而未决的问题是,我们是否希望 rgw 处理查询 api,或者只是让 elasticsearch 处理它。另一种选择是通过 rgw 代理元数据请求并将这些请求发送到 elasticsearch。在任何需要 rgw 参与查询过程的解决方案中,我们需要创建一个 RESTful api(该 api 可以基于 elasticsearch api)。将此留在 rgw 之外是微不足道的(从 rgw 开发的角度来看)。
Elasticsearch 并不提供现成的安全模块(至少是开源和免费的),例如用户身份验证和/或授权。需要安全机制,以便用户只能在其自己的数据上运行元数据查询,而不能在其他用户的数据上运行元数据查询。Elasticsearch 当前的安全机制需要一个专有的非开源 elasticsearch 扩展,或者其他基本的开源模块。Elasticsearch 默认的“安全”模型不存在,而是依赖于通过代理限制对特定 url 前缀的访问。我们希望以哪种方式进行是一个悬而未决的问题。我们可以将其留给用户(前提是我们记录了设置),或者通过 rgw 代理请求并重用其自身的身份验证来解决它(一方面将解决授权问题,但另一方面会引入 api 问题,它可能与当前常用的 elasticsearch api 不兼容)。我们当前存储哪些用户具有对每个对象的读取权限。这将允许过滤搜索结果,以便只有授权用户才能看到相关的对象。
状态 ¶
上述分支(通过 PR 引用),实现了一个简单的同步模块,该模块将对象的元数据推送到配置的 elasticsearch 模块。我想要添加的主要内容是
- 限制区域同步到预指定的区域,而不是区域组中的所有区域
这不一定是此功能的独有功能,但在这里可以提供很大的帮助。有一些边缘情况可能导致在此同步来自多个区域时出现一些麻烦(并且不是常规 rgw 数据同步的问题,但由于某些限制可能会导致一些奇怪的情况)。
- elasticsearch 预配置 / 索引设置
我们当前不控制 elasticsearch 创建的任何索引。我们只是发布对象,让 elasticsearch 做它应该做的事情。这可能不是最优的,甚至可能存在问题。处理此问题的一种方法是在 elasticsearch 区域上启动同步过程时预配置索引。但是,这需要更大的 elasticsearch 专业知识,因为存在一些棘手的问题(例如,如何处理用户自定义的元数据?)。
这里有一个示例查询,它检索所有具有自定义“color”元数据字段设置为“silver”的对象
$ curl -XGET https://:9200/rgw/_search?q=meta.custom.color:silver { "took": 5, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 1, "max_score": 0.30685282, "hits": [ { "_index": "rgw", "_type": "object", "_id": "cde6b332-5bb8-4dc0-8219-b68932565ea1.4127.1:foo3:", "_score": 0.30685282, "_source": { "bucket": "buck2", "name": "foo3", "instance": "", "owner": { "id": "yehsad", "display_name": "yehuda" }, "permissions": [ "yehsad" ], "meta": { "size": 35, "mtime": "2016-08-23T18:28:40.098Z", "etag": "6216701a3418bdf56506670b91db3845", "x-amz-date": "Tue, 23 Aug 2016 18:28:39 GMT", "custom": { "color": "silver" } } } } ] } }
未解决的问题 ¶
- 特殊元数据搜索 api
我们需要将特殊的元数据搜索 api 集成到 rgw 中吗?这将需要定义新的 api。另一种选择是只代理对 elasticsearch 的请求。第三种选择是无所作为。
- 授权
授权是一个问题。现在,可以连接到 elasticsearch 服务器的用户默认情况下能够获取系统中所有对象的元数据。可以通过在 elasticsearch 上配置代理来限制用户操作。我们提供的读取权限字段应该有助于解决这个问题。
- 我们是否应该只记录用户需要如何配置系统? - 我们是否需要调查外部 elasticsearch 安全模块?
我看到的不太行。
- 通过 rgw 代理请求以强制通过 rgw 进行授权?
- 用于元数据分类的深度对象检查
目前,我们只查看分配给对象的当前元数据。我们可以在未来探索允许以某种可扩展的方式查看对象的实际数据,然后将其他元数据附加到这些对象。例如,对于图像文件,它可以存储分辨率或存在的 EXIF 数据。当前可以通过运行在数据本身上的外部脚本来完成,并更新对象的元数据,但将其挂接到同步模块本身可能会很有趣。