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

相关文章
|
存储 自然语言处理 固态存储
ublk:来自Linux社区的新热点,基于io_uring的全新高性能用户态块设备
如果您想快速了解ublk的意义、作用及性能,请直接看第二节Q&A部分。一、简介用户态块设备,就是提供/dev/ublkbX这样的标准块设备给业务,业务读写这个块的实际IO处理由您编写的用户态的代码决定。这就好比您使用FUSE,所有对挂载于FUSE的目录的读写都是您编写的IO handler来处理一样。使用用户态块设备,您可以方便地向上层业务以块设备/dev/ublkbX的形式提供您的自定义
|
2月前
|
人工智能 负载均衡 安全
云上AI推理平台全掌握 (3):服务接入与全球调度
阿里云人工智能平台 PAI 平台推出的全球化的服务接入矩阵,为 LLM 服务量身打造了专业且灵活的服务接入方案,正重新定义 AI 服务的高可用接入标准——从单地域 VPC 安全隔离到跨洲际毫秒级调度,让客户的推理服务在任何网络环境下都能实现「接入即最优」。
|
7月前
|
Linux UED C++
MarkEdit:相信做技术的同学都会喜欢这个编辑器的,MarkEdit编辑器,让Markdown编辑变得简单而强大,超赞~~~
嗨,大家好,我是小华同学。MarkEdit是一款跨平台的Markdown编辑器,支持Windows、macOS和Linux,提供实时预览、快捷键、自定义主题和插件系统等核心功能。它适用于日常笔记、技术文档、博客写作、学术论文和电子书制作等多种场景。
358 31
|
10月前
|
域名解析 网络协议 安全
反向DNS解析是从IP地址到域名的映射,主要作用于验证和识别,提高通信来源的可信度和可追溯性
在网络世界中,反向DNS解析是从IP地址到域名的映射,主要作用于验证和识别,提高通信来源的可信度和可追溯性。它在邮件服务器验证、网络安全等领域至关重要,帮助识别恶意行为,增强网络安全性。尽管存在配置错误等挑战,但正确管理下,反向DNS解析能显著提升网络环境的安全性和可靠性。
619 3
|
JavaScript 前端开发
基于Jeecgboot前后端分离的ERP系统开发代码生成(四)
基于Jeecgboot前后端分离的ERP系统开发代码生成(四)
663 1
|
JSON 前端开发 数据格式
前端开发中的跨域问题及解决方案
【2月更文挑战第3天】 在前端开发中,跨域是一个常见的技术难题。本文将介绍跨域问题的产生原因,以及在前端开发中常见的跨域解决方案,包括JSONP、CORS、代理和设置响应头等方法,帮助开发者更好地理解和解决跨域相关的技术挑战。
401 2
|
弹性计算 IDE 开发工具
ECS热门应用 | 轻松打造一套 Web IDE
使用ECS云服务器搭建网页IDE,增强编码便捷性,提升开发者体验。
ECS热门应用 | 轻松打造一套 Web IDE
|
监控 安全 大数据
阿里服务的ASM、MSE和ARMS都有其各自的应用场景
阿里服务的ASM、MSE和ARMS都有其各自的应用场景
686 39
|
SQL 分布式计算 大数据
大数据问题排查系列 - 因HIVE 中元数据与HDFS中实际的数据不一致引起的问题的修复
大数据问题排查系列 - 因HIVE 中元数据与HDFS中实际的数据不一致引起的问题的修复
|
弹性计算 运维 供应链
工业供应链行业之云原生典型案例:服务网格ASM+容器服务ACK 助力震坤行提升应急供应链管理
随着业务不断快速发展,公司亟需提升数字化竞争力,延伸价值链条。在云上搭建新业务流程研发系统,通过容器化技术进行云原生优化改造,解决业务应用部署中碰到的不稳定、上线人工干预过多、无法稳定升级等问题。 服务网格作为一种用来管理应用服务通信的基础核心技术, 为应用服务间的调用带来了安全、可靠、快速、应用无感知的流量路由、安全、可观测能力。阿里云服务网格ASM产品提供了高可用、免运维、内建安全最佳实践;开发人员可以更专注于业务应用而非基础设施运维。可在服务网格产品内一键创建服务网格实例,无需复杂的配置。
851 0
工业供应链行业之云原生典型案例:服务网格ASM+容器服务ACK 助力震坤行提升应急供应链管理