diff --git a/docs/proposal/bpf_map_batch_delete_zh.md b/docs/proposal/bpf_map_batch_delete_zh.md new file mode 100644 index 000000000..a8b713f9e --- /dev/null +++ b/docs/proposal/bpf_map_batch_delete_zh.md @@ -0,0 +1,115 @@ +--- +title: Kmesh BPF Map 批量删除 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh BPF Map 批量删除 + +## 摘要 + +本文档描述了 Kmesh 中 BPF Map 批量删除的设计方案,用于提高大规模数据删除的效率。 + +## 背景 + +在服务网格场景中,需要定期清理或批量删除大量 BPF Map 数据。批量删除机制可以显著提高删除效率,减少系统开销。 + +## 目标 + +1. 实现批量删除功能 +2. 提高删除性能 +3. 保证数据一致性 +4. 支持错误恢复 + +## 设计细节 + +### 架构设计 + +批量删除系统包含以下组件: + +1. 删除管理器 +2. 事务控制器 +3. 错误处理器 +4. 性能监控器 + +### 数据结构 + +```c +struct BatchDeleteConfig { + __u32 batch_size; // 批量大小 + __u32 timeout; // 超时时间 + __u32 retry_count; // 重试次数 + __u32 flags; // 删除标志 +}; + +struct BatchDeleteStats { + __u64 total_deletes; // 总删除数 + __u64 success_count; // 成功数量 + __u64 failure_count; // 失败数量 + __u64 retry_count; // 重试次数 +}; + +struct BatchDelete { + __u32 map_id; // Map ID + void *keys; // 键数组 + __u32 count; // 删除数量 + __u32 flags; // 删除标志 +}; +``` + +### 删除接口 + +```go +type BatchDeleter interface { + BatchDelete(deletes []BatchDelete, config *BatchDeleteConfig) error + GetDeleteStats() (*BatchDeleteStats, error) + CancelDelete(batchID string) error + GetDeleteStatus(batchID string) (string, error) +} +``` + +## 使用示例 + +### 配置批量删除 + +```yaml +batch_delete_config: + batch_size: 1000 + timeout: 30s + retry_count: 3 + flags: + - ATOMIC + - ASYNC +``` + +### 执行删除 + +```bash +# 执行批量删除 +kmesh map batch-delete --config=config.yaml --input=keys.json + +# 查看删除状态 +kmesh map delete-status + +# 取消删除 +kmesh map delete-cancel +``` + +## 注意事项 + +1. 数据一致性 +2. 性能影响 +3. 错误处理 + +## 未来工作 + +1. 支持更多删除模式 +2. 优化性能 +3. 增强监控能力 \ No newline at end of file diff --git a/docs/proposal/bpf_map_batch_lookup_zh.md b/docs/proposal/bpf_map_batch_lookup_zh.md new file mode 100644 index 000000000..9fb7acd87 --- /dev/null +++ b/docs/proposal/bpf_map_batch_lookup_zh.md @@ -0,0 +1,116 @@ +--- +title: Kmesh BPF Map 批量查询 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh BPF Map 批量查询 + +## 摘要 + +本文档描述了 Kmesh 中 BPF Map 批量查询的设计方案,用于提高大规模数据查询的效率。 + +## 背景 + +在服务网格场景中,经常需要同时查询大量 BPF Map 数据。批量查询机制可以显著提高查询效率,减少系统开销。 + +## 目标 + +1. 实现批量查询功能 +2. 提高查询性能 +3. 优化内存使用 +4. 支持并发查询 + +## 设计细节 + +### 架构设计 + +批量查询系统包含以下组件: + +1. 查询管理器 +2. 缓存系统 +3. 并发控制器 +4. 性能监控器 + +### 数据结构 + +```c +struct BatchLookupConfig { + __u32 batch_size; // 批量大小 + __u32 timeout; // 超时时间 + __u32 max_concurrent; // 最大并发数 + __u32 flags; // 查询标志 +}; + +struct BatchLookupStats { + __u64 total_lookups; // 总查询数 + __u64 cache_hits; // 缓存命中数 + __u64 cache_misses; // 缓存未命中数 + __u64 error_count; // 错误数量 +}; + +struct BatchLookup { + __u32 map_id; // Map ID + void *keys; // 键数组 + void *values; // 值数组缓冲区 + __u32 count; // 查询数量 + __u32 flags; // 查询标志 +}; +``` + +### 查询接口 + +```go +type BatchLookupManager interface { + BatchLookup(lookups []BatchLookup, config *BatchLookupConfig) error + GetLookupStats() (*BatchLookupStats, error) + CancelLookup(batchID string) error + GetLookupStatus(batchID string) (string, error) +} +``` + +## 使用示例 + +### 配置批量查询 + +```yaml +batch_lookup_config: + batch_size: 1000 + timeout: 10s + max_concurrent: 4 + flags: + - USE_CACHE + - ASYNC +``` + +### 执行查询 + +```bash +# 执行批量查询 +kmesh map batch-lookup --config=config.yaml --input=keys.json + +# 查看查询状态 +kmesh map lookup-status + +# 取消查询 +kmesh map lookup-cancel +``` + +## 注意事项 + +1. 内存使用控制 +2. 缓存管理 +3. 性能监控 + +## 未来工作 + +1. 支持更多查询模式 +2. 优化缓存策略 +3. 增强监控能力 \ No newline at end of file diff --git a/docs/proposal/bpf_map_batch_update_zh.md b/docs/proposal/bpf_map_batch_update_zh.md new file mode 100644 index 000000000..fb0c0a183 --- /dev/null +++ b/docs/proposal/bpf_map_batch_update_zh.md @@ -0,0 +1,116 @@ +--- +title: Kmesh BPF Map 批量更新 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh BPF Map 批量更新 + +## 摘要 + +本文档描述了 Kmesh 中 BPF Map 批量更新的设计方案,用于提高大规模数据更新的效率。 + +## 背景 + +在大规模服务网格场景中,需要频繁更新大量 BPF Map 数据。批量更新机制可以显著提高更新效率,减少系统开销。 + +## 目标 + +1. 实现批量更新功能 +2. 提高更新性能 +3. 保证数据一致性 +4. 支持错误恢复 + +## 设计细节 + +### 架构设计 + +批量更新系统包含以下组件: + +1. 批处理管理器 +2. 事务控制器 +3. 错误处理器 +4. 性能监控器 + +### 数据结构 + +```c +struct BatchUpdateConfig { + __u32 batch_size; // 批量大小 + __u32 timeout; // 超时时间 + __u32 retry_count; // 重试次数 + __u32 flags; // 更新标志 +}; + +struct BatchUpdateStats { + __u64 total_updates; // 总更新数 + __u64 success_count; // 成功数量 + __u64 failure_count; // 失败数量 + __u64 retry_count; // 重试次数 +}; + +struct BatchUpdate { + __u32 map_id; // Map ID + void *keys; // 键数组 + void *values; // 值数组 + __u32 count; // 更新数量 + __u32 flags; // 更新标志 +}; +``` + +### 更新接口 + +```go +type BatchUpdater interface { + BatchUpdate(updates []BatchUpdate, config *BatchUpdateConfig) error + GetUpdateStats() (*BatchUpdateStats, error) + CancelUpdate(batchID string) error + GetUpdateStatus(batchID string) (string, error) +} +``` + +## 使用示例 + +### 配置批量更新 + +```yaml +batch_update_config: + batch_size: 1000 + timeout: 30s + retry_count: 3 + flags: + - ATOMIC + - ASYNC +``` + +### 执行更新 + +```bash +# 执行批量更新 +kmesh map batch-update --config=config.yaml --input=updates.json + +# 查看更新状态 +kmesh map batch-status + +# 取消更新 +kmesh map batch-cancel +``` + +## 注意事项 + +1. 内存使用控制 +2. 事务一致性 +3. 性能监控 + +## 未来工作 + +1. 支持更多更新模式 +2. 优化内存使用 +3. 增强监控能力 \ No newline at end of file diff --git a/docs/proposal/bpf_map_in_map_zh.md b/docs/proposal/bpf_map_in_map_zh.md new file mode 100644 index 000000000..e6cbf8231 --- /dev/null +++ b/docs/proposal/bpf_map_in_map_zh.md @@ -0,0 +1,115 @@ +--- +title: Kmesh BPF Map-in-Map +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh BPF Map-in-Map + +## 摘要 + +本文档描述了 Kmesh 中 BPF Map-in-Map 的设计方案,用于实现复杂的数据结构和层次化存储。 + +## 背景 + +Map-in-Map 是 eBPF 中的一种高级特性,允许在一个 Map 中嵌套另一个 Map。Kmesh 需要利用这一特性来支持更复杂的数据组织形式。 + +## 目标 + +1. 实现 Map-in-Map 功能 +2. 提供层次化数据存储 +3. 支持动态数据结构 +4. 优化访问性能 + +## 设计细节 + +### 架构设计 + +Map-in-Map 系统包含以下组件: + +1. 外层 Map 管理器 +2. 内层 Map 管理器 +3. 数据同步器 +4. 缓存系统 + +### 数据结构 + +```c +struct OuterMapConfig { + __u32 type; // Map 类型 + __u32 key_size; // 键大小 + __u32 inner_map_fd; // 内层 Map 文件描述符 + __u32 max_entries; // 最大条目数 +}; + +struct InnerMapConfig { + __u32 type; // Map 类型 + __u32 key_size; // 键大小 + __u32 value_size; // 值大小 + __u32 max_entries; // 最大条目数 +}; + +struct MapInMapInfo { + __u32 outer_id; // 外层 Map ID + __u32 inner_id; // 内层 Map ID + __u32 entries; // 当前条目数 + __u32 flags; // Map 标志 +}; +``` + +### 管理接口 + +```go +type MapInMapManager interface { + CreateOuterMap(config *OuterMapConfig) (uint32, error) + CreateInnerMap(config *InnerMapConfig) (uint32, error) + UpdateOuterElement(outerID uint32, key interface{}, innerID uint32) error + UpdateInnerElement(innerID uint32, key interface{}, value interface{}) error + LookupElement(outerID uint32, outerKey interface{}, innerKey interface{}) (interface{}, error) + GetMapInfo(outerID uint32) (*MapInMapInfo, error) +} +``` + +## 使用示例 + +### 创建 Map-in-Map + +```bash +# 创建内层 Map +kmesh map create-inner --type=hash --key-size=4 --value-size=8 --max-entries=1000 + +# 创建外层 Map +kmesh map create-outer --type=array --inner-map= --max-entries=100 +``` + +### 管理数据 + +```bash +# 更新外层 Map +kmesh map update-outer --key=1 --inner-map= + +# 更新内层 Map +kmesh map update-inner --key=100 --value=200 + +# 查询数据 +kmesh map lookup --outer-key=1 --inner-key=100 +``` + +## 注意事项 + +1. 内存管理 +2. 性能优化 +3. 并发控制 + +## 未来工作 + +1. 支持更多 Map 类型 +2. 优化数据结构 +3. 增强监控能力 \ No newline at end of file diff --git a/docs/proposal/bpf_map_management_zh.md b/docs/proposal/bpf_map_management_zh.md new file mode 100644 index 000000000..7ef97615f --- /dev/null +++ b/docs/proposal/bpf_map_management_zh.md @@ -0,0 +1,115 @@ +--- +title: Kmesh BPF Map 管理 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh BPF Map 管理 + +## 摘要 + +本文档描述了 Kmesh 中 BPF Map 的管理方案,包括 Map 的创建、更新、删除和查询等功能。 + +## 背景 + +BPF Map 是 eBPF 程序中重要的数据存储和共享机制。Kmesh 需要提供完善的 Map 管理能力,以支持复杂的数据处理需求。 + +## 目标 + +1. 实现 Map 生命周期管理 +2. 提供高效的数据访问 +3. 支持多种 Map 类型 +4. 确保数据一致性 + +## 设计细节 + +### 架构设计 + +BPF Map 管理系统包含以下组件: + +1. Map 管理器 +2. 数据同步器 +3. 缓存系统 +4. 监控组件 + +### 数据结构 + +```c +struct MapConfig { + __u32 type; // Map 类型 + __u32 key_size; // 键大小 + __u32 value_size; // 值大小 + __u32 max_entries; // 最大条目数 + __u32 flags; // Map 标志 +}; + +struct MapInfo { + __u32 id; // Map ID + __u32 type; // Map 类型 + __u32 key_size; // 键大小 + __u32 value_size; // 值大小 + __u32 max_entries; // 最大条目数 + __u32 flags; // Map 标志 + __u32 entries; // 当前条目数 +}; +``` + +### 管理接口 + +```go +type MapManager interface { + CreateMap(config *MapConfig) (uint32, error) + DeleteMap(id uint32) error + UpdateElement(id uint32, key interface{}, value interface{}) error + LookupElement(id uint32, key interface{}) (interface{}, error) + GetMapInfo(id uint32) (*MapInfo, error) + ListMaps() ([]uint32, error) +} +``` + +## 使用示例 + +### 创建和管理 Map + +```bash +# 创建新的 Map +kmesh map create --type=hash --key-size=4 --value-size=8 --max-entries=1000 + +# 更新 Map 元素 +kmesh map update --key=1234 --value=5678 + +# 查询 Map 元素 +kmesh map lookup --key=1234 +``` + +### 监控 Map 状态 + +```bash +# 查看所有 Map +kmesh map list + +# 查看 Map 详情 +kmesh map info + +# 查看 Map 使用统计 +kmesh map stats +``` + +## 注意事项 + +1. 内存使用控制 +2. 并发访问处理 +3. 性能优化 + +## 未来工作 + +1. 支持更多 Map 类型 +2. 优化内存管理 +3. 增强监控能力 \ No newline at end of file diff --git a/docs/proposal/bypass_zh.md b/docs/proposal/bypass_zh.md index c9f4a33fa..c6fb704db 100644 --- a/docs/proposal/bypass_zh.md +++ b/docs/proposal/bypass_zh.md @@ -1,86 +1,86 @@ -## 背景 - -目前,如果服务之间在开启服务网格的情况下通信失败,很难判断问题是因为服务网格接管流量造成的,还是服务本身存在错误。 因此,我们提供了将网格服务从通信流量路径中删除的功能,以查明问题是由服务网格还是应用程序本身的错误引起的。 - -## 功能设计 - -bypass是一种通用网格功能,用于从流量路径中删除 sidecar/kmesh 网格服务。 下面两种场景介绍了启用bypass功能后的流量路径。 - -### 场景一:sidecar - -下面两张图中,在集群中启用了sidecar来接管流量。 图一为启用bypass功能前的流量路径。从中我们可以看到,流量路径是服务A->sidecar->sidecar->服务B,当服务A和服务B通信失败时,从黑盒层面,用户无法判断是否是 sidecar 或服务本身存在问题。 图二中,开启了pod1的bypass功能,从而pod1中的sidecar会被从流量路径中移除。 如果此时服务A和服务B能够正常通信,则证明sidecar存在问题。 - -![alt text](pics/sidecar_pre_bypass.svg) - -![alt text](pics/sidecar_bypass.svg) - -### 场景二:kmesh - -在图一中,流量路径是服务A->kmesh->服务B。在图二中,开启了bypass功能后,会在kmesh的ebpf程序中判断bypass功能已经开启,从而kmesh不会接管服务A发出的数据,流量路径是服务A->服务B。如果此时服务A和服务B能够正常通信,则证明kmesh存在问题。 - -![alt text](pics/kmesh_pre_bypass.svg) - -![alt text](pics/kmesh_bypass.svg) - -## Bypass的数据结构 - -```c -struct bpf_map_def SEC("maps") bypass_fliter_map = { - .type = BPF_MAP_TYPE_HASH, - .key_size = sizeof(__u32), - .value_size = sizeof(__u8), - .max_entries = 256, -}; -``` - -key代表pod的IP地址,value代表当前pod是否开启bypass功能,用0/1表示。 当执行到这个ebpf程序时,它会检查对应的pod是否启用了bypass功能。 如果启用,则所有后续的 iptables 规则都将被短路,且出入方向的流量都将被短接。反之则不会短接后续的iptables规则。 - -## 如何开启bypass - -执行以下命令: - -```shell -kubectl label pod kmesh.net/bypass=enabled -``` - -这将会导致一个pod的出入流量都将被短接 - -## 如何观测label的变化 - -Kmesh Daemon 通过与 Kubernetes API Server 通信,使用字段选择器实现了对特定标签的观测。它观察 Kubernetes API Server 的变化,并过滤所需的资源对象,从而只观测特定标签的变化。 - -```go -informerFactory := informers.NewSharedInformerFactoryWithOptions(client, 0, - informers.WithTweakListOptions(func(options *metav1.ListOptions) { - options.FieldSelector = fmt.Sprintf("spec.nodeName=%s", nodeName) - options.LabelSelector = "kmesh.net/bypass=enabled" - })) - -podInformer := informerFactory.Core().V1().Pods() -``` - -## 流量治理流程 - -### 场景一:sidecar - -![alt text](pics/sidecar_traffic_path.svg) - -上图中黑色箭头表示的路径是bypass功能开启前的流量路径,蓝色箭头是bypass功能开启后的流量路径。 不同的是,启用bypass功能后,kmesh mda会在iptables规则的顶层添加两条。 规则是: - -```shell -iptables -t nat -I OUTPUT -m bpf --object-pinned /sys/fs/bpf/bypass -j RETURN -iptables -t nat -I PREROUTING -m bpf --object-pinned /sys/fs/bpf/bypass -j RETURN -``` - -这两条规则将导致流量路径在ebpf程序中被更新。 ebpf程序会判断当前pod是否开启了bypass功能。 如果启用该功能,数据将直接发送到对端服务,而不是服务网格中。 - -### 场景二:kmesh - -![alt text](pics/kmesh_traffic_path.svg) - -该场景下,上图中蓝色箭头所代表的路径即为旁路功能开启前后的流量路径。 不同之处是在kmesh原有的ebpf程序中增加了对bypass功能的判断。 当前kmesh是否接管流量的依据是ebpf程序是否获取到的classid是否与kmesh定义的classid一致。 如果一致,流量就会被接管。开启了bypass功能之后,还会再判断一次bypass功能是否启用。 - -## 注意 - -- 当前bypass功能仅短接单个Pod的服务网格流量,而不是整个流量路径上的服务网格。为了解决短接一方的服务网格之后,导致另一方服务网格无法解析收到的加密报文的问题。 在启用bypass功能之前,需要配置服务网格以明文格式发送消息 -- 目前bypass会短接单个Pod的出入方向的流量。 后续还将对出入方向的流量进行细分。 例如,只有出方向的流量会被短路。 +## 背景 + +目前,如果服务之间在开启服务网格的情况下通信失败,很难判断问题是因为服务网格接管流量造成的,还是服务本身存在错误。 因此,我们提供了将网格服务从通信流量路径中删除的功能,以查明问题是由服务网格还是应用程序本身的错误引起的。 + +## 功能设计 + +bypass是一种通用网格功能,用于从流量路径中删除 sidecar/kmesh 网格服务。 下面两种场景介绍了启用bypass功能后的流量路径。 + +### 场景一:sidecar + +下面两张图中,在集群中启用了sidecar来接管流量。 图一为启用bypass功能前的流量路径。从中我们可以看到,流量路径是服务A->sidecar->sidecar->服务B,当服务A和服务B通信失败时,从黑盒层面,用户无法判断是否是 sidecar 或服务本身存在问题。 图二中,开启了pod1的bypass功能,从而pod1中的sidecar会被从流量路径中移除。 如果此时服务A和服务B能够正常通信,则证明sidecar存在问题。 + +![alt text](pics/sidecar_pre_bypass.svg) + +![alt text](pics/sidecar_bypass.svg) + +### 场景二:kmesh + +在图一中,流量路径是服务A->kmesh->服务B。在图二中,开启了bypass功能后,会在kmesh的ebpf程序中判断bypass功能已经开启,从而kmesh不会接管服务A发出的数据,流量路径是服务A->服务B。如果此时服务A和服务B能够正常通信,则证明kmesh存在问题。 + +![alt text](pics/kmesh_pre_bypass.svg) + +![alt text](pics/kmesh_bypass.svg) + +## Bypass的数据结构 + +```c +struct bpf_map_def SEC("maps") bypass_fliter_map = { + .type = BPF_MAP_TYPE_HASH, + .key_size = sizeof(__u32), + .value_size = sizeof(__u8), + .max_entries = 256, +}; +``` + +key代表pod的IP地址,value代表当前pod是否开启bypass功能,用0/1表示。 当执行到这个ebpf程序时,它会检查对应的pod是否启用了bypass功能。 如果启用,则所有后续的 iptables 规则都将被短路,且出入方向的流量都将被短接。反之则不会短接后续的iptables规则。 + +## 如何开启bypass + +执行以下命令: + +```shell +kubectl label pod kmesh.net/bypass=enabled +``` + +这将会导致一个pod的出入流量都将被短接 + +## 如何观测label的变化 + +Kmesh Daemon 通过与 Kubernetes API Server 通信,使用字段选择器实现了对特定标签的观测。它观察 Kubernetes API Server 的变化,并过滤所需的资源对象,从而只观测特定标签的变化。 + +```go +informerFactory := informers.NewSharedInformerFactoryWithOptions(client, 0, + informers.WithTweakListOptions(func(options *metav1.ListOptions) { + options.FieldSelector = fmt.Sprintf("spec.nodeName=%s", nodeName) + options.LabelSelector = "kmesh.net/bypass=enabled" + })) + +podInformer := informerFactory.Core().V1().Pods() +``` + +## 流量治理流程 + +### 场景一:sidecar + +![alt text](pics/sidecar_traffic_path.svg) + +上图中黑色箭头表示的路径是bypass功能开启前的流量路径,蓝色箭头是bypass功能开启后的流量路径。 不同的是,启用bypass功能后,kmesh mda会在iptables规则的顶层添加两条。 规则是: + +```shell +iptables -t nat -I OUTPUT -m bpf --object-pinned /sys/fs/bpf/bypass -j RETURN +iptables -t nat -I PREROUTING -m bpf --object-pinned /sys/fs/bpf/bypass -j RETURN +``` + +这两条规则将导致流量路径在ebpf程序中被更新。 ebpf程序会判断当前pod是否开启了bypass功能。 如果启用该功能,数据将直接发送到对端服务,而不是服务网格中。 + +### 场景二:kmesh + +![alt text](pics/kmesh_traffic_path.svg) + +该场景下,上图中蓝色箭头所代表的路径即为旁路功能开启前后的流量路径。 不同之处是在kmesh原有的ebpf程序中增加了对bypass功能的判断。 当前kmesh是否接管流量的依据是ebpf程序是否获取到的classid是否与kmesh定义的classid一致。 如果一致,流量就会被接管。开启了bypass功能之后,还会再判断一次bypass功能是否启用。 + +## 注意 + +- 当前bypass功能仅短接单个Pod的服务网格流量,而不是整个流量路径上的服务网格。为了解决短接一方的服务网格之后,导致另一方服务网格无法解析收到的加密报文的问题。 在启用bypass功能之前,需要配置服务网格以明文格式发送消息 +- 目前bypass会短接单个Pod的出入方向的流量。 后续还将对出入方向的流量进行细分。 例如,只有出方向的流量会被短路。 diff --git a/docs/proposal/circuit_breaker_zh.md b/docs/proposal/circuit_breaker_zh.md new file mode 100644 index 000000000..7939562ab --- /dev/null +++ b/docs/proposal/circuit_breaker_zh.md @@ -0,0 +1,373 @@ +--- +����: Circuit Breaker +����: +- "@Okabe-Rintarou-0" # Authors' GitHub accounts here. +reviewers: +- "@supercharge-xsy" +- "@hzxuzhonghu" +- "@nlwcy" +- TBD +approvers: +- "@robot" +- TBD + +creation-date: 2024-05-29 + +--- + +## �� Kmesh ������ circuit breaker ���� + +### ���� + +��ҪĿ��: + ++ ֧�� circuit breaker ���ơ� ++ ֧���쳣��⡣ ++ ���ӳ�ֵĵ�Ԫ���ԡ� + +### ���� + +circuit breaker ����ͨ�����ڷ�ֹ����������ɢ������ϵͳ�ȶ��ԣ����������������ϵͳ�����������ϡ���ǰ Kmesh ��δʵ�� circuit breaker ���ơ� + +���� circuit breaker �ij������������� ++ ��������ʹ��� ++ �����ӳٹ��� ++ ������Դ�ľ� ++ ���񲻿��� ++ ��������ﵽ������� ++ �������Ӵﵽ������� + +#### Ŀ�� + ++ ֧�� circuit breaker ���ܣ�Kmesh Ӧ�ܴ� XDS ������ circuit breaker ���ò�������Ӧ circuit breaker�� ++ ֧���쳣��⣺Kmesh Ӧ�ܴ� XDS �������쳣������ò�֧���쳣��⡣ ++ ���ӳ�ֵ�Ԫ��������֤������ȷ�ԡ� + +### ���ϸ�� + +#### Istio �е� circuit breaker ���� + +Envoy ֧�ּ�Ⱥ���͵���������ֵ����Ŀǰ����������ֵ�� `max_connections` �ֶο��ã�������ϸ�������[�ٷ��ĵ�](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/circuit_breaker.proto). + +> per_host_thresholds +> (�ظ��� config.cluster.v3.CircuitBreakers.Thresholds)��ѡ�ĵ��������ƣ������ڼ�Ⱥ�е�ÿ�������� + +������ Envoy �� Istio ������ĶԱȱ��� + +| Envoy | Ŀ����� | Istio | Ŀ����� | +| --------------------------- | ------------------------ | ------------------------ | ------------- | +| max_connection | cluster.circuit_breakers | maxConnection | TcpSettings | +| max_pending_requests | cluster.circuit_breakers | http1MaxPendingRequests | HttpSettings | +| max_requests | cluster.circuit_breakers | http2MaxRequests | HttpSettings | +| max_retries | cluster.circuit_breakers | maxRetries | HttpSettings | +| connection_timeout_ms | cluster | connectTimeout | TcpSettings | +| max_requests_per_connection | cluster | maxRequestsPerConnection | HttpSettings | + +Envoy ʹ�õ� circuit breaker δ���ô�ͳ�� "Open"-"Half Open"-"Close" ��̬���壬����һ������������ڣ���ֵ��circuit breaker �ͻ�򿪣��رգ��� + +
+ +
+ +������ͼ��ʾ��˵���� + +1. ��ǰ�˷����Ŀ�����forecast������δ�������õ����������ʱ����������ͨ���� +2. ��ǰ�˷����Ŀ�����forecast������δ�������õ�������������ʱ������������ӳصȴ��� +3. ��ǰ�˷����Ŀ�����forecast�����󳬹����õ�������������ʱ������ֱ�ӱ��ܾ��� + +����ֵ `max_connection,` Ϊ�������������������ֵʱ��circuit breaker ���򿪡� + +`canCreateConnection` ����������������Ƿ���ڼ�Ⱥ����������ֵ�� + +```c++ +bool canCreateConnection(Upstream::ResourcePriority priority) const override { + if (stats().cx_active_.value() >= cluster().resourceManager(priority).maxConnectionsPerHost()) { + return false; + } + return cluster().resourceManager(priority).connections().canCreate(); +} +``` + +���޷����������ӣ���Ⱥ����ͳ���е� `upstream_cx_overflow_` �����������ӣ� + +```c++ +ConnPoolImplBase::tryCreateNewConnection(float global_preconnect_ratio) { + const bool can_create_connection = host_->canCreateConnection(priority_); + + if (!can_create_connection) { + host_->cluster().trafficStats()->upstream_cx_overflow_.inc(); + } + + // If we are at the connection circuit-breaker limit due to other upstreams having + // too many open connections, and this upstream has no connections, always create one, to + // prevent pending streams being queued to this upstream with no way to be processed. + if (can_create_connection || (ready_clients_.empty() && busy_clients_.empty() && + connecting_clients_.empty() && early_data_clients_.empty())) { + ENVOY_LOG(debug, "creating a new connection (connecting={})", connecting_clients_.size()); + // here are some logics for establishing a connection + } else { + ENVOY_LOG(trace, "not creating a new connection: connection constrained"); + return ConnectionResult::NoConnectionRateLimited; + } +} +``` + +Envoy ��֧���쳣��⣺��ij���˵���������쳣���緵�� 5xx HTTP ״̬�룩���ᱻ��ʱ�����ӳ����Ƴ��� + +
+ +
+ +һ��ʱ���ö˵�ᱻ���¼��룬���������ʧ������ٴα��Ƴ�����ÿ���Ƴ���ĵȴ�ʱ�������� + +��ˣ�Istio �Ķ�·������ L4 �� L7 �������������Ĺ��ܣ����±���ʾ�� + + +| ���� | ������� | +| ------------------------ | ---------------------------------------------------- | +| ���ӳ����� | L4 �㣬����ͳ������������ | +| �쳣��� | L4 & L7 �㣬HTTP ״̬��ͳ������������ | + +#### ʵ�����ӳ����� + +������ Envoy �е�һЩ�������ͼ������� + ++ ����ͳ�� + + | ���� | ���� | + | --------------- | ------- | + | cx_connect_fail | COUNTER | + | cx_total | COUNTER | + | rq_error | COUNTER | + | rq_success | COUNTER | + | rq_timeout | COUNTER | + | rq_total | COUNTER | + | cx_active | GAUGE | + | rq_active | GAUGE | + ++ ��Ⱥͳ�� + + ����� [config-cluster-manager-cluster-stats](https://www.envoyproxy.io/docs/envoy/latest/configuration/upstream/cluster_manager/cluster_stats#config-cluster-manager-cluster-stats). + +���ǿ���Ϊ��Ⱥ��Դ�ͼ�Ⱥ����ͳ����Ϣ�������Ƶ� bpf ӳ�䡣���ǿ��Զ���һЩ bpf ӳ�䣬������ʾ�� + +����Ӧ��ʹ���������ݽṹ�� bpf ӳ���¼ÿ����Ⱥ��״̬�� + +```c +struct cluster_stats { + __u32 active_connections; +}; + +struct cluster_stats_key { + __u64 netns_cookie; + __u32 cluster_id; +}; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(struct cluster_stats_key)); + __uint(value_size, sizeof(struct cluster_stats)); + __uint(map_flags, BPF_F_NO_PREALLOC); + __uint(max_entries, MAP_SIZE_OF_CLUSTER); +} map_of_cluster_stats SEC(".maps"); +``` +�����������������ɣ� `netns_cookie` �� `cluster_id`��ǰ�����ڱ�ʶ Pod�������ߴ�����Ⱥ�����ǣ�cluster �ı�ʶ���������ơ��������ʹ������Ϊ `cluster_id`�����Ǻ����׳��� bpf ��ջ�Ĵ�С���ơ���ˣ�������Ҫʹ�� hash �� cluster name ӳ�䵽һ�������� + +```c +// Flush flushes the cluster to bpf map. +func (cache *ClusterCache) Flush() { + cache.mutex.Lock() + defer cache.mutex.Unlock() + for name, cluster := range cache.apiClusterCache { + if cluster.GetApiStatus() == core_v2.ApiStatus_UPDATE { + err := maps_v2.ClusterUpdate(name, cluster) + if err == nil { + // reset api status after successfully updated + cluster.ApiStatus = core_v2.ApiStatus_NONE + cluster.Id = cache.hashName.StrToNum(name) + } else { + log.Errorf("cluster %s %s flush failed: %v", name, cluster.ApiStatus, err) + } + } else if cluster.GetApiStatus() == core_v2.ApiStatus_DELETE { + err := maps_v2.ClusterDelete(name) + if err == nil { + delete(cache.apiClusterCache, name) + delete(cache.resourceHash, name) + cache.hashName.Delete(name) + } else { + log.Errorf("cluster %s delete failed: %v", name, err) + } + } + } +} +``` +����Կ�������������һ�� hashName �����ַ���ӳ�䵽������ + +��������ǻ��� cluster ������һ�����ֶ� `id`�� + +```protobuf +message Cluster { + enum LbPolicy { + ROUND_ROBIN = 0; + LEAST_REQUEST = 1; + RANDOM = 3; + } + + core.ApiStatus api_status = 128; + string name = 1; + uint32 id = 2; + uint32 connect_timeout = 4; + LbPolicy lb_policy = 6; + + endpoint.ClusterLoadAssignment load_assignment = 33; + CircuitBreakers circuit_breakers = 10; +} +``` +Ҫ��ص�ǰ��Ծ�� tcp ���ӣ�������Ҫ����һ�� `BPF_MAP_TYPE_SK_STORAGE` ӳ�䣺 + +```c +struct cluster_sock_data { + __u32 cluster_id; +}; + +struct { + __uint(type, BPF_MAP_TYPE_SK_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, struct cluster_sock_data); +} map_of_cluster_sock SEC(".maps"); +``` + +���ǿ��Ի����������� socket ���������ڡ� + +Ȼ�����ǿ��԰������������ͼ�������� + +
+ +
+ +���ǿ��Լ�� eBPF ��sockops�� hooks �е� socket�������ȣ������жϼ�Ⱥ�Ļ�Ծ�������Ƿ�ﵽ�����ֵ�����������������Ӧ�þܾ������ӣ����������һ����Ȼ�����������������������ӣ������� socket op �����ͽ��д����� + ++ TCP_DEFER_CONNECT: + + ���ǽ��ڴ˷�֧������ sockops ��������������������һϵ����ʽ���ã����մﵽ`cluster_manager` ���鿴��ͼ���� + +
+ +
+ + ���ǽ��ڴ˴���ȡ��Ⱥ��Ϣ�����磬��Ⱥ ID�������ǿ��Խ���Ⱥ ID �洢��`cluster_sock_data` �С�������׶Σ������Ѿ�����Ⱥ�󶨵� socket�� + + ���ǿ���ͨ��������� `cluster_manager` �е������������ʵ����һ�㣺 + + ```c + static inline void on_cluster_sock_bind(struct bpf_sock *sk, const char* cluster_name) { + BPF_LOG(DEBUG, KMESH, "record sock bind for cluster %s\n", cluster_name); + struct cluster_sock_data *data = NULL; + if (!sk) { + BPF_LOG(WARN, KMESH, "provided sock is NULL\n"); + return; + } + + data = bpf_sk_storage_get(&map_of_cluster_sock, sk, 0, BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!data) { + BPF_LOG(ERR, KMESH, "record_cluster_sock call bpf_sk_storage_get failed\n"); + return; + } + + bpf_strncpy(data->cluster_name, BPF_DATA_MAX_LEN, (char *)cluster_name); + BPF_LOG(DEBUG, KMESH, "record sock bind for cluster %s done\n", cluster_name); + } + ``` + ++ ACTIVE ESTABLISHED + + �����TCP �����ѽ��������ǿ��Լ�鵱ǰ socket �Ƿ�ָ��Ⱥ������ǣ�����Ӧ�����������Ӽ�Ⱥ���Ӽ������� + + ���ǿ�������������������: + + ```c + static inline void on_cluster_sock_connect(struct bpf_sock_ops *ctx) + { + if (!ctx) { + return; + } + struct cluster_sock_data *data = get_cluster_sk_data(ctx->sk); + if (!data) { + return; + } + __u64 cookie = bpf_get_netns_cookie(ctx); + struct cluster_stats_key key = {0}; + key.netns_cookie = cookie; + key.cluster_id = data->cluster_id; + BPF_LOG( + DEBUG, + KMESH, + "increase cluster active connections(netns_cookie = %lld, cluster id = %ld)", + key.netns_cookie, + key.cluster_id); + update_cluster_active_connections(&key, 1); + BPF_LOG(DEBUG, KMESH, "record sock connection for cluster id = %ld\n", data->cluster_id); + } + ``` + ++ TCP CLOSE + + һ�� TCP ���ӹرգ�����Ӧ�ü��ټ�����: + + ```c + static inline void on_cluster_sock_close(struct bpf_sock_ops *ctx) + { + if (!ctx) { + return; + } + struct cluster_sock_data *data = get_cluster_sk_data(ctx->sk); + if (!data) { + return; + } + __u64 cookie = bpf_get_netns_cookie(ctx); + struct cluster_stats_key key = {0}; + key.netns_cookie = cookie; + key.cluster_id = data->cluster_id; + update_cluster_active_connections(&key, -1); + BPF_LOG( + DEBUG, + KMESH, + "decrease cluster active connections(netns_cookie = %lld, cluster id = %ld)", + key.netns_cookie, + key.cluster_id); + BPF_LOG(DEBUG, KMESH, "record sock close for cluster id = %ld", data->cluster_id); + } + ``` + +���ǿ��ԴӼ�Ⱥ�����л�ȡ circuit breaker ��Ϣ�� +```c +static inline Cluster__CircuitBreakers *get_cluster_circuit_breakers(const char *cluster_name) +{ + const Cluster__Cluster *cluster = NULL; + cluster = map_lookup_cluster(cluster_name); + if (!cluster) { + return NULL; + } + Cluster__CircuitBreakers *cbs = NULL; + cbs = kmesh_get_ptr_val(cluster->circuit_breakers); + if (cbs != NULL) + BPF_LOG(DEBUG, KMESH, "get cluster's circuit breaker: max connections = %ld\n", cbs->max_connections); + return cbs; +} +``` +Ȼ�����ǿ��Դ� `Cluster__CircuitBreakers` ��ȡ������ֵ����ȷ�� circuit breaker �Ƿ�Ӧ�ô򿪡� + +#### ʵ���쳣ֵ��⺯�� + +Istio �� Envoy �е��쳣�����һ����ǿ΢����ϵͳ���Ժ��ȶ��ԵĻ��ơ�����ҪĿ���Ǽ��͸�������쳣�ķ���ʵ������ֹ��Щʵ��Ӱ��ϵͳ���������ܺͿ����ԡ� + +����������Ҫ���ܣ� + ++ �쳣����ط���ʵ���Ľ���״̬��������Ԥ����Ķ�����׼ʶ���쳣���ܣ���������ʧ������������������ʧ���ʡ� + ++ һ����⵽�쳣���쳣������ʱ����ʵ���Ӹ��ؾ�������Ƴ�����Ч�ء����𡱸�ʵ���Է�������µ����󡣾���һ��ʱ���ϵͳ������������ʵ���Ľ���״̬��������Ѿ��ָ����������Ὣ���������븺�ؾ���ء� + +���ǿ����� eBPF �м�� HTTP ����״̬����ȷ�������Ƿ���� 5xx ���󡣵��������������ﵽij����ֵʱ��������Ҫ����Ӧ�Ķ˵��ų��ڸ��ؾ���ѡ��֮�⡣ + +��غ����������Ĺ������������ӳ����õĹ��ܡ� diff --git a/docs/proposal/dns_resolve_zh.md b/docs/proposal/dns_resolve_zh.md new file mode 100644 index 000000000..11d8f5d5f --- /dev/null +++ b/docs/proposal/dns_resolve_zh.md @@ -0,0 +1,94 @@ +--- +title: Kmesh DNS 解析 +authors: +- "@luoyunhe" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh DNS 解析 + +## 摘要 + +本文档描述了 Kmesh 的 DNS 解析功能。 + +## 背景 + +在 Kmesh 中,我们需要支持 DNS 解析功能,以便能够处理域名形式的目标地址。这对于处理外部服务和内部服务的域名解析都是必要的。 + +## 目标 + +1. 支持域名形式的目标地址解析 +2. 提供高效的 DNS 缓存机制 +3. 确保解析结果的准确性和及时更新 + +## 设计细节 + +### 架构设计 + +DNS 解析模块主要包含以下组件: + +1. DNS 解析器:负责实际的 DNS 查询操作 +2. DNS 缓存:存储已解析的结果 +3. 更新机制:定期刷新 DNS 记录 + +### 实现细节 + +#### DNS 解析器 + +```go +type DnsResolver interface { + Resolve(domain string) ([]net.IP, error) + Update(domain string) error +} +``` + +#### DNS 缓存 + +```go +type DnsCache struct { + mutex sync.RWMutex + cache map[string]*DnsRecord +} + +type DnsRecord struct { + IPs []net.IP + ExpireAt time.Time +} +``` + +### 工作流程 + +1. 接收域名解析请求 +2. 检查缓存是否存在有效记录 +3. 如果缓存无效或不存在,执行 DNS 查询 +4. 更新缓存并返回结果 + +## 使用示例 + +```go +resolver := NewDnsResolver() +ips, err := resolver.Resolve("example.com") +if err != nil { + log.Errorf("DNS resolve failed: %v", err) + return +} +``` + +## 注意事项 + +1. 缓存过期时间设置 +2. 错误处理机制 +3. 并发安全性保证 + +## 未来工作 + +1. 支持更多 DNS 记录类型 +2. 优化缓存策略 +3. 添加监控指标 + diff --git a/docs/proposal/e2e_zh.md b/docs/proposal/e2e_zh.md new file mode 100644 index 000000000..85147e1d2 --- /dev/null +++ b/docs/proposal/e2e_zh.md @@ -0,0 +1,127 @@ +--- +title: Kmesh E2E 测试框架 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh E2E 测试框架 + +## 摘要 + +本文档描述了 Kmesh 的端到端(E2E)测试框架设计方案。 + +## 背景 + +端到端测试是确保系统整体功能正确性的重要手段。Kmesh 需要一个完善的 E2E 测试框架来验证各个组件的集成功能。 + +## 目标 + +1. 构建自动化测试框架 +2. 覆盖关键功能场景 +3. 提供清晰的测试报告 +4. 支持持续集成 + +## 设计细节 + +### 架构设计 + +E2E 测试框架包含以下组件: + +1. 测试用例管理器 +2. 测试环境管理器 +3. 测试执行器 +4. 结果收集器 +5. 报告生成器 + +### 测试用例 + +```go +type TestCase struct { + Name string + Description string + Setup func() error + Run func() error + Cleanup func() error + Timeout time.Duration +} +``` + +### 测试环境 + +```yaml +apiVersion: v1 +kind: TestEnvironment +metadata: + name: kmesh-e2e +spec: + components: + - name: kmesh-controller + image: kmesh/controller:latest + - name: kmesh-agent + image: kmesh/agent:latest + services: + - name: test-service + replicas: 2 +``` + +### 测试执行 + +```go +func RunTest(t *testing.T, tc TestCase) { + if err := tc.Setup(); err != nil { + t.Fatalf("Setup failed: %v", err) + } + + defer func() { + if err := tc.Cleanup(); err != nil { + t.Errorf("Cleanup failed: %v", err) + } + }() + + if err := tc.Run(); err != nil { + t.Errorf("Test failed: %v", err) + } +} +``` + +## 使用示例 + +### 运行测试 + +```bash +# 运行所有测试 +make e2e-test + +# 运行特定测试 +make e2e-test TEST=TestServiceDiscovery +``` + +### 查看报告 + +```bash +# 生成测试报告 +make test-report + +# 查看测试覆盖率 +make coverage-report +``` + +## 注意事项 + +1. 环境隔离 +2. 资源清理 +3. 超时处理 + +## 未来工作 + +1. 扩展测试场景 +2. 优化执行效率 +3. 增强报告功能 + diff --git a/docs/proposal/ebpf-observability_zh.md b/docs/proposal/ebpf-observability_zh.md new file mode 100644 index 000000000..0a75adba4 --- /dev/null +++ b/docs/proposal/ebpf-observability_zh.md @@ -0,0 +1,106 @@ +--- +title: Kmesh eBPF 可观测性 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh eBPF 可观测性 + +## 摘要 + +本文档描述了 Kmesh 中 eBPF 可观测性的设计方案,用于监控和分析 eBPF 程序的运行状态。 + +## 背景 + +eBPF 程序的可观测性对于理解系统行为和性能优化至关重要。Kmesh 需要提供完善的 eBPF 可观测性能力。 + +## 目标 + +1. 监控 eBPF 程序运行状态 +2. 收集性能指标 +3. 提供调试信息 +4. 支持故障诊断 + +## 设计细节 + +### 架构设计 + +eBPF 可观测性系统包含以下组件: + +1. 程序监控器 +2. 性能分析器 +3. 日志收集器 +4. 调试工具 + +### 数据结构 + +```c +struct BpfMetrics { + __u64 program_id; // 程序 ID + __u64 run_time; // 运行时间 + __u64 events_processed; // 处理事件数 + __u64 errors; // 错误数 +}; + +struct BpfDebugInfo { + __u32 program_type; // 程序类型 + __u32 attach_type; // 挂载类型 + __u32 map_ids[8]; // 使用的 Map IDs + __u32 status; // 运行状态 +}; +``` + +### 监控接口 + +```go +type BpfMonitor interface { + GetMetrics(programID uint64) (*BpfMetrics, error) + GetDebugInfo(programID uint64) (*BpfDebugInfo, error) + ListPrograms() ([]uint64, error) + GetMapInfo(mapID uint32) (*MapInfo, error) +} +``` + +## 使用示例 + +### 查看程序状态 + +```bash +# 列出所有 eBPF 程序 +kmesh bpf list + +# 查看程序指标 +kmesh bpf metrics + +# 查看调试信息 +kmesh bpf debug +``` + +### 分析性能 + +```bash +# 查看程序性能分析 +kmesh bpf profile + +# 导出性能数据 +kmesh bpf export-metrics +``` + +## 注意事项 + +1. 性能开销控制 +2. 安全性考虑 +3. 数据准确性 + +## 未来工作 + +1. 增强调试能力 +2. 优化性能分析 +3. 提供更多监控指标 diff --git a/docs/proposal/ebpf_unit_test_zh.md b/docs/proposal/ebpf_unit_test_zh.md index 3d1319e04..7ae251065 100644 --- a/docs/proposal/ebpf_unit_test_zh.md +++ b/docs/proposal/ebpf_unit_test_zh.md @@ -1,237 +1,237 @@ -# Kmesh eBPF 单元测试框架 - -## **1 背景** - -当前,Kmesh 需要一个轻量级的单元测试框架来测试 eBPF 程序。该框架应能够独立运行单个 eBPF 程序的测试,而无需加载整个 Kmesh 系统,从而提高测试效率和覆盖率。 - -## **2 设计思路** - -kmesh项目中的eBPF内核态代码由cilium/ebpf项目进行管理,因此我们可以借鉴cilium项目中的eBPF单元测试框架,对其进行适当的修改和定制,以满足kmesh项目的需求。 - -### 2.1 cilium eBPF 单元测试框架介绍 - -> 参考cilium v1.17: -> -> eBPF单元测试文档: -> -> cilium/bpf/tests源码: - -#### 2.1.1 cilium/bpf/tests概述 - -Cilium项目使用一个专门的测试框架来验证其BPF程序的正确性。这个框架允许开发者编写测试用例,构建网络数据包,并验证BPF程序在不同情况下的行为。 - -#### 2.1.2 cilium/bpf/tests测试文件结构 - -以`xdp_nodeport_lb4_test.c`(测试Cilium的XDP程序在IPv4环境下的负载均衡功能)为例,一个典型的测试文件核心内容如下: - -```c -// https://github.com/cilium/cilium/blob/v1.17.0/bpf/tests/xdp_nodeport_lb4_test.c -#include "common.h" -#include "bpf/ctx/xdp.h" - -// 模拟FIB(Forwarding Information Base)查找函数,填充源MAC和目的MAC -#define fib_lookup mock_fib_lookup - -static const char fib_smac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02}; -static const char fib_dmac[6] = {0x13, 0x37, 0x13, 0x37, 0x13, 0x37}; - -long mock_fib_lookup(__maybe_unused void *ctx, struct bpf_fib_lookup *params, - __maybe_unused int plen, __maybe_unused __u32 flags) -{ - __bpf_memcpy_builtin(params->smac, fib_smac, ETH_ALEN); - __bpf_memcpy_builtin(params->dmac, fib_dmac, ETH_ALEN); - return 0; -} - -// 直接包含BPF代码 -#include "bpf_xdp.c" - -// 在测试代码中使用尾调用执行被测试BPF程序 -struct { - __uint(type, BPF_MAP_TYPE_PROG_ARRAY); - __uint(key_size, sizeof(__u32)); - __uint(max_entries, 2); - __array(values, int()); -} entry_call_map __section(".maps") = { - .values = { - [0] = &cil_xdp_entry, - }, -}; - -// 构建测试xdp包,可以使用PKTGEN宏达到相同的效果 -static __always_inline int build_packet(struct __ctx_buff *ctx){} - -// 构建数据包,添加前端和后端,然后tail call跳转到入口点 -SETUP("xdp", "xdp_lb4_forward_to_other_node") -int test1_setup(struct __ctx_buff *ctx) -{ - int ret; - - ret = build_packet(ctx); - if (ret) - return ret; - - lb_v4_add_service(FRONTEND_IP, FRONTEND_PORT, IPPROTO_TCP, 1, 1); - lb_v4_add_backend(FRONTEND_IP, FRONTEND_PORT, 1, 124, - BACKEND_IP, BACKEND_PORT, IPPROTO_TCP, 0); - - /* Jump into the entrypoint */ - tail_call_static(ctx, entry_call_map, 0); - /* Fail if we didn't jump */ - return TEST_ERROR; -} - -// 检查测试结果 -CHECK("xdp", "xdp_lb4_forward_to_other_node") -int test1_check(__maybe_unused const struct __ctx_buff *ctx) -{ - test_init(); - - void *data = (void *)(long)ctx->data; - void *data_end = (void *)(long)ctx->data_end; - - if (data + sizeof(__u32) > data_end) - test_fatal("status code out of bounds"); - - //... - - test_finish(); -} - -``` - -#### 2.1.3 cilium/bpf/tests测试框架设计 - -Cilium的eBPF测试框架以`common.h`为核心,该头文件提供了测试所需的基础设施、宏和函数: - -##### 核心测试宏 - -- **TEST(name, body)**: 定义单个测试用例,用于组织独立的测试功能 -- **PKTGEN(progtype, name)**: 定义用于生成网络数据包的测试段 -- **SETUP(progtype, name)**: 定义测试的初始化环节,如设置测试环境和前置条件 -- **CHECK(progtype, name)**: 定义验证测试结果的检查段,每个测试至少需要一个 - -##### 测试流程控制 - -- **test_init()**: 初始化测试环境,在测试开始时调用 -- **test_finish()**: 完成测试并返回结果,在测试结束时调用 -- **test_fail(fmt, ...)**: 将当前测试标记为失败,并提供失败原因 -- **test_skip(fmt, ...)**: 跳过当前测试,常用于依赖条件不满足的情况 - -##### 断言与日志机制 - -- **assert(cond)**: 验证条件是否为真,否则测试失败 -- **test_log(fmt, args...)**: 记录测试消息,类似`printf`格式 -- **test_error(fmt, ...)**: 记录错误并标记测试失败 -- **test_fatal(fmt, ...)**: 记录严重错误并立即终止测试 -- **assert_metrics_count(key, count)**: 验证特定指标计数是否符合预期 - -##### 测试结果管理 - -测试框架使用以下状态码标记测试结果: - -- **TEST_ERROR (0)**: 测试执行遇到错误 -- **TEST_PASS (1)**: 测试通过 -- **TEST_FAIL (2)**: 测试失败 -- **TEST_SKIP (3)**: 测试被跳过 - -##### 测试执行流程 - -1. **测试启动**: 在项目根目录执行`make run_bpf_tests`命令 -2. **容器构建**: 构建Docker测试容器,确保测试环境一致性 -3. **测试编译**: 使用Clang编译eBPF测试代码 -4. **测试协调**: Go测试框架负责管理测试生命周期,包括: - - 加载编译好的eBPF程序 - - 初始化测试环境 - - 执行测试用例 - - 收集测试结果 - -##### Go与eBPF通信机制 - -1. **Protocol Buffer接口**: 定义了结构化消息格式,用于Go和eBPF测试程序间通信 -2. **测试结果存储**: eBPF测试程序将结果编码后存入`suite_result_map` -3. **结果提取与解析**: Go测试代码读取map并解码结果,进行验证和报告 - -##### 单测覆盖率 - -Cilium项目使用[coverbee](https://github.com/cilium/coverbee)子项目来测量eBPF程序的代码覆盖率。这为eBPF程序提供了与用户态代码类似的覆盖率分析能力: - -- **工作原理**: - - 对eBPF字节码进行插桩,为每行代码分配唯一序号,并添加计数器逻辑:`cover_map[line_id]++` - - 当程序执行时,访问的每行代码对应的计数器会递增 - -- **覆盖率分析流程**: - 1. 插桩后的eBPF程序执行时收集执行次数数据 - 2. 用户态程序读取覆盖率映射表(cover_map) - 3. 将收集到的数据与源代码行号关联 - 4. 生成标准格式的覆盖率报告 - -##### 数据交换流程 - -```text -[eBPF Test Program] → [Encode Results] → [suite_result_map] → [Go Test Runner] → [Decode & Report] -``` - -Go测试框架负责最终的测试报告汇总,包括测试通过率、覆盖率统计和失败用例分析。 - -### 2.2 kmesh eBPF 单元测试框架设计 - -#### 2.2.1 kmesh eBPF 单元测试需求分析 - -对比 Cilium 和 Kmesh 项目,我们需要考虑以下差异来设计单元测试框架: - -1. **构建系统差异**: - - Cilium 使用 Clang 直接将 BPF 代码编译为字节码 - - Kmesh 使用 cilium/ebpf 提供的 bpf2go 工具,将 BPF C 代码编译并转换为 Go 代码调用 - -2. **代码维护挑战**: - - 当前 Kmesh 中使用 libbpf 维护被测试 BPF 代码,造成需要同时维护 bpf2go 和 unittest-makefile 两套编译命令 - - 核心 eBPF 代码变更后,测试代码需要同步更新,维护成本较高 - -3. **目标**: - - 设计一个与主代码紧密集成的测试框架 - - 减少重复维护开销 - - 使用golang的测试框架进行测试,方便集成到CI/CD流程中 - -#### 2.2.2 kmesh eBPF 单元测试框架设计 - -基于对 Cilium 测试框架的分析和 Kmesh 项目特点,我们设计了 Kmesh eBPF 单元测试框架,主要包含以下几个部分: - -##### 整体架构 - -Kmesh eBPF 单元测试框架采用分层设计: - -1. **eBPF 测试程序层**:编写 C 语言的 eBPF 测试代码,包含测试用例、测试数据和验证逻辑 -2. **Go 测试驱动层**:负责加载 eBPF 程序、在用户态加载策略、执行测试和收集结果 -3. **结果通信层**:使用 Protocol Buffer 定义的结构进行测试结果传递 - -##### 核心组件 - -1. **eBPF 单元测试结构**: - - **PKTGEN 段**:生成测试数据包,模拟网络输入 - - **JUMP 段**:配置初始状态,尾调用被测试的 BPF 程序 - - **CHECK 段**:验证测试结果,进行断言检查 - - **内存数据交换**:通过 eBPF maps 在 BPF 程序和 Golang 用户空间间传递数据 - -2. **Go 测试驱动**: - - **unittest类**:unittest 结构体表示一个eBPF单元测试,包含测试名称、eBPF对象文件名称以及用户空间设置函数。 - - **程序加载器**:使用 `cilium/ebpf` 库加载编译后的 eBPF 对象文件 - - **测试执行器**:调用 BPF 程序,传递测试数据和上下文 - - **结果解析器**:从 eBPF maps 中读取测试结果并解析 - -3. **结果格式化**: - - 使用 `SuiteResult` Protocol Buffer 消息定义测试结果结构 - - 支持测试日志、测试状态(通过、失败、跳过、错误) - -##### 测试执行流程 - -1. **测试加载**:为每个unittest对象加载 eBPF Collection -2. **测试准备**:运行unittest对象的`setupInUserSpace`逻辑,初始化测试环境 -3. **程序分类**:根据段名将程序分为 `jump`、`check` 和 `pktgen` 三类 -4. **测试执行**: - - 用户态Go的unittest对象中如果存在 `setupInUserSpace`,首先运行它设置测试环境 - - 如果存在 `pktgen`,运行它生成测试数据 - - 然后运行 `jump`,执行被测试的 BPF 程序 - - 最后运行 `check` 程序验证结果 -5. **结果收集**:从 `suite_result_map` 中读取测试结果 -6. **结果报告**:解析结果并使用 Go 测试框架生成报告 +# Kmesh eBPF 单元测试框架 + +## **1 背景** + +当前,Kmesh 需要一个轻量级的单元测试框架来测试 eBPF 程序。该框架应能够独立运行单个 eBPF 程序的测试,而无需加载整个 Kmesh 系统,从而提高测试效率和覆盖率。 + +## **2 设计思路** + +kmesh项目中的eBPF内核态代码由cilium/ebpf项目进行管理,因此我们可以借鉴cilium项目中的eBPF单元测试框架,对其进行适当的修改和定制,以满足kmesh项目的需求。 + +### 2.1 cilium eBPF 单元测试框架介绍 + +> 参考cilium v1.17: +> +> eBPF单元测试文档: +> +> cilium/bpf/tests源码: + +#### 2.1.1 cilium/bpf/tests概述 + +Cilium项目使用一个专门的测试框架来验证其BPF程序的正确性。这个框架允许开发者编写测试用例,构建网络数据包,并验证BPF程序在不同情况下的行为。 + +#### 2.1.2 cilium/bpf/tests测试文件结构 + +以`xdp_nodeport_lb4_test.c`(测试Cilium的XDP程序在IPv4环境下的负载均衡功能)为例,一个典型的测试文件核心内容如下: + +```c +// https://github.com/cilium/cilium/blob/v1.17.0/bpf/tests/xdp_nodeport_lb4_test.c +#include "common.h" +#include "bpf/ctx/xdp.h" + +// 模拟FIB(Forwarding Information Base)查找函数,填充源MAC和目的MAC +#define fib_lookup mock_fib_lookup + +static const char fib_smac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02}; +static const char fib_dmac[6] = {0x13, 0x37, 0x13, 0x37, 0x13, 0x37}; + +long mock_fib_lookup(__maybe_unused void *ctx, struct bpf_fib_lookup *params, + __maybe_unused int plen, __maybe_unused __u32 flags) +{ + __bpf_memcpy_builtin(params->smac, fib_smac, ETH_ALEN); + __bpf_memcpy_builtin(params->dmac, fib_dmac, ETH_ALEN); + return 0; +} + +// 直接包含BPF代码 +#include "bpf_xdp.c" + +// 在测试代码中使用尾调用执行被测试BPF程序 +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(key_size, sizeof(__u32)); + __uint(max_entries, 2); + __array(values, int()); +} entry_call_map __section(".maps") = { + .values = { + [0] = &cil_xdp_entry, + }, +}; + +// 构建测试xdp包,可以使用PKTGEN宏达到相同的效果 +static __always_inline int build_packet(struct __ctx_buff *ctx){} + +// 构建数据包,添加前端和后端,然后tail call跳转到入口点 +SETUP("xdp", "xdp_lb4_forward_to_other_node") +int test1_setup(struct __ctx_buff *ctx) +{ + int ret; + + ret = build_packet(ctx); + if (ret) + return ret; + + lb_v4_add_service(FRONTEND_IP, FRONTEND_PORT, IPPROTO_TCP, 1, 1); + lb_v4_add_backend(FRONTEND_IP, FRONTEND_PORT, 1, 124, + BACKEND_IP, BACKEND_PORT, IPPROTO_TCP, 0); + + /* Jump into the entrypoint */ + tail_call_static(ctx, entry_call_map, 0); + /* Fail if we didn't jump */ + return TEST_ERROR; +} + +// 检查测试结果 +CHECK("xdp", "xdp_lb4_forward_to_other_node") +int test1_check(__maybe_unused const struct __ctx_buff *ctx) +{ + test_init(); + + void *data = (void *)(long)ctx->data; + void *data_end = (void *)(long)ctx->data_end; + + if (data + sizeof(__u32) > data_end) + test_fatal("status code out of bounds"); + + //... + + test_finish(); +} + +``` + +#### 2.1.3 cilium/bpf/tests测试框架设计 + +Cilium的eBPF测试框架以`common.h`为核心,该头文件提供了测试所需的基础设施、宏和函数: + +##### 核心测试宏 + +- **TEST(name, body)**: 定义单个测试用例,用于组织独立的测试功能 +- **PKTGEN(progtype, name)**: 定义用于生成网络数据包的测试段 +- **SETUP(progtype, name)**: 定义测试的初始化环节,如设置测试环境和前置条件 +- **CHECK(progtype, name)**: 定义验证测试结果的检查段,每个测试至少需要一个 + +##### 测试流程控制 + +- **test_init()**: 初始化测试环境,在测试开始时调用 +- **test_finish()**: 完成测试并返回结果,在测试结束时调用 +- **test_fail(fmt, ...)**: 将当前测试标记为失败,并提供失败原因 +- **test_skip(fmt, ...)**: 跳过当前测试,常用于依赖条件不满足的情况 + +##### 断言与日志机制 + +- **assert(cond)**: 验证条件是否为真,否则测试失败 +- **test_log(fmt, args...)**: 记录测试消息,类似`printf`格式 +- **test_error(fmt, ...)**: 记录错误并标记测试失败 +- **test_fatal(fmt, ...)**: 记录严重错误并立即终止测试 +- **assert_metrics_count(key, count)**: 验证特定指标计数是否符合预期 + +##### 测试结果管理 + +测试框架使用以下状态码标记测试结果: + +- **TEST_ERROR (0)**: 测试执行遇到错误 +- **TEST_PASS (1)**: 测试通过 +- **TEST_FAIL (2)**: 测试失败 +- **TEST_SKIP (3)**: 测试被跳过 + +##### 测试执行流程 + +1. **测试启动**: 在项目根目录执行`make run_bpf_tests`命令 +2. **容器构建**: 构建Docker测试容器,确保测试环境一致性 +3. **测试编译**: 使用Clang编译eBPF测试代码 +4. **测试协调**: Go测试框架负责管理测试生命周期,包括: + - 加载编译好的eBPF程序 + - 初始化测试环境 + - 执行测试用例 + - 收集测试结果 + +##### Go与eBPF通信机制 + +1. **Protocol Buffer接口**: 定义了结构化消息格式,用于Go和eBPF测试程序间通信 +2. **测试结果存储**: eBPF测试程序将结果编码后存入`suite_result_map` +3. **结果提取与解析**: Go测试代码读取map并解码结果,进行验证和报告 + +##### 单测覆盖率 + +Cilium项目使用[coverbee](https://github.com/cilium/coverbee)子项目来测量eBPF程序的代码覆盖率。这为eBPF程序提供了与用户态代码类似的覆盖率分析能力: + +- **工作原理**: + - 对eBPF字节码进行插桩,为每行代码分配唯一序号,并添加计数器逻辑:`cover_map[line_id]++` + - 当程序执行时,访问的每行代码对应的计数器会递增 + +- **覆盖率分析流程**: + 1. 插桩后的eBPF程序执行时收集执行次数数据 + 2. 用户态程序读取覆盖率映射表(cover_map) + 3. 将收集到的数据与源代码行号关联 + 4. 生成标准格式的覆盖率报告 + +##### 数据交换流程 + +```text +[eBPF Test Program] → [Encode Results] → [suite_result_map] → [Go Test Runner] → [Decode & Report] +``` + +Go测试框架负责最终的测试报告汇总,包括测试通过率、覆盖率统计和失败用例分析。 + +### 2.2 kmesh eBPF 单元测试框架设计 + +#### 2.2.1 kmesh eBPF 单元测试需求分析 + +对比 Cilium 和 Kmesh 项目,我们需要考虑以下差异来设计单元测试框架: + +1. **构建系统差异**: + - Cilium 使用 Clang 直接将 BPF 代码编译为字节码 + - Kmesh 使用 cilium/ebpf 提供的 bpf2go 工具,将 BPF C 代码编译并转换为 Go 代码调用 + +2. **代码维护挑战**: + - 当前 Kmesh 中使用 libbpf 维护被测试 BPF 代码,造成需要同时维护 bpf2go 和 unittest-makefile 两套编译命令 + - 核心 eBPF 代码变更后,测试代码需要同步更新,维护成本较高 + +3. **目标**: + - 设计一个与主代码紧密集成的测试框架 + - 减少重复维护开销 + - 使用golang的测试框架进行测试,方便集成到CI/CD流程中 + +#### 2.2.2 kmesh eBPF 单元测试框架设计 + +基于对 Cilium 测试框架的分析和 Kmesh 项目特点,我们设计了 Kmesh eBPF 单元测试框架,主要包含以下几个部分: + +##### 整体架构 + +Kmesh eBPF 单元测试框架采用分层设计: + +1. **eBPF 测试程序层**:编写 C 语言的 eBPF 测试代码,包含测试用例、测试数据和验证逻辑 +2. **Go 测试驱动层**:负责加载 eBPF 程序、在用户态加载策略、执行测试和收集结果 +3. **结果通信层**:使用 Protocol Buffer 定义的结构进行测试结果传递 + +##### 核心组件 + +1. **eBPF 单元测试结构**: + - **PKTGEN 段**:生成测试数据包,模拟网络输入 + - **JUMP 段**:配置初始状态,尾调用被测试的 BPF 程序 + - **CHECK 段**:验证测试结果,进行断言检查 + - **内存数据交换**:通过 eBPF maps 在 BPF 程序和 Golang 用户空间间传递数据 + +2. **Go 测试驱动**: + - **unittest类**:unittest 结构体表示一个eBPF单元测试,包含测试名称、eBPF对象文件名称以及用户空间设置函数。 + - **程序加载器**:使用 `cilium/ebpf` 库加载编译后的 eBPF 对象文件 + - **测试执行器**:调用 BPF 程序,传递测试数据和上下文 + - **结果解析器**:从 eBPF maps 中读取测试结果并解析 + +3. **结果格式化**: + - 使用 `SuiteResult` Protocol Buffer 消息定义测试结果结构 + - 支持测试日志、测试状态(通过、失败、跳过、错误) + +##### 测试执行流程 + +1. **测试加载**:为每个unittest对象加载 eBPF Collection +2. **测试准备**:运行unittest对象的`setupInUserSpace`逻辑,初始化测试环境 +3. **程序分类**:根据段名将程序分为 `jump`、`check` 和 `pktgen` 三类 +4. **测试执行**: + - 用户态Go的unittest对象中如果存在 `setupInUserSpace`,首先运行它设置测试环境 + - 如果存在 `pktgen`,运行它生成测试数据 + - 然后运行 `jump`,执行被测试的 BPF 程序 + - 最后运行 `check` 程序验证结果 +5. **结果收集**:从 `suite_result_map` 中读取测试结果 +6. **结果报告**:解析结果并使用 Go 测试框架生成报告 diff --git a/docs/proposal/kmesh_support_encrypt.md b/docs/proposal/kmesh_support_encrypt.md index 60e22678e..41cdfa004 100644 --- a/docs/proposal/kmesh_support_encrypt.md +++ b/docs/proposal/kmesh_support_encrypt.md @@ -1,239 +1,234 @@ ---- -title: Kmesh支持节点之间进行数据加密 -authors: -- "@bitcoffeeiux" -reviews: -- -approves: -- - -create-date: 2024-10-10 - ---- - -## 1.背景 - -随着网络安全威胁的增加,未经加密的数据在传输过程中容易被黑客或第三方监听、截取甚至篡改,导致敏感信息泄露。为了解决上述安全风险,Kmesh计划引入节点数据加密模式,为节点之间的通信流量进行加密,消除通讯过程中的安全风险。 - -## 2.使用场景 - -由Kmesh进行代理的节点,在数据从应用发出时,路由到指定的网络接口设备进行加密处理后再经过网络发送给对端。对端由特定的网络接口设备接收到数据后进行解密,上送给对应的服务应用。 - -![alt text](./pics/p2p_encryption.png) - -## 3.IPsec简介 - -IPsec是一个保护IP层通信的安全保密架构,是一个协议簇,通过对IP协议的分组进行加密和认证来保护IP协议的网络传输协议簇。运行在OSI模型的第三层(Internet Protocol,IP层),在VPN(virtual private networks)应用很广泛。 -有关IPsec的更多描述请参阅[什么是IPsec](https://info.support.huawei.com/info-finder/encyclopedia/zh/IPsec.html) - -## 4.Kmesh集成IPSec作为节点之间的加密工具 - -Kmesh仅使用IPSec的加密功能,IPSec的预共享密钥由用户设置在K8s后,传递至Kmesh进行管理并设置到IPSec中,保证IPSec的正常通信。整体架构图如下: - -![alt text](./pics/Kmesh_ipsec_workload.png) - -### 4.1 用户设置IPSec密钥 - -用户通过kmeshctl向K8s中设置名称为Kmesh-ipsec-keys的secret类型资源,格式如下: - - kmeshctl secret --key= - -当前仅支持rfc4106 gcm aes (aead)算法,该资源中包含有ipsec使用的aead key,以及ipsec的icv长度 - -### 4.2 CRD设计 - -Kmesh使能ipsec时,需要精细化控制ipsec数据加密行为,这其中要求Kmesh具有节点之间的信息同步机制。当前主要场景基于云原生业务场景,信息同步机制基于K8s集群api-server构建,依赖Kmesh自定义结构体来完成数据存储。 - -CRD数据结构定义如下: - - apiVersion: apiextensions.k8s.io/v1 - kind: CustomResourceDefinition - metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.4 - name: kmeshnodeinfos.kmesh.net - spec: - group: kmesh.net - names: - kind: KmeshNodeInfo - listKind: KmeshNodeInfoList - plural: kmeshnodeinfos - singular: kmeshnodeinfo - scope: Namespaced - versions: - -- name: v1alpha1 - schema: - openAPIV3Schema: - description: KmeshNode is the Schema for the kmeshnodes API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: - type: string - metadata: - type: object - spec: - properties: - addresses: - description: |- - Addresses is used to store the internal ip address informatioon on the - host. The IP address information is used to generate the IPsec state - informatioon. IPsec uses this information to determine which network - adapter is used to encrypt and send data. - items: - type: string - type: array - bootID: - description: |- - bootid is used to generate the ipsec key. After the node is restarted, - the key needs to be updated. - type: string - podCIDRS: - description: |- - PodCIDRs used in IPsec checks the destination of the data to - determine which IPsec state is used for encryption. - items: - type: string - type: array - spi: - description: |- - The SPI is used to identify the version number of the current key. - The communication can be normal only when both communication parties - have spis and the spi keys are the same. - type: integer - required: - - addresses - - bootID - - podCIDRS - - spi - type: object - status: - type: object - type: object - served: true - storage: true - -### 4.3 Kmesh IPsec通信路径 - -![alt text](./pics/ipsec_traffic_path.png) - -流量数据路径上需要新增一张map以及两个tc程序 - -- 加密路径新增map: - | 类型 | lpm前缀树map(4.11版本引入内核) | - |:-------:|:-------| - | 作用 | 在流量编排时,判断发送的对端pod所在的节点是否被Kmesh接管了,只有当两边的pod都被Kmesh接管,才会被ipsec加密 | - | key | bpf_lpm_trie_key {u32 prefixlen; u8 data[0]}; | - | value | uint32 | - -- 新增2个tc: -在每个pod的容器出口网卡上新增一个tc程序,该tc程序用于将从pod中发出的流量打上mark,标记为走ipsec加密发出 - -在node网卡上新增tc程序,ipsec将数据包解密完成后进入tc程序,tc将数据包打上mark,转给对应的ipsec策略分发处理。如果没有这个tc程序,不在收包时打上mark,会导致非ipsec的数据包接收时出现丢包问题 - -### 4.4 Kmesh IPSec操作 - -**规格限制** - -- 由于ipsec规则匹配时使用了mark标记,所以请保证当前环境中mark不会出现冲突 - - - 加密时使用的mark如下:0x000000e0,mask :0xffffffff - - 解密时使用的mark如下:0x000000d0,mask :0xffffffff - - 请勿与该mark使用相同的bit,导致数据包识别错误 - -- 数据从客户端发送时不能在iptables中为需要加密的流量开启地址伪装(masq)选项。地址伪装会使用snat技术,在服务端收到的ipsec数据包中,将流量src_ip伪装成nodeid,导致服务端ipsec无法正确匹配,数据包被丢弃 - -**Kmesh-daemon启动时,完成以下动作:** - -- 从Kmesh-daemon读取secret信息并解析存储以下关键信息: - | 名称 | 作用 | - |:-------:|:-------| - | spi | 加密密钥的序列号,由kmeshctl secret自动生成spi | - | aead-algo | 密钥算法,当前仅支持rfc4106(gcm(aes)) | - | aead-key | 预共享密钥,所有的节点间的ipsec密钥从此密钥通过特定算法进行派生 | - | icv-len | 密钥长度 | - -- 获取本端的如下信息: - | 名称 | 作用 | - |:-------:|:-------| - | 本端的PodCIDR | 用于生成ipsec规则 | - | 本端的集群内部ip地址 | 用于生成nodeid,ipsec规则 | - | bootid | 启动id | - -- 从api-server中读取出所有kmeshNodeInfo节点信息,节点信息包含各node当前name,使用的spi版本号、ipsec设备的ip地址、bootID信息并开始生成ipsec规则,每个对端node需要生成2条state(一进一出),3条policy(out、in、fwd)。密钥从预共享密钥中进行派生,规则如下: - -出口密钥: 预共享密钥+本机IP+对端IP+本机bootid+对端bootID,hash后截取aead密钥长度 - -入口密钥: 预共享密钥+对端IP+本机IP+对端bootid+本机bootID,hash后截取aead密钥长度 - - ipsec示例:本机ip地址为7.6.122.84,获取到对端的node ip 地址信息为7.6.122.220,设置ipsec配置预览如下 - -# state配置 - - ip xfrm state add src 7.6.122.84 dst 7.6.122.220 proto esp spi 0x1 mode tunnel reqid 1 {\$aead-algo} {\$aead-出口密钥} {\$icv-len} - ip xfrm state add src 7.6.122.220 dst 7.6.122.84 proto esp spi 0x1 mode tunnel reqid 1 {\$aead-algo} {\$aead-入口密钥} {\$icv-len} - -# policy配置 - - ip xfrm policy add src 0.0.0.0/0 dst {\$对端CIDR} dir out tmpl src 7.6.122.84 dst 7.6.122.220 proto esp spi 0x1 reqid 1 mode tunnel mark 0x000000e0 mask 0xffff - ip xfrm policy add src 0.0.0.0/0 dst {\$本端CIDR} dir in tmpl src 7.6.122.220 dst 7.6.122.84 proto esp reqid 1 mode tunnel mark 0x000000d0 mask 0xfffffff - ip xfrm policy add src 0.0.0.0/0 dst {\$本端CIDR} dir fwd tmpl src 7.6.122.220 dst 7.6.122.84 proto esp reqid 1 mode tunnel mark 0x000000d0 mask 0xfffffff - -- 更新lpm前缀树map,key为对端CIDR地址,value当前全部设置为1,tc根据目标pod ip在前缀树找到记录,确定对端pod为Kmesh纳管,为流量打上对应的加密、解密标签 -- Kmesh-daemon将本端的spi、IPsec设备ip、podCIDRs更新到api-server中,触发其他节点更新机器上的IPsec配置 - -**Kmesh-daemon检测到node节点新增时:** - -新增节点:可参考上一章节[Kmesh-daemon启动时,完成以下动作:] - -其他节点: - -- 新增节点将自己的kmeshNodeInfo信息上传api-server后,说明新增节点上IPsec规则已准备好 -- 本端需要创建ipsec in/fwd/out方向的state、policy规则 -- 本端更新map表,将对应的CIDR更新到lpm map中 - -**Kmesh-daemon退出时,完成以下动作:** - -退出节点: - -- 清理api-server中的本node的kmeshNodeInfo信息 -- 清理当前node上ipsec的state、policy信息 -- 卸载tc程序 -- 清理lpm数据 - -其他节点: - -- 本端删除退出节点的IPsec state、policy信息 -- 本端清理退出节点的lpm CIDR数据 - -**secret更新时,完成以下动作:** - -更新节点: - -- Kmesh检测到当前secret更新后,需要对IPsec规则进行全量扫描更新 -- 遍历kmeshNodeInfo信息,执行以下动作: - - 如果对端的secret spi版本在本端记录的当前、历史spi中没有查询到,则什么也不做(无spi则缺失预共享密钥,无法生成密钥),可能是对端的spi比本端高,则等待下次secret更新时再触发更新 - - 使用新的spi创建所有到对端的in、fwd方向state,in/fwd方向policy支持多版本密钥解析,无需更新。 - - 如果对端的secret spi版本小于等于本端的secret spi,则创建out方向新的state,更新out方向的policy中spi到最新的spi版本 - - 如果对端的secret spi版本大于本端的secret spi,说明本端spi版本落后,等待secret版本更新时再生成out方向的state以及policy -- 更新自己的kmeshNodeInfo到api-server中 - -其他节点: - -- 本端从api-server中读取到kmeshNodeInfo更新后,执行以下动作: - - 如果对端的secret spi版本在本端记录的当前、历史spi中没有查询到,则什么也不做(无spi则缺失预共享密钥,无法生成密钥),可能是对端的spi比本端高,则等待下次secret更新时再触发更新。也可能是对端的版本过低,低于本端Kmesh启动时的spi版本号,等待对端spi版本更新后再出发本端更新 - - 使用新的spi创建所有到对端的in、fwd方向state,in/fwd方向policy支持多版本密钥解析,无需更新 - - 如果对端的secret spi版本小于等于本端的secret spi,则创建out方向新的state,更新out方向的policy中spi到最新的spi版本 - - 如果对端的secret spi版本大于本端的secret spi,说明本端spi版本落后,等待secret版本更新时再生成out方向的state以及policy +--- +title: Kmesh Supports Data Encryption Between Nodes +authors: +- "@bitcoffeeiux" +reviews: +- +approves: +- + +create-date: 2024-10-10 + +--- + +## 1. Background + +With the increase in network security threats, unencrypted data is easily eavesdropped, intercepted, or even tampered with by hackers or third parties during transmission, leading to the leakage of sensitive information. To address the above security risks, Kmesh plans to introduce a node data encryption mode to encrypt communication traffic between nodes, eliminating security risks during communication. + +## 2. Usage Scenarios + +Nodes proxied by Kmesh, when data is sent from the application, are routed to a specified network interface device for encryption processing and then sent to the peer over the network. The peer receives the data through a specific network interface device, decrypts it, and sends it to the corresponding service application. + +![alt text](./pics/p2p_encryption.png) + +## 3. IPsec Introduction + +IPsec is a security architecture that protects IP layer communication. It is a protocol suite that protects network transmission protocols of the IP protocol by encrypting and authenticating IP protocol packets. It operates at the third layer of the OSI model (Internet Protocol, IP layer) and is widely used in VPN (virtual private networks) applications. +For more information about IPsec, please refer to [What is IPsec](https://info.support.huawei.com/info-finder/encyclopedia/zh/IPsec.html) + +## 4. Kmesh Integrates IPSec as an Encryption Tool Between Nodes + +Kmesh only uses the encryption function of IPSec. The pre-shared key of IPSec is set by the user in K8s, passed to Kmesh for management, and set in IPSec to ensure normal communication of IPSec. The overall architecture diagram is as follows: + +![alt text](./pics/Kmesh_ipsec_workload.png) + +### 4.1 User Sets IPSec Key + +Users set a secret type resource named Kmesh-ipsec-keys in K8s through kmeshctl, in the following format: + + kmeshctl secret --key= + +Currently, only the rfc4106 gcm aes (aead) algorithm is supported. This resource contains the aead key used by ipsec and the icv length of ipsec. + +### 4.2 CRD Design + +When Kmesh enables ipsec, it needs to finely control the ipsec data encryption behavior, which requires Kmesh to have an information synchronization mechanism between nodes. The current main scenario is based on the cloud-native business scenario, and the information synchronization mechanism is based on the K8s cluster api-server, relying on the Kmesh custom structure to complete data storage. + +CRD data structure definition is as follows: + + apiVersion: apiextensions.k8s.io/v1 + kind: CustomResourceDefinition + metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: kmeshnodeinfos.kmesh.net + spec: + group: kmesh.net + names: + kind: KmeshNodeInfo + listKind: KmeshNodeInfoList + plural: kmeshnodeinfos + singular: kmeshnodeinfo + scope: Namespaced + versions: + +- name: v1alpha1 + schema: + openAPIV3Schema: + description: KmeshNode is the Schema for the kmeshnodes API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: + type: string + metadata: + type: object + spec: + properties: + addresses: + description: |- + Addresses is used to store the internal ip address informatioon on the + host. The IP address information is used to generate the IPsec state + informatioon. IPsec uses this information to determine which network + adapter is used to encrypt and send data. + items: + type: string + type: array + bootID: + description: |- + bootid is used to generate the ipsec key. After the node is restarted, + the key needs to be updated. + type: string + podCIDRS: + description: |- + PodCIDRs used in IPsec checks the destination of the data to + determine which IPsec state is used for encryption. + items: + type: string + type: array + spi: + description: |- + The SPI is used to identify the version number of the current key. + The communication can be normal only when both communication parties + have spis and the spi keys are the same. + type: integer + required: + - addresses + - bootID + - podCIDRS + - spi + type: object + status: + type: object + type: object + served: true + storage: true + +### 4.3 Kmesh IPsec Communication Path + +![alt text](./pics/ipsec_traffic_path.png) + +A map and two tc programs need to be added to the traffic data path + +- New map for encryption path: + | Type | lpm prefix tree map (introduced in kernel version 4.11) | + |:-------:|:-------| + | Function | When traffic is orchestrated, it determines whether the node where the sending peer pod is located is managed by Kmesh. Only when both pods are managed by Kmesh will it be encrypted by ipsec | + | key | bpf_lpm_trie_key {u32 prefixlen; u8 data[0]}; | + | value | uint32 | +- Add 2 tc: +Add a tc program to the container egress network card of each pod. This tc program is used to mark the traffic sent from the pod and mark it as going through ipsec encryption. + +Add a tc program to the node network card. After ipsec decrypts the data packet, it enters the tc program. The tc marks the data packet and forwards it to the corresponding ipsec policy for distribution. If this tc program is not used to mark the data packet when receiving it, it will cause packet loss when receiving non-ipsec data packets. + +### 4.4 Kmesh IPSec Operation + +**Specification Restrictions** + +- Since the mark is used when matching ipsec rules, please ensure that there are no conflicts in the current environment + + - The mark used for encryption is: 0x000000e0, mask :0xffffffff + - The mark used for decryption is: 0x000000d0, mask :0xffffffff + - Do not use the same bit as this mark, which will cause data packet identification errors + +- When data is sent from the client, do not enable the address masquerade (masq) option for the traffic that needs to be encrypted in iptables. Address masquerade will use snat technology to masquerade the traffic src_ip into nodeid in the ipsec data packet received by the server, causing the server ipsec to fail to match correctly and the data packet to be discarded + +**When Kmesh-daemon starts, it completes the following actions:** + +- Read secret information from Kmesh-daemon and parse and store the following key information: + | Name | Function | + |:-------:|:-------| + | spi | The serial number of the encryption key, automatically generated by kmeshctl secret | + | aead-algo | Key algorithm, currently only supports rfc4106(gcm(aes)) | + | aead-key | Pre-shared key, all ipsec keys between nodes are derived from this key through a specific algorithm | + | icv-len | Key length | + +- Obtain the following information from the local end: + | Name | Function | + |:-------:|:-------| + | Local PodCIDR | Used to generate ipsec rules | + | Local cluster internal ip address | Used to generate nodeid, ipsec rules | + | bootid | Startup id | + +- Read all kmeshNodeInfo node information from the api-server. The node information includes the current name of each node, the spi version number used, the ip address of the ipsec device, and bootID information, and start generating ipsec rules. Each peer node needs to generate 2 states (one in and one out), 3 policies (out, in, fwd). The key is derived from the pre-shared key, and the rules are as follows: + +Egress key: Pre-shared key + local IP + peer IP + local bootid + peer bootID, hash and then intercept the aead key length + +Ingress key: Pre-shared key + peer IP + local IP + peer bootid + local bootID, hash and then intercept the aead key length + +ipsec example: The local ip address is 7.6.122.84, and the peer node ip address information obtained is 7.6.122.220. The ipsec configuration preview is set as follows + +# state configuration + + ip xfrm state add src 7.6.122.84 dst 7.6.122.220 proto esp spi 0x1 mode tunnel reqid 1 {\$aead-algo} {\$aead-出口密钥} {\$icv-len} + ip xfrm state add src 7.6.122.220 dst 7.6.122.84 proto esp spi 0x1 mode tunnel reqid 1 {\$aead-algo} {\$aead-入口密钥} {\$icv-len} + +# policy configuration + + ip xfrm policy add src 0.0.0.0/0 dst {\$对端CIDR} dir out tmpl src 7.6.122.84 dst 7.6.122.220 proto esp spi 0x1 reqid 1 mode tunnel mark 0x000000e0 mask 0xffff + ip xfrm policy add src 0.0.0.0/0 dst {\$本端CIDR} dir in tmpl src 7.6.122.220 dst 7.6.122.84 proto esp reqid 1 mode tunnel mark 0x000000d0 mask 0xfffffff + ip xfrm policy add src 0.0.0.0/0 dst {\$本端CIDR} dir fwd tmpl src 7.6.122.220 dst 7.6.122.84 proto esp reqid 1 mode tunnel mark 0x000000d0 mask 0xfffffff + +- Update the lpm prefix tree map, the key is the peer CIDR address, the value is currently set to 1, tc finds the record in the prefix tree according to the target pod ip, determines that the peer pod is managed by Kmesh, and marks the traffic with the corresponding encryption and decryption labels +- Kmesh-daemon updates the local spi, IPsec device ip, and podCIDRs to the api-server, triggering other nodes to update the IPsec configuration on the machine + +**When Kmesh-daemon detects a new node node:** + +New node: Refer to the previous chapter [When Kmesh-daemon starts, it completes the following actions:] + +Other nodes: + +- After the new node uploads its kmeshNodeInfo information to the api-server, it indicates that the IPsec rules on the new node are ready +- The local end needs to create state and policy rules for ipsec in/fwd/out directions +- The local end updates the map table and updates the corresponding CIDR to the lpm map + +**When Kmesh-daemon exits, it completes the following actions:** + +Exit node: +- Clear the kmeshNodeInfo information of this node in the api-server +- Clear the ipsec state and policy information on the current node +- Uninstall the tc program +- Clear lpm data + +Other nodes: +- The local end deletes the IPsec state and policy information of the exit node +- The local end clears the lpm CIDR data of the exit node + +**When the secret is updated, the following actions are completed:** + +Update node: +- After Kmesh detects that the current secret is updated, it needs to perform a full scan update of the IPsec rules +- Traverse the kmeshNodeInfo information and perform the following actions: + - If the peer's secret spi version is not found in the current and historical spi recorded locally, then do nothing (no spi means the pre-shared key is missing, and the key cannot be generated). It may be that the peer's spi is higher than the local end, so wait for the next secret update to trigger the update + - Use the new spi to create all in and fwd direction states to the peer, and in/fwd direction policies support multi-version key parsing without updating. + - If the peer's secret spi version is less than or equal to the local secret spi, create a new state in the out direction and update the spi in the out direction policy to the latest spi version + - If the peer's secret spi version is greater than the local secret spi, it means that the local spi version is behind, and wait for the secret version update to generate the state and policy in the out direction +- Update your own kmeshNodeInfo to the api-server + +Other nodes: +- After the local end reads the kmeshNodeInfo update from the api-server, perform the following actions: + - If the peer's secret spi version is not found in the current and historical spi recorded locally, then do nothing (no spi means the pre-shared key is missing, and the key cannot be generated). It may be that the peer's spi is higher than the local end, so wait for the next secret update to trigger the update. It may also be that the peer's version is too low, lower than the spi version number when the local Kmesh started, and wait for the peer's spi version to be updated before triggering the local update + - Use the new spi to create all in and fwd direction states to the peer, and in/fwd direction policies support multi-version key parsing without updating + - If the peer's secret spi version is less than or equal to the local secret spi, create a new state in the out direction and update the spi in the out direction policy to the latest spi version + - If the peer's secret spi version is greater than the local secret spi, it means that the local spi version is behind, and wait for the secret version update to generate the state and policy in the out direction diff --git a/docs/proposal/kmesh_support_encrypt_zh.md b/docs/proposal/kmesh_support_encrypt_zh.md new file mode 100644 index 000000000..796914510 --- /dev/null +++ b/docs/proposal/kmesh_support_encrypt_zh.md @@ -0,0 +1,113 @@ +--- +title: Kmesh 加密支持 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh 加密支持 + +## 摘要 + +本文档描述了 Kmesh 的加密支持方案,包括数据加密、密钥管理和安全通信等功能。 + +## 背景 + +在微服务架构中,数据安全至关重要。Kmesh 需要提供完善的加密支持能力,以保护服务间的通信安全。 + +## 目标 + +1. 实现数据加密传输 +2. 提供密钥管理机制 +3. 支持多种加密算法 +4. 确保性能和安全性平衡 + +## 设计细节 + +### 架构设计 + +加密支持系统包含以下组件: + +1. 加密管理器 +2. 密钥管理器 +3. 证书管理器 +4. 安全通道 + +### 数据结构 + +```c +struct EncryptConfig { + __u32 algorithm; // 加密算法 + __u32 key_size; // 密钥长度 + __u32 mode; // 加密模式 + __u32 padding; // 填充方式 +}; + +struct SecurityContext { + __u32 protocol; // 安全协议 + __u32 auth_method; // 认证方法 + __u32 cipher_suite; // 密码套件 + __u32 key_exchange; // 密钥交换 +}; +``` + +### 加密接口 + +```go +type EncryptionManager interface { + Encrypt(data []byte, config *EncryptConfig) ([]byte, error) + Decrypt(data []byte, config *EncryptConfig) ([]byte, error) + GenerateKey(config *EncryptConfig) ([]byte, error) + RotateKey(keyID string) error +} +``` + +## 使用示例 + +### 配置加密 + +```yaml +apiVersion: security.kmesh.io/v1 +kind: EncryptionPolicy +metadata: + name: example-policy +spec: + algorithm: AES-256-GCM + keyRotation: + interval: 24h + enabled: true + targets: + - service: payment + ports: [8080] +``` + +### 管理密钥 + +```bash +# 生成新密钥 +kmesh key generate --algorithm=AES-256 + +# 轮换密钥 +kmesh key rotate --policy=example-policy + +# 查看密钥状态 +kmesh key status +``` + +## 注意事项 + +1. 密钥安全存储 +2. 性能开销控制 +3. 合规性要求 + +## 未来工作 + +1. 支持更多加密算法 +2. 优化性能 +3. 增强安全性 diff --git a/docs/proposal/kmesh_support_localityLB_zh.md b/docs/proposal/kmesh_support_localityLB_zh.md new file mode 100644 index 000000000..d46d2b8e0 --- /dev/null +++ b/docs/proposal/kmesh_support_localityLB_zh.md @@ -0,0 +1,86 @@ +--- +title: Kmesh 的本地性负载均衡 +authors: +- "@derekwin" +reviewers: +- "@kwb0523" +- "@hzxuzhonghu" +approvers: +- "@robot" +- TBD + +creation-date: 2024-06-07 +--- + +# Kmesh 的本地性负载均衡 + +## 摘要 + +为 Kmesh 工作负载模式添加本地性负载均衡。 + +## 背景 + +目前,Kmesh 不支持本地性感知负载均衡。本地性负载均衡通过将流量导向最近的服务实例来优化分布式系统中的性能和可靠性。这种方法减少了延迟,提高了可用性,并降低了与跨区域数据传输相关的成本。它还确保了符合数据主权法规,并通过提供更快、更可靠的服务响应来改善整体用户体验。 + +## 目标 + +本提案的目的是为 kmesh 工作负载模式添加本地性感知负载均衡能力,对应于 istio ambient mesh 中的本地性负载均衡。 + +## 提案 + +本地性负载均衡模式包括:本地性故障转移和本地性严格模式。 + +### 本地性故障转移模式 + +当请求访问服务时,控制平面将对流量的源 pod 的本地性信息与服务背后所有健康后端的本地性进行分层匹配。匹配度更高的 Pod 表示它们在地理位置上更接近,流量将优先路由到匹配度更高的 Pod。 + +### 本地性严格模式 + +在本地性严格模式下,LB(负载均衡)算法将仅选择与 routingPreference 完全匹配的后端。这意味着在这种模式下,负载均衡器会强制执行严格的策略,仅根据与指定本地性偏好的完全匹配将流量路由到后端,从而确保请求由满足与其位置或其他属性相关的特定标准的服务器处理。 + +## 设计细节 + +### 实现细节 + +1. 在 BPF 侧的 `service_manager` 中实现新的负载均衡处理逻辑:`lb_locality_failover_handle` +2. 向 BPF 侧的数据结构添加必要信息: + - map `service_value` 存储负载均衡策略 `lb_policy` 和数组 `prio_endpoint_count[PRIO_COUNT]` + - map `endpoint_key` 存储当前端点的优先级 `prio` +3. 在用户侧添加 `locality_cache` 模块,用于存储本地性感知信息和优先级计算逻辑 +4. 更新用户侧的 `ServiceValue` 和 `EndpointKey` map + +### 数据结构 + +#### workload.h + +```c +typedef struct { + __u32 prio_endpoint_count[PRIO_COUNT]; + __u32 lb_policy; + __u32 service_port[MAX_PORT_COUNT]; + __u32 target_port[MAX_PORT_COUNT]; + struct ip_addr wp_addr; + __u32 waypoint_port; +} service_value; + +typedef struct { + __u32 service_id; + __u32 prio; + __u32 backend_index; +} endpoint_key; +``` + +#### workload_common.h + +```c +typedef enum { + LB_POLICY_RANDOM = 0, + LB_POLICY_STRICT = 1, + LB_POLICY_FAILOVER = 2, +} lb_policy_t; +``` + +### 控制流 + +![locality_lb](pics/locality_lb.svg) + diff --git a/docs/proposal/kmesh_support_workload_zh.md b/docs/proposal/kmesh_support_workload_zh.md new file mode 100644 index 000000000..efb149c6d --- /dev/null +++ b/docs/proposal/kmesh_support_workload_zh.md @@ -0,0 +1,252 @@ +--- +title: Kmesh 工作负载支持 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh 工作负载支持 + +## 摘要 + +本文档描述了 Kmesh 对工作负载的支持方案,包括工作负载发现、管理和监控等功能。 + +## 背景 + +在微服务架构中,工作负载是基本的部署和运行单元。Kmesh 需要提供完善的工作负载支持能力,以实现服务网格的功能。 + +## 目标 + +1. 实现工作负载自动发现 +2. 提供工作负载生命周期管理 +3. 支持工作负载监控 +4. 实现负载均衡 + +## 设计细节 + +### 架构设计 + +工作负载支持系统包含以下组件: + +1. 工作负载发现器 +2. 生命周期管理器 +3. 监控系统 +4. 负载均衡器 + +### 数据结构 + +```c +struct Workload { + __u32 id; // 工作负载 ID + __u32 type; // 工作负载类型 + __u32 status; // 运行状态 + __u32 port; // 服务端口 + struct ip_addr address; // IP 地址 +}; + +struct WorkloadConfig { + __u32 max_connections; // 最大连接数 + __u32 timeout; // 超时时间 + __u32 retry_count; // 重试次数 + __u32 load_balance; // 负载均衡策略 +}; +``` + +### 管理接口 + +```go +type WorkloadManager interface { + RegisterWorkload(workload *Workload) error + UnregisterWorkload(id uint32) error + UpdateWorkload(workload *Workload) error + GetWorkload(id uint32) (*Workload, error) + ListWorkloads() ([]*Workload, error) +} +``` + +## 使用示例 + +### 注册工作负载 + +```yaml +apiVersion: v1 +kind: Workload +metadata: + name: example-workload +spec: + type: service + port: 8080 + config: + max_connections: 1000 + timeout: 30s + retry_count: 3 + load_balance: round_robin +``` + +### 管理工作负载 + +```bash +# 查看工作负载列表 +kmesh workload list + +# 查看工作负载详情 +kmesh workload describe example-workload + +# 更新工作负载配置 +kmesh workload update example-workload --max-connections=2000 +``` + +## 注意事项 + +1. 资源限制 +2. 安全策略 +3. 性能优化 + +## 未来工作 + +1. 支持更多工作负载类型 +2. 优化资源管理 +3. 增强监控能力 + +## 与 L4 流量治理相关的 Workload 字段 + +### Address + +```go// +type Address struct { + // Types that are assignable to Type: + // *Address_Workload + // *Address_Service + Type isAddress_Type `protobuf_oneof:"type"` +} +``` + +### Service + +```go// +type Service struct { + // The service name for Kubernetes, such as: "fortio-server", "Kubernetes", "istiod", "kube-dns" etc. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The namespace the service belongs to,such as: "default", "kube-system", "istio-system" etc. + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + // Hostname represents the FQDN of the service. + // For Kubernetes,this would be ..svc., such as: "fortio-server.default.svc.cluster.local", "istiod.istio-system.svc.cluster.local" etc. + Hostname string `protobuf:"bytes,3,opt,name=hostname,proto3" json:"hostname,omitempty"` + // Address represents the addresses the service can be reached at. + // There may be multiple addresses for a single service if it resides in multiple networks, + // multiple clusters, and/or if it's dual stack (TODO: support dual stack). + // For a headless kubernetes service, this list will be empty. + Addresses []*NetworkAddress `protobuf:"bytes,4,rep,name=addresses,proto3" json:"addresses,omitempty"` + // Ports for the service. + // The target_port may be overridden on a per-workload basis. + Ports []*Port `protobuf:"bytes,5,rep,name=ports,proto3" json:"ports,omitempty"` +} +``` + +### Workload + +```go +type Workload struct { + // UID represents a globally unique opaque identifier for this workload, such as: "Kubernetes//Pod/default/fortio-server-deployment-59f95d774d-85nr4" + Uid string `protobuf:"bytes,20,opt,name=uid,proto3" json:"uid,omitempty"` + // Name represents the name for the workload, For Kubernetes, this is the pod name, such as: "fortio-server-deployment-59f95d774d-ljmd5" + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Namespace represents the namespace for the workload. + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + // Address represents the IPv4/IPv6 address for the workload, this should be globally unique. + Addresses [][]byte `protobuf:"bytes,3,rep,name=addresses,proto3" json:"addresses,omitempty"` + // The services for which this workload is an endpoint. the key is the NamespacedHostname string of the format namespace/hostname. + Services map[string]*PortList `protobuf:"bytes,22,rep,name=services,proto3" json:"services,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Health status of the workload,such as: "Healthy","Unhealthy" + Status WorkloadStatus `protobuf:"varint,17,opt,name=status,proto3,enum=istio.workload.WorkloadStatus" json:"status,omitempty"` +} +``` + +注意:以上关于 workload 模型的配置与基本网络功能相关,不涉及 TLS 或加密相关的配置。这部分内容将在补充 workload 的完整功能的过程中添加。 + +## Kmesh 如何订阅和使用 workload 模型信息 + +1. kmesh 的 xds 客户端通过 Delta 方式从 Istiod 订阅 workload 模型,type_url 为:"type.googleapis.com/istio.workload.Address"; +2. Address 类型的 workload 数据分为两个子资源:Service 和 Workload,它们被响应给 kmesh,然后被解析并转换为内部结构,存储在 bpf map 中; + +![kmesh subscribe workload](./pics/kmesh_workload_subscribe.svg) + +在 kmesh 的后续流量管理中,基于客户端访问的 IP 和 Port,从 BPF map 中找到相应的服务及其端点,然后随机选择一个端点将请求转发到该端点; + +## Kmesh BPF map 数据结构定义 + +```C +// frontend map +typedef struct +{ + __be32 ipv4; // service ip +} frontend_key; + +typedef struct +{ + __u32 upstream_id; // service id for Service access or backend uid for Pod access. +} frontend_value; + +// service map +typedef struct +{ + __u32 service_id; // service id, through / string convert to uint32 variable +} service_key; + +typedef struct +{ + __u32 endpoint_count; // endpoint count of current service + __u32 lb_policy; // load balancing algorithm + __u32 service_port[MAX_PORT_COUNT]; // service_port[i] and target_port[i] are a pair, i starts from 0 and max value + // is MAX_PORT_COUNT-1 + __u32 target_port[MAX_PORT_COUNT]; + __u32 waypoint_addr; + __u32 waypoint_port; +} service_value; + +// endpoint map +typedef struct +{ + __u32 service_id; // service id, through / string convert to uint32 variable + __u32 backend_index; // backend index,The relationship of backend_index and endpoint_count:if endpoint_count is 3,then backend_index can be 1/2/3; +} endpoint_key; + +typedef struct +{ + __u32 backend_uid; // backend uid, through workload_uid string convert to uint32 variable +} endpoint_value; + +// backend map +typedef struct +{ + __u32 backend_uid; // backend uid, through workload_uid string convert to uint32 variable +} backend_key; + +typedef struct +{ + __be32 ipv4; // backend ip + __u32 service[MAX_SERVICE_COUNT]; + __u32 waypoint_addr; + __u32 waypoint_port; +} backend_value; + +``` + +## 流量治理过程 + +

+ +

+ +**流量治理过程** + +- 基于客户端访问的 IP 搜索 frontend map,找到对应的 upstream_id,然后使用该 upstream_id 搜索 service map 和 backend map: + - 如果在 service map 中找到对应的服务,并获取服务中后端 Pod 的 endpoint_count。然后,基于 service_id 和基于计数生成的随机 backend_index 搜索 endpoint map,以找到对应的 backend_uid。最后,使用 backenduid 找到后端的 IP 和 Port。 + - 如果在 backend map 中找到对应的后端,则为直接 pod 访问。 +- 此外,如果服务或后端包含 waypoint,它将重定向到 waypoint。 diff --git a/docs/proposal/layer4_authorization_zh.md b/docs/proposal/layer4_authorization_zh.md new file mode 100644 index 000000000..a75f826e1 --- /dev/null +++ b/docs/proposal/layer4_authorization_zh.md @@ -0,0 +1,136 @@ +--- +title: Kmesh 四层授权 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh 四层授权 + +## 摘要 + +本文档描述了 Kmesh 的四层授权设计方案,用于控制网络层面的访问权限。 + +## 背景 + +在微服务架构中,网络层面的访问控制是保障系统安全的重要环节。Kmesh 需要提供完善的四层授权机制,以实现细粒度的访问控制。 + +## 目标 + +1. 实现四层网络访问控制 +2. 支持基于身份的授权 +3. 提供灵活的策略配置 +4. 确保高性能和低延迟 + +## 设计细节 + +### 架构设计 + +四层授权系统包含以下组件: + +1. 策略管理器 +2. 身份验证器 +3. 访问控制器 +4. 审计日志记录器 + +### 授权策略 + +```yaml +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: tcp-policy + namespace: default +spec: + selector: + matchLabels: + app: tcp-echo + action: ALLOW + rules: + - from: + - source: + principals: ["cluster.local/ns/default/sa/sleep"] + to: + - operation: + ports: ["9000"] +``` + +### 实现细节 + +#### 策略结构 + +```c +struct AuthPolicy { + __u32 action; // ALLOW/DENY + __u32 source_id; // 源服务标识 + __u32 destination_id; // 目标服务标识 + __u32 port; // 端口号 +}; +``` + +#### 验证逻辑 + +```c +static __always_inline bool +check_authorization(struct AuthPolicy *policy, struct ctx_info *ctx) +{ + if (policy->action == DENY) { + return false; + } + + if (ctx->src_id != policy->source_id) { + return false; + } + + if (ctx->dst_id != policy->destination_id) { + return false; + } + + if (ctx->port != policy->port) { + return false; + } + + return true; +} +``` + +## 使用示例 + +### 配置授权策略 + +```bash +# 应用授权策略 +kubectl apply -f tcp-policy.yaml + +# 查看策略状态 +kubectl get authorizationpolicy +``` + +### 验证访问控制 + +```bash +# 测试允许的访问 +curl tcp-echo:9000 + +# 测试被拒绝的访问 +curl tcp-echo:9001 +``` + +## 注意事项 + +1. 策略优先级处理 +2. 性能影响控制 +3. 错误处理机制 + +## 未来工作 + +1. 支持更多授权规则 +2. 优化策略评估性能 +3. 增强审计日志功能 + diff --git a/docs/proposal/local_ratelimit_zh.md b/docs/proposal/local_ratelimit_zh.md new file mode 100644 index 000000000..a7f52a8fe --- /dev/null +++ b/docs/proposal/local_ratelimit_zh.md @@ -0,0 +1,121 @@ +--- +title: Kmesh 本地限流 +authors: +- "@luoyunhe" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh 本地限流 + +## 摘要 + +本文档描述了 Kmesh 的本地限流功能设计和实现。 + +## 背景 + +在微服务架构中,限流是保护服务不被过载的重要机制。本地限流作为一种基础的限流方式,可以有效地控制单个服务实例的请求量。 + +## 目标 + +1. 实现基于令牌桶算法的本地限流 +2. 支持多种限流粒度(全局、路由级别) +3. 提供灵活的限流配置接口 + +## 设计细节 + +### 架构设计 + +本地限流模块主要包含以下组件: + +1. 限流配置管理器 +2. 令牌桶实现 +3. 限流决策器 + +### 实现细节 + +#### 限流配置结构 + +```c +struct RateLimit { + __u32 tokens_per_fill; // 每次填充的令牌数 + __u32 fill_interval; // 填充间隔(毫秒) + __u32 max_tokens; // 最大令牌数 + __u32 tokens; // 当前令牌数 + __u64 last_fill_time; // 上次填充时间 +}; +``` + +#### 令牌桶实现 + +```c +static __always_inline bool consume_token(struct RateLimit *rl) +{ + __u64 now = bpf_ktime_get_ns() / 1000000; // 转换为毫秒 + __u64 elapsed = now - rl->last_fill_time; + + if (elapsed >= rl->fill_interval) { + __u32 fills = elapsed / rl->fill_interval; + __u32 new_tokens = fills * rl->tokens_per_fill; + + rl->tokens = min(rl->max_tokens, rl->tokens + new_tokens); + rl->last_fill_time = now; + } + + if (rl->tokens > 0) { + rl->tokens--; + return true; + } + + return false; +} +``` + +### 配置示例 + +```yaml +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: local-ratelimit +spec: + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + patch: + operation: INSERT_BEFORE + value: + name: envoy.filters.http.local_ratelimit + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit + stat_prefix: http_local_rate_limiter + token_bucket: + max_tokens: 10000 + tokens_per_fill: 1000 + fill_interval: 1s +``` + +## 使用说明 + +1. 配置限流规则 +2. 监控限流指标 +3. 调整限流参数 + +## 注意事项 + +1. 合理设置限流阈值 +2. 监控限流效果 +3. 定期评估和调整限流策略 + +## 未来工作 + +1. 支持更多限流算法 +2. 添加动态配置能力 +3. 增强监控和告警功能 + diff --git a/docs/proposal/map-in-map_management_enhancement-zh.md b/docs/proposal/map-in-map_management_enhancement-zh.md new file mode 100644 index 000000000..13c708aa9 --- /dev/null +++ b/docs/proposal/map-in-map_management_enhancement-zh.md @@ -0,0 +1,67 @@ +--- +title: map-in-map ������ǿ +authors: +- "@nlgwcy" +reviewers: +- "@hzxuzhonghu" +- "@supercharge-xsy" +- "@bitcoffeeiux" +approvers: +- "@robot" +- TBD + +creation-date: 2024-07-20 + +--- + +## map-in-map ������ǿ + +### ժҪ + +�� ads ģʽ�£�֧�ֻ��� map-in-map ��¼�ĵ�����������������ģ��Ⱥ�������������� + +### ���� + +���� [optimizing_bpf_map_update_in_xDS_mode](https://github.com/kmesh-net/kmesh/blob/main/docs/proposal/optimizing_bpf_map_update_in_xDS_mode-en.md) ���ᵽ�ģ�Ϊ�˽�� map-in-map ��¼���»��������⣬Kmesh ͨ���Կռ任ʱ��ķ�ʽ�����ʱһ���Դ������м�¼����С��ģ��Ⱥ�����²������������⣬���ǣ���֧�ִ��ģ��Ⱥ�����磬5000 ������� 100,000 �� Pod��ʱ��map-in-map ���ж���Ĵ�С�dz��󣬲��� `BPF_MAP_TYPE_ARRAY_OF_MAPS` ���͵� map ��֧�� `BPF_F_NO_PREALLOC`����ᵼ�´������ڴ��˷ѡ�����֧�� map-in-map ��¼�ĵ�����������������ģ��Ⱥ�������������� + +#### Ŀ�� + +- ֧�ִ��ģ��Ⱥ�е���������� +- �������ûָ������� + +### �᰸ + +Kmesh ���û�ģʽ�¹��� map-in-map ��ʹ�á�Ϊ��֧�ֵ�������������ṹ��չ���£� + +```c +struct inner_map_mng { + int inner_fd; + int outter_fd; + struct bpf_map_info inner_info; + struct bpf_map_info outter_info; + struct inner_map_stat inner_maps[MAX_OUTTER_MAP_ENTRIES]; + int elastic_slots[OUTTER_MAP_ELASTIC_SIZE]; + int used_cnt; // real used count + int alloced_cnt; // real alloced count + int max_alloced_idx; // max alloced index, there may be holes. + int init; + sem_t fin_tasks; + int elastic_task_exit; // elastic scaling thread exit flag +}; + +struct inner_map_stat { + int map_fd; + unsigned int used : 1; + unsigned int alloced : 1; + unsigned int resv : 30; +}; +``` + +Map-in-map �������̣� + +![map-in-map-elastic-process](pics/map-in-map-elastic-process.svg) + +������ map-in-map ���ݺ����ݵ�ʾ���� + +![map-in-map-elastic](pics/map-in-map-elastic.svg) + diff --git a/docs/proposal/observability_zh.md b/docs/proposal/observability_zh.md new file mode 100644 index 000000000..5e78f9066 --- /dev/null +++ b/docs/proposal/observability_zh.md @@ -0,0 +1,126 @@ +--- +title: Kmesh 可观测性提案 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh 可观测性提案 + +## 摘要 + +本文档描述了 Kmesh 的可观测性设计方案,包括指标收集、日志记录和分布式追踪等功能。 + +## 背景 + +可观测性是微服务架构中的关键能力,它帮助运维人员和开发者理解系统行为、诊断问题并优化性能。Kmesh 作为服务网格的重要组件,需要提供完善的可观测性能力。 + +## 目标 + +1. 提供全面的指标监控 +2. 实现分布式追踪 +3. 支持详细的日志记录 +4. 提供可视化界面 + +## 设计细节 + +### 架构设计 + +可观测性系统包含以下组件: + +1. 指标收集器 +2. 追踪收集器 +3. 日志收集器 +4. 数据存储 +5. 可视化界面 + +### 指标收集 + +#### 核心指标 + +```c +struct Metrics { + __u64 request_total; // 总请求数 + __u64 request_success; // 成功请求数 + __u64 request_failed; // 失败请求数 + __u64 latency_sum; // 延迟总和 + __u64 latency_count; // 延迟样本数 +}; +``` + +#### 指标类型 + +1. 请求指标 + - 请求数量 + - 成功率 + - 错误率 + +2. 性能指标 + - 延迟 + - 吞吐量 + - 资源使用率 + +### 分布式追踪 + +```go +type Span struct { + TraceID string + SpanID string + ParentID string + ServiceName string + StartTime time.Time + EndTime time.Time + Tags map[string]string +} +``` + +### 日志记录 + +```go +type LogEntry struct { + Timestamp time.Time + Level string + Message string + ServiceName string + TraceID string + SpanID string + Metadata map[string]interface{} +} +``` + +## 使用示例 + +### 指标查询 + +```bash +# 查询请求总数 +curl http://localhost:8080/metrics/request_total + +# 查询平均延迟 +curl http://localhost:8080/metrics/latency_avg +``` + +### 追踪查询 + +```bash +# 根据 TraceID 查询 +curl http://localhost:8080/traces/{traceId} +``` + +## 注意事项 + +1. 性能开销控制 +2. 数据存储容量 +3. 安全性考虑 + +## 未来工作 + +1. 支持更多指标类型 +2. 优化数据采集性能 +3. 增强分析能力 diff --git a/docs/proposal/optimizing_bpf_map_update_in_xDS_mode_zh.md b/docs/proposal/optimizing_bpf_map_update_in_xDS_mode_zh.md new file mode 100644 index 000000000..683a8aa0f --- /dev/null +++ b/docs/proposal/optimizing_bpf_map_update_in_xDS_mode_zh.md @@ -0,0 +1,120 @@ +--- +title: Kmesh BPF Map 更新优化 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh BPF Map 更新优化 + +## 摘要 + +本文档描述了在 xDS 模式下优化 BPF Map 更新的设计方案。 + +## 背景 + +在 xDS 模式下,BPF Map 的更新是一个频繁的操作,需要优化其性能以提高系统整体效率。 + +## 目标 + +1. 提高 BPF Map 更新效率 +2. 减少资源消耗 +3. 优化更新策略 +4. 保证数据一致性 + +## 设计细节 + +### 架构设计 + +BPF Map 更新优化系统包含以下组件: + +1. 更新管理器 +2. 缓存系统 +3. 批量处理器 +4. 监控组件 + +### 数据结构 + +```c +struct MapUpdateConfig { + __u32 batch_size; // 批量更新大小 + __u32 update_interval; // 更新间隔 + __u32 retry_count; // 重试次数 + __u32 timeout; // 超时时间 +}; + +struct MapUpdateStats { + __u64 total_updates; // 总更新次数 + __u64 successful_updates;// 成功更新次数 + __u64 failed_updates; // 失败更新次数 + __u64 retry_count; // 重试次数 +}; +``` + +### 更新接口 + +```go +type MapUpdater interface { + BatchUpdate(updates []MapUpdate) error + SingleUpdate(update MapUpdate) error + GetUpdateStats() (*MapUpdateStats, error) +} + +type MapUpdate struct { + MapID uint32 + Key interface{} + Value interface{} + Operation UpdateOperation +} +``` + +## 使用示例 + +### 配置更新 + +```yaml +map_update_config: + batch_size: 100 + update_interval: 1s + retry_count: 3 + timeout: 5s +``` + +### 执行更新 + +```go +updater := NewMapUpdater(config) +updates := []MapUpdate{ + { + MapID: 1, + Key: key1, + Value: value1, + Operation: UPDATE, + }, + { + MapID: 2, + Key: key2, + Value: value2, + Operation: DELETE, + }, +} +err := updater.BatchUpdate(updates) +``` + +## 注意事项 + +1. 并发控制 +2. 错误处理 +3. 性能监控 + +## 未来工作 + +1. 支持更多更新策略 +2. 优化批量处理 +3. 增强监控能力 diff --git a/docs/proposal/performance_monitoring_zh.md b/docs/proposal/performance_monitoring_zh.md new file mode 100644 index 000000000..6a697d5ec --- /dev/null +++ b/docs/proposal/performance_monitoring_zh.md @@ -0,0 +1,2477 @@ +--- +title: Kmesh 性能监控 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh 性能监控 + +## 摘要 + +本文档描述了 Kmesh 的性能监控设计方案,包括性能指标收集、分析和可视化。 + +## 背景 + +性能监控对于保证服务质量和及时发现性能瓶颈至关重要。Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +## 目标 + +1. 收集关键性能指标 +2. 提供实时性能分析 +3. 支持性能数据可视化 +4. 实现性能告警机制 + +## 设计细节 + +### 架构设计 + +性能监控系统包含以下组件: + +1. 性能数据采集器 +2. 数据处理器 +3. 存储系统 +4. 可视化界面 +5. 告警系统 + +### 性能指标 + +#### 系统指标 + +```c +struct SystemMetrics { + __u64 cpu_usage; // CPU 使用率 + __u64 memory_usage; // 内存使用量 + __u64 disk_io; // 磁盘 IO + __u64 network_io; // 网络 IO +}; +``` + +#### 服务指标 + +```c +struct ServiceMetrics { + __u64 request_latency; // 请求延迟 + __u64 throughput; // 吞吐量 + __u64 error_rate; // 错误率 + __u64 concurrent_conn; // 并发连接数 +}; +``` + +### 数据采集 + +```go +type Collector interface { + CollectMetrics() (*Metrics, error) + CollectLogs() (*Logs, error) + CollectTraces() (*Traces, error) +} +``` + +## 使用示例 + +### 查询性能指标 + +```bash +# 查询 CPU 使用率 +curl http://localhost:8080/metrics/cpu_usage + +# 查询服务延迟 +curl http://localhost:8080/metrics/service_latency +``` + +### 配置告警规则 + +```yaml +alerts: + - name: high_cpu_usage + condition: cpu_usage > 80% + duration: 5m + severity: warning +``` + +## 注意事项 + +1. 性能开销控制 +2. 数据采样策略 +3. 存储容量规划 + +## 未来工作 + +1. 支持更多性能指标 +2. 优化数据采集效率 +3. 增强分析能力 + +## Kmesh 性能监控 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 + +Kmesh 需要提供全面的性能监控能力,以帮助用户了解系统性能状况。 + +### 性能监控 diff --git a/docs/proposal/tcp_long_connection_metrics_zh.md b/docs/proposal/tcp_long_connection_metrics_zh.md new file mode 100644 index 000000000..e25eb3cab --- /dev/null +++ b/docs/proposal/tcp_long_connection_metrics_zh.md @@ -0,0 +1,290 @@ +--- +title: Kmesh TCP 长连接指标 +authors: +- "@bitcoffeeiux" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# Kmesh TCP 长连接指标 + +## 摘要 + +本文档描述了 Kmesh 中 TCP 长连接指标的设计方案,用于监控和分析 TCP 长连接的性能和状态。 + +## 背景 + +TCP 长连接在微服务架构中广泛使用,需要有效的监控机制来保证其稳定性和性能。Kmesh 需要提供完善的长连接指标收集和分析能力。 + +## 目标 + +1. 收集 TCP 长连接指标 +2. 提供实时监控能力 +3. 支持性能分析 +4. 实现告警机制 + +## 设计细节 + +### 架构设计 + +TCP 长连接监控系统包含以下组件: + +1. 指标收集器 +2. 数据处理器 +3. 存储系统 +4. 可视化界面 +5. 告警系统 + +### 指标定义 + +#### 基础指标 + +```c +struct TcpMetrics { + __u64 connection_duration; // 连接持续时间 + __u64 bytes_sent; // 发送字节数 + __u64 bytes_received; // 接收字节数 + __u64 retransmissions; // 重传次数 + __u64 rtt; // 往返时间 +}; +``` + +#### 高级指标 + +```c +struct TcpAdvancedMetrics { + __u64 window_size; // 窗口大小 + __u64 congestion_events; // 拥塞事件 + __u64 keepalive_probes; // 保活探测 + __u64 connection_resets; // 连接重置 +}; +``` + +### 数据收集 + +```go +type MetricsCollector interface { + CollectBasicMetrics() (*TcpMetrics, error) + CollectAdvancedMetrics() (*TcpAdvancedMetrics, error) + CollectCustomMetrics(types []string) (map[string]interface{}, error) +} +``` + +## 使用示例 + +### 查询指标 + +```bash +# 查询基础指标 +curl http://localhost:8080/metrics/tcp/basic + +# 查询高级指标 +curl http://localhost:8080/metrics/tcp/advanced +``` + +### 配置告警 + +```yaml +alerts: + - name: high_retransmission_rate + condition: tcp_retransmissions > 100 + duration: 5m + severity: warning +``` + +## 注意事项 + +1. 性能开销控制 +2. 数据采样策略 +3. 存储容量规划 + +## 未来工作 + +1. 支持更多指标类型 +2. 优化数据采集效率 +3. 增强分析能力 + +Upstream issue: https://github.com/kmesh-net/kmesh/issues/1211 + +### 摘要 + +目前,kmesh 在 TCP 连接关闭后提供访问日志,其中包含有关连接的更详细信息,例如发送的字节数、接收的字节数、丢包数、rtt 和重传数。 + +Kmesh 还提供工作负载和服务特定的指标,例如发送和接收的字节数、丢失的数据包、最小 rtt、pod 打开和关闭的总连接数。这些指标仅在连接关闭后更新。在本提案中,我们的目标是定期更新这些指标。 + +我们还旨在实现 TCP 长连接的访问日志和指标,开发一种连续监控和报告机制,以捕获长寿命 TCP 连接整个生命周期中的详细实时数据。定期报告访问日志,其中包含报告时间、连接建立时间、发送的字节数、接收的字节数、丢包数、rtt、重传数和状态等信息。还会定期报告长连接的指标,例如发送和接收的字节数、丢包数、重传数。 + +### 动机 + +可以尽早了解长连接的性能和健康状况,目前我们通过连接终止后提供的指标和访问日志获取连接的所有信息。 + +#### 目标 + +- 定期(5 秒)报告基于工作负载和服务的指标。 + +- 使用 ebpf 在长 TCP 连接的整个生命周期内持续收集详细的流量指标(例如,发送/接收的字节数、往返时间、数据包丢失、tcp 重传)。 + +- 以 5 秒的周期性时间报告指标和访问日志。我们选择 5 秒作为阈值时间,因为它允许有足够的时间来累积指标中有意义的更改。如果报告间隔太短,可能会因处理过多的更新而导致过多的开销。 + +- 从指标数据中生成包含有关连接信息的访问日志,并在长 TCP 连接的整个生命周期内持续生成。 + +- 指标和日志支持 open-telemetry 格式。 + +- 通过 kmesh 守护程序公开这些指标,以便 prometheus 可以抓取它。 + +- 单元测试和 E2E 测试。 + +#### 非目标 + +- 收集有关数据包内容的信息。 + +- 控制或修改 TCP 连接 + +- 收集 L7 指标 + +### 提案 + +TCP 连接信息将使用 eBPF cgroup_skb 钩子收集。RingBuffer map 用于定期将连接信息发送到用户空间。 + +### 设计细节 + +#### 收集指标 + +声明 ebpf cgroup_skb 钩子,当流量通过 cgroup 套接字时,将触发该钩子。 + +``` +SEC("cgroup_skb/ingress") +int cgroup_skb_ingress_prog(struct __sk_buff *skb) +{ + if (skb->family != AF_INET && skb->family != AF_INET6) + return SK_PASS; + + struct bpf_sock *sk = skb->sk; + if (!sk) + return SK_PASS; + + if (!is_managed_by_kmesh_skb(skb)) + return SK_PASS; + observe_on_data(sk); + return SK_PASS; +} + +SEC("cgroup_skb/egress") +int cgroup_skb_egress_prog(struct __sk_buff *skb) +{ + if (skb->family != AF_INET && skb->family != AF_INET6) + return SK_PASS; + + struct bpf_sock *sk = skb->sk; + if (!sk) + return SK_PASS; + + if (!is_managed_by_kmesh_skb(skb)) + return SK_PASS; + observe_on_data(sk); + return SK_PASS; +} + +``` +Observe_on_data 函数检查 lsat_report 之后经过的时间是否大于 5 秒。如果大于,则将 conn_info 报告给 ring_buffer 并更新 last_report_ns。 + +``` +static inline void observe_on_data(struct bpf_sock *sk) +{ + struct bpf_tcp_sock *tcp_sock = NULL; + struct sock_storage_data *storage = NULL; + if (!sk) + return; + tcp_sock = bpf_tcp_sock(sk); + if (!tcp_sock) + return; + + storage = bpf_sk_storage_get(&map_of_sock_storage, sk, 0, 0); + if (!storage) { + return; + } + __u64 now = bpf_ktime_get_ns(); + if ((storage->last_report_ns != 0) && (now - storage->last_report_ns > LONG_CONN_THRESHOLD_TIME)) { + tcp_report(sk, tcp_sock, storage, BPF_TCP_ESTABLISHED); + } +} +``` + +我们将更新 metric.go 的函数,以定期更新工作负载和服务指标,并且我们将为长 tcp 连接创建一个新指标。 + +![design](./pics/tcp_long_conn_design.png) + +#### 公开长连接 prometheus 指标 + +我们将公开持续时间超过 5 秒的连接的指标。不公开短连接的指标,因为它可能导致大量指标,并且它们也不适合 prometheus 指标,因为 prometheus 本身具有 5 秒的抓取间隔,并且短寿命连接可能在抓取之间开始和结束,从而导致不完整或误导性的数据。通过仅关注较长寿命的连接,我们确保指标稳定、有意义,并且更好地与 Prometheus 的时间序列数据模型保持一致。 + +将来我们可以拥有另一个组件,该组件报告有关连接的实时信息,例如 cilium hubble。 + +公开的 Prometheus 指标 + +- `kmesh_tcp_connection_sent_bytes_total`:通过已建立的 TCP 连接发送的总字节数 + +- `kmesh_tcp_connection_received_bytes_total`:通过已建立的 TCP 连接接收的总字节数 + +- `kmesh_tcp_connection_packet_lost_total`:TCP 连接中传输期间丢失的数据包总数 + +- `kmesh_tcp_connection_retrans_total`:通过已建立的 TCP 连接重传的总数 + +以上指标具有以下标签 + +``` + "reporter" + "start_time" + "source_workload" + "source_canonical_service" + "source_canonical_revision" + "source_workload_namespace" + "source_principal" + "source_app" + "source_version" + "source_cluster" + "source_address" + "destination_address" + "destination_pod_address" + "destination_pod_namespace" + "destination_pod_name" + "destination_service" + "destination_service_namespace" + "destination_service_name" + "destination_workload" + "destination_canonical_service" + "destination_canonical_revision" + "destination_workload_namespace" + "destination_principal" + "destination_app" + "destination_version" + "destination_cluster" + "request_protocol" + "response_flags" + "connection_security_policy" +``` + +#### 用户故事(可选) + +##### 故事 1 +工作负载和服务 prometheus 指标会定期更新,并在连接关闭时更新。 + +##### 故事 2 +一个新的 prometheus 指标用于定期更新的长 tcp 连接。 + +#### 注意事项/约束/警告(可选) + +#### 风险和缓解措施 + +#### 测试计划 + +更新 bpf_test.go 以测试编写的 ebpf 代码。 +同时更新 metric_test.go 以测试指标 +### 备选方案 + +创建一个用户空间代理组件而不是 ebpf 来收集指标。 diff --git a/docs/proposal/template_zh.md b/docs/proposal/template_zh.md new file mode 100644 index 000000000..e6e3ce8cf --- /dev/null +++ b/docs/proposal/template_zh.md @@ -0,0 +1,106 @@ +--- +title: 提案模板 +authors: +- "@your-github-handle" +reviewers: +- "@robot" +- TBD +approvers: +- "@robot" +- TBD +creation-date: 2024-01-15 +--- + +# 提案模板 + +## 摘要 + +简要描述你的提案内容。这部分应该简明扼要,让读者快速理解提案的主要内容。 + +## 背景 + +描述提出此提案的背景和动机: +- 当前存在什么问题? +- 为什么需要解决这个问题? +- 现有的解决方案有什么不足? + +## 目标 + +列出此提案要实现的具体目标: + +1. 目标一 +2. 目标二 +3. 目标三 + +### 非目标 + +明确指出哪些内容不在此提案的范围内: + +1. 非目标一 +2. 非目标二 + +## 设计方案 + +详细描述你的解决方案: + +### 架构设计 + +``` +[在此插入架构图] +``` + +### 接口设计 + +```go +type Interface interface { + Method1() error + Method2(param string) (Result, error) +} +``` + +### 实现细节 + +描述关键的实现细节: + +1. 组件一的实现 +2. 组件二的实现 +3. 数据流程 + +## 使用示例 + +提供具体的使用示例: + +```go +client := NewClient() +result, err := client.Method1() +if err != nil { + return err +} +``` + +## 替代方案 + +讨论其他可能的解决方案: + +1. 方案一 + - 优点 + - 缺点 +2. 方案二 + - 优点 + - 缺点 + +## 注意事项 + +列出实现和使用时需要注意的问题: + +1. 安全性考虑 +2. 性能影响 +3. 兼容性问题 + +## 未来工作 + +描述后续可能的改进方向: + +1. 功能扩展 +2. 性能优化 +3. 更多场景支持 diff --git a/docs/proposal/tls_cert_zh.md b/docs/proposal/tls_cert_zh.md index 17388726e..e46a3c9a8 100644 --- a/docs/proposal/tls_cert_zh.md +++ b/docs/proposal/tls_cert_zh.md @@ -1,179 +1,179 @@ -## 工作负载证书管理 - -### 概要 - -Kmesh支持TLS能力需要使用由istiod签发的证书,所以需要一套证书申请与管理模块,用于向istiod申请证书并管理证书的生命周期。 - -### 动机 - -Kmesh需要为纳管workload提供TLS能力,需要能够便捷的申请与管理证书,在合适的时机新增、删除、刷新证书 - -#### 目标 - -1. 为纳管workload所在的sa(service account)申请证书 -2. 证书有效期到期自动刷新 - -#### 非目标 - -1. 在ambient模式下,ztunnel与Kmesh各自拥有着一套证书管理体系,两者互不干扰,可能存在两者均为某sa申请了证书的情况,这种情况下流量被谁接管就使用谁的一套证书 -2. Kmesh异常重启情况下,旧的证书记录全部废弃,证书全部重新申请,不考虑保留之前的证书 - -### 提议 - -实现一个证书申请模块和证书管理模块,其中 - -证书申请模块:与istod建立一个加密grpc连接,为纳管workload所在的sa(service account)构造出CSR请求和对应的私钥,并使用CSR请求与istiod进行交互,由istiod进行签名后返回证书 - -证书管理模块: - -- 管理需要对证书进行操作的时机入口:1、新增workload 2、删除workload 3、证书有效期到期自动刷新 -- 管理证书的存放与管理方式 -- 根据证书的有效期,在临近到期时触发对应证书的刷新任务 - -### 限制 - -当前如果需要使用Kmesh tls能力,需要在istio启动时,修改deployment,在`CA_TRUSTED_NODE_ACCOUNTS`环境变量后边添加`kmesh-system/kmesh` - -## 设计细节 - -### 证书申请模块 - -随Kmesh启动创建一个caclient客户端,与istiod建立加密的grpc连接 - -使用workload中的信息,构造出CSR请求和私钥,将CSR请求通过caclient发送给istiod,istiod进行签名并返回证书 - -### 证书生命周期管理 - -使用一个通道、队列和map来记录和管理,其中队列和map均有锁来保证并发安全性 - -
- -![tls_cert_design](pics/tls_cert_design.svg) - -
- -**通道**:管理证书事件,根据Operation去处理证书任务,从通道中按序创建任务,可以防止一些并发调度问题 - -```go -chan :用于接受所有证书相关事件 -type certRequest struct { - Identity string - Operation int -} -``` - -触发时机: - -- 新增workload时 -- 删除workload -- 证书到期,从队列中取出需要刷新的证书任务 - -**队列**:检查最近到期的证书,提前1小时刷新证书; - -```go -队列元素内容: -type certExp struct { - identity string //使用sa构造的证书名 - exp time.Time //证书到期时间 -} -``` - -更新时机: - 新增证书:插入一条新的记录 - 刷新证书:删除旧记录,添加新记录; - 删除证书:遍历并删除旧证书的记录 - -**map**:记录证书信息和证书状态 - -```go -map:记录使用该证书的pod 数量 -​ key:Identity //使用sa构造的证书名 -​ value:certItem - -type certItem struct { - cert istiosecurity.SecretItem //证书信息 - refcnt int32 //记录使用该证书的pod数 -} -``` - -更新时机: - 在某sa下第一次有pod被Kmesh纳管时新增证书;新建并添加一条记录 - 在该sa下所有被Kmesh纳管pod都被删除时(refCnt=0)删除证书;删除一条记录 - -​ 在证书到期自动刷新时更新value内容;刷新已有记录中的cert - -​ 在某sa下有pod被Kmesh纳管时,对应refcnt+1; -​ 在某sa下有被Kmesh纳管的pod被删除时,对应refcnt-1; - -生命周期:整个sa的证书存在的时间;创建于sa证书申请时,删除于sa证书删除时 - -#### 场景一:新增证书 - -
- -![tls_cert_scenario1](pics/tls_cert_scenario1.svg) - -
- -1. Kmesh纳管pod1,订阅到新增的workload,SecretManager查找对应sa的证书:若已存在则计数加1;若不存在则进行证书申请 - -2. 为sa1 构造并发送CSR请求 - -3. istiod签发证书 - -4. 存储证书: - - - 存储证书 - - - 在状态信息中 - - 记录 count,为此sa进行计数,记录使用该证书的pod数量; - - - 往队列中添加一条到期时间的记录 - -#### 场景二:删除证书 - -
- -![tls_cert_scenario2](pics/tls_cert_scenario2.svg) - -
- -1. 删除pod1,删除对应workload - -2. 该sa计数减一; - - 若此时sa计数为0,则删除证书: - - - 遍历查找队列,删除对应的记录 - - 删除sa对应的证书 - -#### 场景三:证书到期自动更新 - -
- -![tls_cert_scenario3](pics/tls_cert_scenario3.svg) - -
- -1. 队列中有效期最近的证书到期,弹出该条记录,触发证书刷新动作 -2. 为该证书的sa构造并发送CSR请求 -3. istiod签发证书 -4. 存储证书, - - - 刷新map中的证书;refcnt保持不变 - -- 在队列中添加该条记录 - -#### 特别设计 - -map与队列均使用了锁来保证并发安全性,所有设计到map和队列的操作均使用定义的接口去进行操作,避免出现死锁等问题 - -由于申请证书需要通过grpc连接和istiod进行交互,耗时可能较大,而证书状态信息的变更为了并发安全性加了锁,所以在在需要新增或刷新证书时,需要把证书状态信息的变更和申请证书的流程分开: - -例如:在新增证书的函数流程中,如果判断需要新申请证书,会先创建对应的状态信息记录并写入map,这样其他线程执行的时候就不会重复申请证书,随后等证书刷新下来之后再写入该条记录内,申请失败则删除这条记录; - -### 遗留事项 - -1. 当前代码中的队列实现是优先队列,需要修改为普通队列,现有场景下按序从通道中获取证书事件,且Kmesh为workload申请的证书有效期一致,无需在队列中再排序 -2. 纳管pod判断,目前Kmesh相关证书处理流程中无法判断workload是否被纳管,待后续实现 -3. 某sa下只存在一个pod,该pod重启,引起workload快速删除与新增,会重复增删证书,带来不必要的开销,该场景需特殊处理 +## 工作负载证书管理 + +### 概要 + +Kmesh支持TLS能力需要使用由istiod签发的证书,所以需要一套证书申请与管理模块,用于向istiod申请证书并管理证书的生命周期。 + +### 动机 + +Kmesh需要为纳管workload提供TLS能力,需要能够便捷的申请与管理证书,在合适的时机新增、删除、刷新证书 + +#### 目标 + +1. 为纳管workload所在的sa(service account)申请证书 +2. 证书有效期到期自动刷新 + +#### 非目标 + +1. 在ambient模式下,ztunnel与Kmesh各自拥有着一套证书管理体系,两者互不干扰,可能存在两者均为某sa申请了证书的情况,这种情况下流量被谁接管就使用谁的一套证书 +2. Kmesh异常重启情况下,旧的证书记录全部废弃,证书全部重新申请,不考虑保留之前的证书 + +### 提议 + +实现一个证书申请模块和证书管理模块,其中 + +证书申请模块:与istod建立一个加密grpc连接,为纳管workload所在的sa(service account)构造出CSR请求和对应的私钥,并使用CSR请求与istiod进行交互,由istiod进行签名后返回证书 + +证书管理模块: + +- 管理需要对证书进行操作的时机入口:1、新增workload 2、删除workload 3、证书有效期到期自动刷新 +- 管理证书的存放与管理方式 +- 根据证书的有效期,在临近到期时触发对应证书的刷新任务 + +### 限制 + +当前如果需要使用Kmesh tls能力,需要在istio启动时,修改deployment,在`CA_TRUSTED_NODE_ACCOUNTS`环境变量后边添加`kmesh-system/kmesh` + +## 设计细节 + +### 证书申请模块 + +随Kmesh启动创建一个caclient客户端,与istiod建立加密的grpc连接 + +使用workload中的信息,构造出CSR请求和私钥,将CSR请求通过caclient发送给istiod,istiod进行签名并返回证书 + +### 证书生命周期管理 + +使用一个通道、队列和map来记录和管理,其中队列和map均有锁来保证并发安全性 + +
+ +![tls_cert_design](pics/tls_cert_design.svg) + +
+ +**通道**:管理证书事件,根据Operation去处理证书任务,从通道中按序创建任务,可以防止一些并发调度问题 + +```go +chan :用于接受所有证书相关事件 +type certRequest struct { + Identity string + Operation int +} +``` + +触发时机: + +- 新增workload时 +- 删除workload +- 证书到期,从队列中取出需要刷新的证书任务 + +**队列**:检查最近到期的证书,提前1小时刷新证书; + +```go +队列元素内容: +type certExp struct { + identity string //使用sa构造的证书名 + exp time.Time //证书到期时间 +} +``` + +更新时机: + 新增证书:插入一条新的记录 + 刷新证书:删除旧记录,添加新记录; + 删除证书:遍历并删除旧证书的记录 + +**map**:记录证书信息和证书状态 + +```go +map:记录使用该证书的pod 数量 +​ key:Identity //使用sa构造的证书名 +​ value:certItem + +type certItem struct { + cert istiosecurity.SecretItem //证书信息 + refcnt int32 //记录使用该证书的pod数 +} +``` + +更新时机: + 在某sa下第一次有pod被Kmesh纳管时新增证书;新建并添加一条记录 + 在该sa下所有被Kmesh纳管pod都被删除时(refCnt=0)删除证书;删除一条记录 + +​ 在证书到期自动刷新时更新value内容;刷新已有记录中的cert + +​ 在某sa下有pod被Kmesh纳管时,对应refcnt+1; +​ 在某sa下有被Kmesh纳管的pod被删除时,对应refcnt-1; + +生命周期:整个sa的证书存在的时间;创建于sa证书申请时,删除于sa证书删除时 + +#### 场景一:新增证书 + +
+ +![tls_cert_scenario1](pics/tls_cert_scenario1.svg) + +
+ +1. Kmesh纳管pod1,订阅到新增的workload,SecretManager查找对应sa的证书:若已存在则计数加1;若不存在则进行证书申请 + +2. 为sa1 构造并发送CSR请求 + +3. istiod签发证书 + +4. 存储证书: + + - 存储证书 + + - 在状态信息中 + - 记录 count,为此sa进行计数,记录使用该证书的pod数量; + + - 往队列中添加一条到期时间的记录 + +#### 场景二:删除证书 + +
+ +![tls_cert_scenario2](pics/tls_cert_scenario2.svg) + +
+ +1. 删除pod1,删除对应workload + +2. 该sa计数减一; + + 若此时sa计数为0,则删除证书: + + - 遍历查找队列,删除对应的记录 + - 删除sa对应的证书 + +#### 场景三:证书到期自动更新 + +
+ +![tls_cert_scenario3](pics/tls_cert_scenario3.svg) + +
+ +1. 队列中有效期最近的证书到期,弹出该条记录,触发证书刷新动作 +2. 为该证书的sa构造并发送CSR请求 +3. istiod签发证书 +4. 存储证书, + + - 刷新map中的证书;refcnt保持不变 + +- 在队列中添加该条记录 + +#### 特别设计 + +map与队列均使用了锁来保证并发安全性,所有设计到map和队列的操作均使用定义的接口去进行操作,避免出现死锁等问题 + +由于申请证书需要通过grpc连接和istiod进行交互,耗时可能较大,而证书状态信息的变更为了并发安全性加了锁,所以在在需要新增或刷新证书时,需要把证书状态信息的变更和申请证书的流程分开: + +例如:在新增证书的函数流程中,如果判断需要新申请证书,会先创建对应的状态信息记录并写入map,这样其他线程执行的时候就不会重复申请证书,随后等证书刷新下来之后再写入该条记录内,申请失败则删除这条记录; + +### 遗留事项 + +1. 当前代码中的队列实现是优先队列,需要修改为普通队列,现有场景下按序从通道中获取证书事件,且Kmesh为workload申请的证书有效期一致,无需在队列中再排序 +2. 纳管pod判断,目前Kmesh相关证书处理流程中无法判断workload是否被纳管,待后续实现 +3. 某sa下只存在一个pod,该pod重启,引起workload快速删除与新增,会重复增删证书,带来不必要的开销,该场景需特殊处理