Fleet 3.12.0 版本解析:主机查询归属可视化、按需 Refetch 主机详情与 Redis 实时查询结果复制
【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet
导读
Fleet 3.12.0 是开源设备管理平台 Fleet 在 2021 年 5 月发布的一个里程碑版本,围绕 osquery 主机管理的日常痛点带来了三项核心增强:在主机详情页直接查看该主机上调度了哪些 pack 内查询、查询的执行频率与最近运行时间;通过 "Refetch" 按钮按需向指定主机请求最新详情数据;以及来自社区的多项实用贡献(Google Cloud Pub/Sub 日志字段复制、Redis 实时查询结果复制、服务端 HTTP keep-alive 开关)。读完本文,你将理解这些功能在 Fleet 当前仓库中的对应实现路径、相关配置项及其适用场景,可直接对照源码验证并落地到自己的部署中。
版本概览:3.12 带来了什么
根据仓库中的发布文章 articles/fleet-3.12.0.md,Fleet 3.12.0 于 2021-05-20 发布(对应文档 meta 中的publishedOn字段),其亮点集中在:
- 主机查询归属可视化:在 UI 中查看每个主机上实际调度运行了哪些 pack 查询,以及各查询的调度频率和最近一次运行时间,帮助管理员确认 osquery 查询是否真正覆盖目标设备;
- "Refetch" 主机详情:在 Host details 页面点击按钮,向指定主机按需请求一份最新数据,确保看到的不是过期的缓存;
- 三项社区贡献:Google Cloud Pub/Sub 属性复制、Redis 实时查询结果复制、服务端 HTTP keep-alive 开关。
下面逐项展开,并结合当前仓库源码给出实现层面的印证。
查看主机上调度了哪些查询(Which queries apply to a host)
为什么需要"查询归属"视图
在 osquery 管理实践中,查询通常组织在pack中,pack 再按 label、platform 等条件定向到一批主机。查询收集的数据是告警、性能仪表盘以及 Incident Response 场景历史数据的来源,因此管理员非常需要确认某个查询是否真的成功配置并运行在目标设备上。
Fleet 3.12.0 在主机详情页展示了该主机被调度运行的所有查询,包括:
- 查询名称(来自哪个 pack);
- 该查询的调度频率(interval);
- 该查询在设备上的最近一次运行时间。
底层实现:scheduled_query_stats
这一 UI 能力背后是 Fleet 对查询运行统计的采集与聚合。在当前仓库中,主机详情的查询统计来源于scheduled_query_stats表:
- 表结构与聚合逻辑位于 server/datastore/mysql/aggregated_stats.go,例如按
scheduled_query_id汇总执行次数(SELECT coalesce(sum(executions), 0) FROM scheduled_query_stats WHERE scheduled_query_id=?); - 主机详情页加载调度查询统计的入口在 server/datastore/mysql/hosts.go(
loadHostScheduledQueryStatsDB),它从scheduled_query_stats表中按host_id分组读取每个scheduled_query_id的统计; - 该统计采集默认开启,对应配置项
app.enable_scheduled_query_stats,默认值为true,定义于 server/config/config.go。
从源码结构看,Fleet 通过 osquery 的scheduled_query_stats上报机制逐主机积累执行计数、系统时间/用户时间与执行次数,再在主机详情接口中按查询聚合展示,这正是"哪个查询跑在哪个设备上、多久跑一次、上次何时运行"这一视图的数据来源。对于监控 osquery 部署健康度的管理员而言,这个视图是排查"查询未生效"类问题的第一入口。
"Refetch" 主机详情:按需获取权威数据
功能动机
主机详情(host vitals)页面承载了设备的关键信息。如果数据长时间未更新,管理员基于过期数据做决策是有风险的。3.12.0 新增的 "Refetch" 能力允许在 Host details 页面点击按钮,主动请求指定主机重新上报最新数据。
API 与调用链
该功能对应的 REST 端点为POST /api/v1/fleet/hosts/:id/refetch,登记于 server/api_endpoints/api_endpoints.yml。
端点到存储层的完整调用链如下:
refetchHostEndpoint解析请求并调用svc.RefetchHost,见 server/service/hosts.go;Service.RefetchHost先做鉴权:非设备 token/设备 URL 认证的请求需要ActionList与ActionRead权限,observer 角色即可执行 refetch(源码注释明确说明使用ActionRead而非ActionWrite是为了允许观察者刷新主机),见 server/service/hosts.go;- 随后调用
svc.ds.UpdateHostRefetchRequested(ctx, id, true)落库; - 存储层实现为一条 UPDATE 语句:
UPDATE hosts SET refetch_requested = ? WHERE id = ?,见 server/datastore/mysql/hosts.go。
refetch_requested标记置位后,主机在下一次 osquery checkin 时即可感知"服务器请求了刷新",从而重新上报详情数据。值得一提的细节是:新注册的主机在创建时总是以refetch_requested = true写入(见 server/datastore/mysql/hosts.go),保证新设备上线后会尽快完成首次完整详情采集。
iOS/iPadOS 的差异化处理
从源码看,Fleet 对 iOS/iPadOS 主机的 refetch 有专门分支(server/service/hosts.go 及后续逻辑):这类设备没有 Fleet Desktop,无法走设备 token 认证路径,因此服务端会读取已发送的 MDM 命令(GetHostMDMCommands),据此决定是否补发 App 信息、DeviceInformation、证书等 MDM 指令来完成按需刷新。相关测试覆盖见 server/service/hosts_test.go(TestRefetchHostIOSTracksBeforeEnqueue)。
社区贡献:三项实用增强
将日志字段复制进 Google Cloud Pub/Sub attributes
感谢社区成员 Michael Samuel 的贡献(对应上游 PR #712):Fleet 写入 Google Cloud Pub/Sub 时,可以将日志字段复制到 Pub/Sub 消息的 attributes 中,从而让用户直接利用这些值编写 Pub/Sub 的订阅过滤器(subscription filters)。这对于基于订阅过滤做分流、告警或路由的部署非常实用。
redis_duplicate_results:将实时查询结果复制到额外 Redis 频道
社区成员 Josh Brower 的贡献(上游 PR #762)为 Redis 后端增加了实时查询结果的"复制"能力。当配置redis_duplicate_results = true时,所有实时查询结果会被额外发布到一个独立的 Redis Pub/Sub 频道,供独立的消费者订阅。
配置与实现层面,当前仓库中可以看到完整的落点:
- 配置项定义:
RedisConfig.DuplicateResults,YAML 键为duplicate_results,见 server/config/config.go; - 命令行/环境变量开关:
redis.duplicate_results,默认值为false,帮助信息为 "Duplicate Live Query results to another Redis channel"(server/config/config.go); - 核心实现:
redisQueryResults.WriteResult先把结果序列化为 JSON 发布到频道results_<campaign_id>,当检测到该频道有订阅者且duplicateResults为真时,再以best-effort方式向固定频道LQDuplicate额外PUBLISH一份同样的 JSON,见 server/pubsub/redis_query_results.go。
从实现可以推断,这一机制的价值在于解耦"查询结果投递"与"额外消费":主频道仍服务于 Fleet 自身上层的实时查询结果汇流,而LQDuplicate可作为可插拔的数据出口,供日志采集、流处理或监控系统独立订阅,且复制失败不会影响主路径(源码注释明确 "Ignore errors, duplicate result publishing is on a 'best-effort' basis")。
server.keepalive:控制服务端 HTTP keep-alive
社区成员 Joseph Macaulay 的贡献(上游 PR #741)增加了对服务端 HTTP keep-alive 属性的控制。在部分大规模部署中,关闭 keep-alive 有助于减少堆积的 TCP 连接数。
当前仓库中对应实现:
- 配置项定义:
ServerConfig.Keepalive,YAML 键为keepalive,见 server/config/config.go; - 开关与默认值:
server.keepalive,默认值为true,帮助信息为 "Controls whether HTTP keep-alives are enabled."(server/config/config.go)。
需要说明的是,该配置项控制的是 Fleet 服务器对外 HTTP 服务的连接复用行为,与应用层 osquery TLS 通信逻辑相互独立;默认开启以保持通常情况下的连接复用效率,仅在出现大量空闲 TCP 连接时建议按需关闭并观察效果。
升级到 3.12.0
发布文章提供了完整的变更摘要与发布二进制信息。在仓库内,各版本的变更记录可对照根目录的 CHANGELOG.md 查看;部署与更新方式(如 Docker Compose、Kubernetes、Linux 包管理等)可参考 docs 目录下对应部署方案文档,以及仓库根目录的 README.md 中关于构建与运行 Fleet 的说明。
升级前建议关注与当前主版本之间的破坏性变更,并先在预发环境验证 osquery 客户端兼容性;3.12.0 中新增的redis_duplicate_results(默认关闭)与server.keepalive(默认开启)均为可选配置,不修改任何既有默认行为,升级路径相对平滑。
小结
Fleet 3.12.0 的三项核心能力在今天看来依然构成 osquery 设备管理的基础体验:查询归属视图让"哪些查询跑在哪些设备上"变得可审计;Refetch让管理员能按需拿到权威的主机状态;而三项社区贡献则分别强化了日志出口的过滤能力(Pub/Sub attributes)、数据分发的可扩展性(RedisLQDuplicate频道)与连接管理(keep-alive 开关)。如果你想深入验证上述实现,可以直接从 server/service/hosts.go、server/pubsub/redis_query_results.go 和 server/config/config.go 三个入口开始阅读源码。
【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考