- 从可观测性建设角度出发,总结大家在日常工作中遇到的痛点;
- 介绍 DeepFlow 的软件架构、系统组成;
- 讲解 DeepFlow 的关键特性 AutoTagging 技术;
- 讲解支撑 AutoTagging 10x 性能提升的 SmartEncoding 技术;
-
总结并分享后续的迭代和演进计划。
01观测数据存储的挑战
可观测性建设从去年开始在国内非常的火热,大家谈的越来越多。随着云原生、微服务的发展落地,可观测性建设逐渐成为了一个必不可少的工程手段。
可观测性建设耗时长我们认为应用开发团队花了一半的时间用于可观测性的建设。这张图里面可以看到,开发者通常需要考虑在不同的 Dev Stack 和 Infra Stack 中如何埋点、如何插码、如何传递追踪上下文、如何生成指标/追踪/日志数据并进行关联,需要考虑的问题太多太杂。除此之外开发者还有很多时间在做 Debug,而这些 Debug 之所以耗费了这么多时间,通常大部分是因为可观测性建设的欠缺导致。
可观测性建设数据关联难可观测性指标数据一般分为Tracing、Metric和Logging三类。- Tracing关注的元数据是traceID/spanID/service/...;
- Metric关注的元数据是vpc/instance/node/kvm/...;
-
Logging关注的元数据是type/level/time/message/...。
02、DeepFlow 软件架构
DeepFlow软件架构DeepFlow的架构其实非常简单,它简单到只有一个Agent和一个Server,分别是数据采集组件和数据存储查询组件。Agent是使用Rust来实现的,高性能且内存安全,它通过eBPF技术实现了对任意开发技术栈、任意基础设施的全自动应用性能指标数据采集(AutoMetrics),以及自动化的分布式链路追踪(AutoTracing),这两项是DeepFlow Agent独有的能力,能极大降低开发者建设可观测性的工作量。Server包含了4个内部模块:Controller面向采集器Agent的管理,能纳管多资源池的10万量级的Agent;Labeler面向标签数据的自动注入,提供AutoTagging的能力;Querier面向数据查询,提供统一的SQL接口;Ingester面向数据存储,提供插件化的、可替换可组合的数据库接口。它支持水平扩展,而且完全不依赖外部的消息队列或负载均衡,就能够去实现对多个Region、多个资源池中Agent的负载均摊。Server也有两个非常核心的技术,AutoTagging和SmartEncoding。通过AutoTagging我们能为Agent采集到的所有观测数据自动注入统一的资源、实例和API标签,使得我们能够消除不同数据类型之间的隔阂,增强所有数据的关联、切分、下钻能力。SmartEncoding是我们非常创新的一个高性能的标签编码机制,通过这个机制,我们既能方便的进行数据关联,又能将标签注入的存储性能提升10倍,这在我们的实际生产环境中已经进行了广泛的验证。03、AutoTagging:构建标准化的标签体系
AutoTagging通过云API、K8s apiserver自动同步30多种资源标签、100多种自定义微服务标签,来构建标准化的标签体系。
DeepFlow资源同步DeepFlow的标签体系:-
自定义标签
- k8s.label/k8s.env/k8s.annotation/..
- os.app/os.proc/...
- cloud.tag
-
进程
- 进程名
-
云资源
- 资源池:区域/可用区
- 计算资源:云服务器/宿主机
- 网络资源:VPC/子网/路由器/IP地址
- 网络服务:安全组/负载均衡器/NAT网关/对等连接/云企业网
- 存储资源:云数据库RDS/Redis
-
容器资源
- 容器集群/容器节点/命名空间/Ingress/容器服务/工作负载/POD
- 为什么是 Agent watch 并上报 K8s资源?一个 Server 可以管理多个集群中的 Agent,Agent在所属集群中watch K8s,避免了集群外部用 server watch 时涉及到的权限和配置问题。
- 如何控制 Agent 对 K8s 资源的 watch?避免 K8s 的 API 压力过大,不能让所有的 Agent 都去 watch K8s,Server 在每个集群中选举一个 Agent;仅让被选中的 Agent watch K8s 资源。
- 内存优化:Agent 仅抓取同步必须的字段,同时会第一时间进行压缩。
- 带宽优化:仅当 K8s 资源有变化时,Agent 才会向 Server 发送具体的资源信息
同步K8s资源的数据流同步云资源-
同步云资源信息:通过调用云平台 API 进行资源抽象和转换,然后将相关标签信息保存至 MySQL 中,并定期更新 ClickHosue 中的字典。
-
同步 Legacy Host 信息:一些环境中,可能没有真正意义的云平台,或者存在一些传统主机需要监控,这就需要用Legacy Host同步方案。由于没有具体的云API,我们完全通过Agent抓取所在服务器的名称等基本信息和网卡信息,上报给Server汇总并进行资源抽象。
-
同步托管 K8s 信息:当 K8s 平台部署在云资源上时,要做到真正的可观测性,需要将K8s的资源和云资源关联起来,才能真正做到无缝地关联、切分和下钻。我们一方面通过获取 K8s 资源所在的 VPC,基于 VPC 内 IP 的唯一性,通过 VPC + IP 将 K8s 的容器节点与云服务器关联起来;另一方面通过将云平台的 API 调用与 K8s 独立,两者使用不同的调用频率,从而解决大规模场景下,云平台 API 慢与 K8s 资源更新快的矛盾。
同步云资源的数据流理想很丰满,现实很骨感。我们努力想实现观测数据无缝跳转,但当上百个标签呈现在眼前时,你会发现后端资源消耗飙升,性能急剧下降,整个平台别说无缝跳转了,连使用都成了问题。于是 SmartEncoding 技术诞生了。04、SmartEncoding:实现 10x 性能提升
SmartEncoding 将标签注入分为3个阶段,通过采集时编码、存储时编码、和查询时编/解码降低标签写入的资源消耗,我们来详细看看每个阶段都如何实现:采集时编码
采集时编码Controller 根据云平台和 K8s 资源抽象好标签信息进行 Int 编码后,并不会将所有的标签下发给 Agent。仅会下发最少量的标签。这样 Agent 只需要为数据追加很少的Int标签即可。在混合云场景下,为了标识资源我们可以用 VPC ID 作为基,它能和 IP 地址联合决定客户端、服务端对应的实例和服务;可以通过 gpid 解决远端进程信息标记的问题。我们主要考虑 Agent 做的工作尽量少,这样可以最大限度的降低采集器的 CPU、内存消耗,以及传输数据的带宽消耗。我们在生产环境中发现有些 K8s 的标签会非常长,key 和 value 高达上百个字节。可以想象如果我们将上百个标签注入每个请求传输到后端,消耗的带宽会非常可观。存储时编码
存储时编码同样 Controller 会向 Ingester 下发 Int 标签,但仅下发持久化存储的标签。Ingester 在收到 Agent 发过来的数据后,会进行一轮标签的扩充,将 Agent 注入的少量标签扩展为更为丰富的标签集合。但这里注意的是,我们并不存储自定义标签。标签的存储是为了方便检索和聚合,我们只需要保证每个切分粒度上都有标签存在即可。举例来讲我们存储 Region、AZ、VM、Node、Namespace、Service、POD 等固定的云或者 K8s 资源标签即可,而其他的自定义的标签一般是依附在这些标签之上的,存在一定的对应的关系。另外,自定义标签动态性高,也不适合全部存储。根据我们的经验,一般每一个请求涉及到的的固定标签在40个左右,自定义标签在60个左右。通过只存储固定的资源标签,我们能将压力进一步降低。查询时编/解码
查询时编解码DeepFlow SQL支持通过字符串查询和聚合,并且也支持自定义标签的查询和聚合。这里我们依赖 ClickHouse 的字典能力。通过编码自定义标签的 Filter 和 Group 查询请求,利用 ClickHouse 的字典转换为系统标签;同时对于 Select 请求也可以利用 ClickHouse 的字典将系统标签转为字符串或者自定义标签返回。我们再来回顾一下这三级编解码,可以发现它能为我们节省大量的资源消耗,性能提升应该十分可观。一方面采集器的CPU、内存可以降低,传输带宽可以降低,最主要的还是后端存储开销的降低。我们在谈论可观测性时经常会谈到采样、避免高基数等。ClickHouse 采用稀疏索引,很好的避免了高基数问题。我们在此之上的多级编解码又能将存储开销显著降低,而且由于查询阶段扫描的数据量变小了,所以能获得更好的查询性能。这里有一些数据可以看一下,DeepFlow 默认使用 ClickHouse 存储数据,在 SmartEncoding 的加持下,标准 Tag 的 CPU 和磁盘消耗相比 LowCard 存储或直接存储有一个数量级的优化,而由于自定义 Tag 不会随数据写入,在通常的场景下整体写入资源消耗可降低50倍。



SELECTcol_1,col_2,col_3 FROMtbl_1 WHEREcol_4=y GROUPBYcol_1,col_2 HAVINGcol_5>100 ORDERBYcol_3 LIMIT100 ``` 我们可以查询某个 Tag 的所有候选项: ```sql SHOWtag${tag_name}valuesFROM${table_name}
SHOWtag${tag_name}values FROM${table_name} WHEREdisplay_nameLIKE'*abc*'
SELECTpod FROM`vtap_flow_port.1m` WHEREpod_cluster='cluster1' GROUPBYpod 更多详细用法[4]查询 Universal Tag
- ClickHouse 的观测数据表中保存tag ID
CREATETABLEflow_metrics.`vtap_flow_port.1m` ( `time`DateTime('Asia/Shanghai')COMMENT'v6.1.8'CODEC(DoubleDelta), `ip4`IPv4COMMENT'IPv4地址', `ip6`IPv6COMMENT'IPV6地址', `is_ipv4`UInt8COMMENT'是否IPV4地址.0:否,ip6字段有效,1:是,ip4字段有效', `l3_device_id`UInt32COMMENT'ip对应的资源ID', `l3_device_type`UInt8COMMENT'ip对应的资源类型', `l3_epc_id`Int32COMMENT'ip对应的EPCID', `pod_cluster_id`UInt16COMMENT'ip对应的容器集群ID', `pod_group_id`UInt32COMMENT'ip对应的容器工作负载ID', `pod_id`UInt32COMMENT'ip对应的容器PODID', `pod_node_id`UInt32COMMENT'ip对应的容器节点ID', `pod_ns_id`UInt16COMMENT'ip对应的容器命名空间ID' ) ENGINE=Distributed(...)
- ClickHouse 的字典表中保存tag ID和名称对应关系
CREATEDICTIONARYflow_tag.pod_map ( `id`UInt64, `name`String, `icon_id`Int64 ) PRIMARYKEYid SOURCE(...)
- 通过 dictGet 实现tag ID到名称的转换
SELECTdictGet(flow_tag.pod_map,'name',toUInt64(pod_id))ASpod FROM`vtap_flow_port.1m` WHEREpod='deepflow' GROUPBYpod LIMIT1 查询 K8s label
- ClickHouse 的字典表中保存tag ID和 K8s label对应关系
CREATEDICTIONARYflow_tag.k8s_label_map ( `pod_id`UInt64, `key`String, `value`String, ) PRIMARYKEYpod_id,key SOURCE(...) LIFETIME(MIN0MAX60) LAYOUT(COMPLEX_KEY_HASHED())
- 通过 dictGet 实现tag ID到 K8s label 的转换
SELECTdictGet(flow_tag.k8s_label_map,'value',(toUInt64(pod_id),'app'))AS`label.app` FROM`vtap_flow_port.1m` WHERE`label.app`='xxx' LIMIT1 查询集成数据,包括 Prometheus、Telegraf、OpenTelemetry 等数据。
- 存储集成数据时,会将数据中原有的 Tag 和 Metric 的 name 和 value 分别定义为 Array 类型,一一对应。
CREATETABLEext_metrics.prometheus_web ( `time`DateTime('Asia/Shanghai')CODEC(DoubleDelta), `_tid`UInt8COMMENT'用于区分trident不同的pipeline', `az_id`UInt16COMMENT'可用区ID', `host_id`UInt16COMMENT'宿主机ID', `tag_names`Array(String)COMMENT'额外的tag', `tag_values`Array(String)COMMENT'额外的tag对应的值', `metrics_float_names`Array(String)COMMENT'额外的metrics', `metrics_float_values`Array(Float64)COMMENT'额外的metrics值' )
- Tag 候选项只需要保留不重复的值,所以我们使用 ReplacingMergeTree Engine
CREATETABLEflow_tag.ext_metrics_custom_field_local ( `time`DateTime('Asia/Shanghai')CODEC(DoubleDelta), `table`LowCardinality(String), `vpc_id`Int32, `pod_ns_id`UInt16, `field_type`LowCardinality(String)COMMENT'value:tag,metrics', `field_name`LowCardinality(String), `field_value_type`LowCardinality(String)COMMENT'value:string,float' ) ENGINE=ReplacingMergeTree(time)
- 通过 indexOf 进行 name 和 value 的对应
SELECTtag_values[indexOf(tag_names,'host')]AS`tag.host` FROMdeepflow_agent_collect_sender WHERE(tag_values[indexOf(tag_names,'host')])='xxxx' LIMIT1
05、总结与后续迭代计划
通过以上分享,相信您会发现DeepFlow有丰富、统一的标准化标签体系,非常方便进行数据关联、切分、下钻。通过 SmartEncoding 的性能优化,Server + ClickHouse 的资源消耗通常为业务消耗的 1%,即监控100个 16c64g 的容器节点,大概需要1个 16c64g 的 Node 部署 Server + ClickHouse,且可以通过对象存储转储冷数据;而且常见的可观测性数据一般都需要注入百量级的标签,DeepFlow Agent 由于只注入了 VPC、GPID 少数几个字段,因此它用于标签注入的资源消耗几乎只有其他方案的百分之几。这样10x性能的使用体验,相信 Cloud-Native、NewOps 都会喜欢!后续我们会支持更丰富的自定义标签,包括通过 K8s API 获取的k8s.annotation 和 k8s.env、通过操作系统获取的 os.proc 信息、通过执行命令获取 os.app 信息;会从时间和带宽消耗两方面进一步优化AutoTagging的性能,通过不同类型资源的 API 可以设置不同的调用频率,避免每次都是重新获取全部资源来缩短缩短大规模下的资源同步时间;通过Agent 仅发送有变化的 K8s 资源信息,进一步降低带宽消耗。06、关于DeepFlow
DeepFlow[5]是一款开源的高度自动化的可观测性平台,是为云原生应用开发者建设可观测性能力而量身打造的全栈、全链路、高性能数据引擎。DeepFlow 使用 eBPF、WASM、OpenTelemetry 等新技术,创新的实现了 AutoTracing、AutoMetrics、AutoTagging、SmartEncoding 等核心机制,帮助开发者提升埋点插码的自动化水平,降低可观测性平台的运维复杂度。利用 DeepFlow 的可编程能力和开放接口,开发者可以快速将其融入到自己的可观测性技术栈中。 审核编辑 :李倩
-
核心技术
+关注
关注
4文章
625浏览量
20436 -
数据存储
+关注
关注
5文章
1014浏览量
52587 -
软件架构
+关注
关注
0文章
64浏览量
10593
原文标题:DeepFlow AutoTagging 10x性能提升实战
文章出处:【微信号:AI_Architect,微信公众号:智能计算芯世界】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
5G手机Redmi 10X性价比很高?Redmi 10X怎么样?来看看Redmi 10X拆解
示波器的10X档和1X档输入阻抗
10X genomics课程笔记
微软承认基于虚拟化的功能将会让Windows 10X的性能更出色
微软Windows 10X系统支持UWP应用和Win32应用程序运行
Windows 10X春季正式上线,面向轻量级设备
微软正式公开Windows 10X取代Windows 10,12月进入RTM阶段
Windows 10X今年即将到来?
微软即将新推出Windows 10X系统
盘点汇总Windows 10X的亮点功能
Windows 10X相较Windows 10有哪些亮点?
浅谈Windows 10X与Windows 10的主要区别
10x无源探头正确使用方法介绍

DeepFlow AutoTagging 10x性能提升实战
评论