Kiali图的生成流程

简介: Kiali图(Graph)的生成过程。Kiali是一款服务网格拓扑可视化工具,本文基于Kiali源码对图的生成流程进行了探索。

Kiali是一款服务网格拓扑可视化工具,能够利用服务网格收集的可观测性指标将网格中的流量链路绘制成直观易懂的拓扑图。Kiali提供了基于 Web 的交互式图形用户界面,能够以多个层级(应用程序,版本,工作负载)展示集群中微服务之间的交互和连接情况。

image.png

Kiali的拓扑图(Graph,以下简称图)底层是通过 Cytoscape.js 绘制的。

cytoscape.js是一个做网页可视化的常用工具 。cytoscape.js包含图论模型和可选的渲染器,用于显示交互式图形。该库旨在使程序员和科学家尽可能轻松地在他们的应用程序中使用图形理论,无论是用于Node.js应用程序中的服务器端分析还是用于丰富的用户界面。

在前端发起请求后,Kiali是如何获取数据并转化成最终的拓扑图的,本文基于Kiali源码对图的生成流程进行了探索。

用户访问后,前端首先向/api/namespaces/graph发起请求,路径/api/namespaces/graph对应router位于routing/routes.go中的第1061行

收到请求后,由handlers/graph.go中的handler GraphNamespaces 来处理。主要干了两件事:

  1. 从请求参数中构造option
  2. 通过认证信息获取business.Layer。Layer按照资源类型,封装了访问资源的客户端,包括k8s, prometheus, jaeger。

Options:

typeOptionsstruct {
ConfigVendorstringTelemetryVendorstringConfigOptionsTelemetryOptions}

ConfigOptions:

typeConfigOptionsstruct {
BoxBystringCommonOptions}

TelemetryOptions:

typeTelemetryOptionsstruct {
AccessibleNamespacesmap[string]time.TimeAppendersRequestedAppenders// requested appenders, nil if param not suppliedIncludeIdleEdgesbool// include edges with request rates of 0InjectServiceNodesbool// inject destination service nodes between source and destination nodes.NamespacesNamespaceInfoMapRatesRequestedRatesCommonOptionsNodeOptions}

CommonOptions:

typeCommonOptionsstruct {
Durationtime.DurationGraphTypestringParamsurl.Values// make available the raw query params for vendor-specific handlingQueryTimeint64// unix time in seconds}

之后转给api包中的GraphNamespaces

在网格环境下,TlemetryVendor的值为"Istio",故会调用graphNamespacesIstio

继续调用istio包下的BuildNamespacesTrafficMap去生成最终的TrafficMap(就是一个string-*Node的map)。

Node定义:

typeNodestruct {
IDstring// unique identifier for the nodeNodeTypestring// Node typeClusterstring// ClusterNamespacestring// NamespaceWorkloadstring// Workload (deployment) nameAppstring// Workload app label valueVersionstring// Workload version label valueServicestring// Service nameEdges     []*Edge// child nodesMetadataMetadata// app-specific data}
typeEdgestruct {
Source*NodeDest*NodeMetadataMetadata// app-specific data}

BuildNamespacesTrafficMap的逻辑分为两步:

  1. 对于每个命名空间生成traffic-map
  2. 生成全局traffic-map并转换

每个命名空间的TrafficMap由buildNamespaceTrafficMap构建。对于常见的HTTP/GRPC请求,对于不同的流量指标(分成了三类)构造query字符串并使用promQuery函数查询所需指标。

  1. Incoming: query source telemetry to capture unserviced namespace services' incoming traffic
  2. Incoming: query destination telemetry to capture namespace services' incoming traffic
  3. Outgoing: query source telemetry to capture namespace workloads' outgoing traffic

promql查询得到的结果是Vector,即Sample指针的Slice。Vector中的Sample拥有相同的timestamp。

Sample定义:

typeSamplestruct {
MetricMetric`json:"metric"`ValueSampleValue`json:"value"`TimestampTime`json:"timestamp"`}

拿到Vector后,由populateTrafficMap函数提取指标中的各个参数

TS是timestamp的缩写

参数被穿给addTraffic函数,由addTraffic去调用addNode向map中添加node。addEdgeTraffic向source node添加edge。

得到了namespaceTrafficMap后,每个开启的appender对其中的node进行增加或删除。

然后MergeTrafficMaps合并到全局的trafficmap当中。

最后使用finalizers对全局的trafficmap进行操作。BuildNamespacesTrafficMap工作完成。

  • appender: 根据请求参数决定开启哪些appender,然后按顺序添加到appenders切片中。具体的appender定义在graph/telemetry/isto/appender/下。
  • finalizers: 和appender同样order is important,不能随意修改顺序

trafficmap由generateGraph转换成  CystoscapeJS 格式的 vendorConfig。

typeConfigstruct {
Timestampint64`json:"timestamp"`Durationint64`json:"duration"`GraphTypestring`json:"graphType"`ElementsElements`json:"elements"`}
typeElementsstruct {
Nodes []*NodeWrapper`json:"nodes"`Edges []*EdgeWrapper`json:"edges"`}
typeNodeWrapperstruct {
Data*NodeData`json:"data"`}
typeEdgeWrapperstruct {
Data*EdgeData`json:"data"`}
typeNodeDatastruct {
// Cytoscape FieldsIDstring`json:"id"`// unique internal node ID (n0, n1...)Parentstring`json:"parent,omitempty"`// Compound Node parent ID// App Fields (not required by Cytoscape)NodeTypestring`json:"nodeType"`Clusterstring`json:"cluster"`Namespacestring`json:"namespace"`Workloadstring`json:"workload,omitempty"`Appstring`json:"app,omitempty"`Versionstring`json:"version,omitempty"`Servicestring`json:"service,omitempty"`// requested service for NodeTypeServiceAggregatestring`json:"aggregate,omitempty"`// set like "<aggregate>=<aggregateVal>"DestServices          []graph.ServiceName`json:"destServices,omitempty"`// requested services for [dest] nodeLabelsmap[string]string`json:"labels,omitempty"`// k8s labels associated with the nodeTraffic               []ProtocolTraffic`json:"traffic,omitempty"`// traffic rates for all detected protocolsHealthDatainterface{}         `json:"healthData"`// data to calculate health status from configurationsHealthDataAppinterface{}         `json:"-"`// for local use to generate appBox healthHasCBbool`json:"hasCB,omitempty"`// true (has circuit breaker) | falseHasFaultInjectionbool`json:"hasFaultInjection,omitempty"`// true (vs has fault injection) | falseHasHealthConfigHealthConfig`json:"hasHealthConfig,omitempty"`// set to the health config overrideHasMirroringbool`json:"hasMirroring,omitempty"`// true (has mirroring) | falseHasMissingSCbool`json:"hasMissingSC,omitempty"`// true (has missing sidecar) | falseHasRequestRoutingbool`json:"hasRequestRouting,omitempty"`// true (vs has request routing) | falseHasRequestTimeoutbool`json:"hasRequestTimeout,omitempty"`// true (vs has request timeout) | falseHasTCPTrafficShiftingbool`json:"hasTCPTrafficShifting,omitempty"`// true (vs has tcp traffic shifting) | falseHasTrafficShiftingbool`json:"hasTrafficShifting,omitempty"`// true (vs has traffic shifting) | falseHasVS*VSInfo`json:"hasVS,omitempty"`// it can be empty if there is a VS without hostnamesHasWorkloadEntry      []graph.WEInfo`json:"hasWorkloadEntry,omitempty"`// static workload entry information | empty if there are no workload entriesIsBoxstring`json:"isBox,omitempty"`// set for NodeTypeBox, current values: [ 'app', 'cluster', 'namespace' ]IsDeadbool`json:"isDead,omitempty"`// true (has no pods) | falseIsGateway*GWInfo`json:"isGateway,omitempty"`// Istio ingress/egress gateway informationIsIdlebool`json:"isIdle,omitempty"`// true | falseIsInaccessiblebool`json:"isInaccessible,omitempty"`// true if the node exists in an inaccessible namespaceIsOutsidebool`json:"isOutside,omitempty"`// true | falseIsRootbool`json:"isRoot,omitempty"`// true | falseIsServiceEntry*graph.SEInfo`json:"isServiceEntry,omitempty"`// set static service entry information}
typeEdgeDatastruct {
// Cytoscape FieldsIDstring`json:"id"`// unique internal edge ID (e0, e1...)Sourcestring`json:"source"`// parent node IDTargetstring`json:"target"`// child node ID// App Fields (not required by Cytoscape)DestPrincipalstring`json:"destPrincipal,omitempty"`// principal used for the edge destinationIsMTLSstring`json:"isMTLS,omitempty"`// set to the percentage of traffic using a mutual TLS connectionResponseTimestring`json:"responseTime,omitempty"`// in millisSourcePrincipalstring`json:"sourcePrincipal,omitempty"`// principal used for the edge sourceThroughputstring`json:"throughput,omitempty"`// in bytes/sec (request or response, depends on client request)TrafficProtocolTraffic`json:"traffic,omitempty"`// traffic rates for the edge protocol}

实际转换主要是由cytoscape包下的buildConfig完成。

整个过程中,数据格式转换过程:

Prometheus的samples -> Kiali的traffimap -> CystoscapeJS的config json

相关文章
|
存储 人工智能 算法
详细设计工具之盒图(N-S图)
详细设计工具之盒图(N-S图)
667 0
详细设计工具之盒图(N-S图)
|
1月前
|
开发者
如何画好一张架构图/业务图/流程图,掌握4个关键点
本文分享了如何制作出有帮助的图表,强调了即使是开发者也需要良好的绘图技巧。文章列举了常见的图表类型,如代码实现图、技术架构图、业务流程图、技术链路图、交互时序图和业务架构图,并指出好的图表应具备结构清晰、外表美观和内容完整的特点。为了达到这些标准,作者推荐了设计的四大原则:亲密性、对齐、对比和重复,以及色轮的运用来提升美感。此外,还介绍了黄金分割构图法以增加视觉吸引力。最后,强调了以终为始的设计思路,确保图表能独立传达完整的信息,并鼓励读者实践这些技巧,提升工作和生活中的沟通效率。
如何画好一张架构图/业务图/流程图,掌握4个关键点
|
1月前
|
开发者
如何画好一张架构图/业务图/流程图,掌握这4个关键点
作为一个开发,日常工作中免不了要画一些图,无论是技术架构图还是业务流程图。基于个人的一些经验,作者分享了他的作图方法,给大家一点思路提供参考,希望在未来的工作、生活中都能有所帮助。
1547 2
|
11月前
|
数据库
设计分E-R图的步骤
设计分E-R图的步骤
145 0
|
存储 C++
C++实现图 - 01 图的概述及实现
前面我们讲的数据结构都是针对于一对一或一对多的情形,如果涉及到多对多的复杂情况就要用到我们接下来讲解的图了,这一讲我们重点讲解邻接表、邻接矩阵、十字链表以及邻接多重表的代码实现。如果已经对图的概念比较熟悉的小伙伴,可以拉到下面看相关的代码实现。
241 0
C++实现图 - 01 图的概述及实现
支付宝创建流程的六张图
支付宝创建流程的六张图
125 0
支付宝创建流程的六张图
|
算法
图 - 基础篇
图 - 基础篇
68 0
利用Proceesson在线绘制流程图实例演练!流程图的要点和注意事项说明
利用Proceesson在线绘制流程图实例演练!流程图的要点和注意事项说明
216 0
利用Proceesson在线绘制流程图实例演练!流程图的要点和注意事项说明
|
存储 算法 数据可视化
聊聊Graphin的图分析
今年有幸跟参与到Antv Graphin的共建组织中,并与山果同学一起做了Graphin FY21财年的产品规划。这篇文章主要根据Graphin规划内容重新思考图分析。 # 定位 既然聊到了图可视化分析,首先要讲清楚什么是图,什么是图分析。 ## 图 ![image.png](https://ata2-img.cn-hangzhou.oss-pub.aliyun-inc.c
1777 0
|
架构师 Java
分析复杂问题时,我们该画一个怎样的图?
我们在面对一些复杂问题时,该如何通过一个系统性的思考路径去(尝试)解决问题?系统循环图可能会是一个简单可行的工具哦!
628 0
分析复杂问题时,我们该画一个怎样的图?