MoreRSS

site iconJimmy Song | 宋净超修改

Tetrate 布道师,云原生社区 创始人,CNCF Ambassador,云原生技术专家。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Jimmy Song | 宋净超的 RSS 预览

深入解析 Envoy 外部处理过滤器(ext_proc)

2024-12-20 11:31:33

在微服务架构中,API 网关通常需要对请求和响应进行高级别的处理,如身份验证、数据转换和安全检查。Envoy 提供的 ext_proc 外部处理过滤器,是一个强大的工具,通过与 gRPC 服务交互,实现灵活的请求与响应处理。本文将深入解析该过滤器的功能、配置与性能优化策略,帮助开发人员和 DevOps 工程师高效应用该特性。

ext_proc 与其他过滤器的关系

ext_proc 和 Envoy 中的其他 gRPC 接口过滤器(如 ext_authz)在功能上有相似之处,但 ext_proc 提供了更强大的功能,支持完整的请求和响应处理。这使其特别适用于需要深度内容检查和修改的应用场景。

你可以通过下面的 Envoy 外部处理过滤器思维导图快速了解 ext_proc

image
Envoy ext_proc 思维导图

这张思维导图展示了 Envoy ext_proc 外部处理过滤器的核心结构和功能模块。ext_proc 通过 gRPC 双向流协议与外部服务交互,可灵活处理 HTTP 请求和响应的各个阶段,并支持同步与异步处理。

ext_proc 工作原理与配置

定义与功能

ext_proc 是 Envoy 提供的 HTTP 过滤器,支持将请求和响应外包给 gRPC 服务进行处理,允许在外部服务中实现复杂的逻辑,灵活应对业务需求。例如,在安全场景中,ext_proc 可用于执行身份验证和授权检查;在数据转换场景中,可以实现数据格式转换与内容过滤。此外,还可用于记录审计日志、动态请求重写以及内容增强等功能,适用于各种企业应用环境中的深度流量管理。

工作原理

ext_proc 使用双向 gRPC 流与外部服务通信,实现请求和响应处理的实时交互。这使得 Envoy 可以将复杂任务(如身份验证、数据转换和自定义 Header 操作)卸载到外部服务,从而提高灵活性和可扩展性。

Envoy 发送 ProcessingRequest 消息,外部服务返回 ProcessingResponse 消息。需要注意的是,每个 HTTP 请求流都会创建一个独立的 gRPC 流,而不会在多个请求之间共享。每个由 Envoy 处理的 HTTP 请求都会创建其专属的 gRPC 流,从而确保请求与响应的隔离和精确管理。

这种设计允许外部服务在请求与响应生命周期的不同阶段进行干预,甚至能够生成全新的响应内容。``

下图概述 Envoy 外部处理过滤器的处理过程:

image
Envoy ext_proc 流程

关键功能

  • 请求和响应处理:读取和修改 HTTP 请求和响应的头部、主体和尾部。
  • 灵活性:根据业务需求定义自定义逻辑,弥补内置功能的不足。
  • 异步处理:支持异步处理模式,防止请求阻塞。

Envoy 配置示例

以下是一个基本的 Envoy 配置示例:

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 8080
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
              log_format:
                text_format: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% \"%RESP(X-EXTPROC-HELLO)%\" \"%RESP(CONTENT-TYPE)%\" \"%RESP(CONTENT-LENGTH)%\" %DURATION% ms\n"
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: [ "*" ]
              routes:
              - match:
                  prefix: "/"
                route:
                  host_rewrite_literal: www.envoyproxy.io
                  cluster: service_envoyproxy_io
          http_filters:
          - name: envoy.filters.http.ext_proc
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor
              grpc_service:
                envoy_grpc:
                  cluster_name: ext_proc_cluster
              failure_mode_allow: true
              processing_mode:
                request_header_mode: SKIP
                response_header_mode: SEND
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - name: ext_proc_cluster
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    lb_policy: ROUND_ROBIN
    http2_protocol_options: {}
    load_assignment:
      cluster_name: ext_proc_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 9000
  - name: service_envoyproxy_io
    type: LOGICAL_DNS
    dns_lookup_family: V4_ONLY
    load_assignment:
      cluster_name: service_envoyproxy_io
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: www.envoyproxy.io
                port_value: 443
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        sni: www.envoyproxy.io

为了理解 Envoy 配置与 gRPC 服务之间的关联,我们需要了解以下配置项如何影响流量处理:

  • grpc_service: 定义与 gRPC 服务通信的目标地址和集群名,对应 Envoy 配置中的 ext_proc_cluster
  • processing_mode: 控制请求头、请求体和响应头等处理阶段的触发行为,决定了何时调用 gRPC 服务。
  • failure_mode_allow: 指定当 gRPC 服务失败时是否继续请求处理,确保服务在部分失败场景下的高可用性。
  • listeners: 定义了 Envoy 接收请求的网络地址和端口。
  • filter_chains: 配置请求的处理链,包括 HTTP 连接管理器和外部处理过滤器。
  • http_filters: 列出启用的过滤器,如 ext_procrouter
  • clusters: 定义上游服务和外部处理 gRPC 服务的位置。

详细的配置说明请参考 Envoy 文档

Envoy 使用这些配置选项将请求和响应外包给 gRPC 服务,处理结果通过双向流协议返回,影响请求的转发行为。

gRPC 服务示例

以下是一个简单的 gRPC 外部处理服务器实现,演示如何通过 ext_proc 添加自定义响应头。该实现展示了核心方法的选择和设计决策,例如使用 Process 方法持续接收请求和发送响应,确保处理过程的连续性。此外,采用 HeaderMutation 配置修改 HTTP 响应头,展现了 gRPC 消息结构与 Envoy 配置的紧密集成,便于动态扩展和灵活管理。

package main

import (
	"log"
	"net"

	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	configPb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
	extProcPb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
)

type extProcServer struct {
	extProcPb.UnimplementedExternalProcessorServer
}

// Process handles external processing requests from Envoy.
// It listens for incoming requests, modifies response headers,
// and sends the updated response back to Envoy.
//
// When a request with response headers is received, it adds a custom header
// "x-extproc-hello" with the value "Hello from ext_proc" and returns the modified headers.
//
// Note: The `RawValue` field is used instead of `Value` because it supports
// setting the header value as a byte slice, allowing precise handling of binary data.
//
// This function is called once per HTTP request to process gRPC messages from Envoy.
// It exits when an error occurs while receiving or sending messages.

func (s *extProcServer) Process(
	srv extProcPb.ExternalProcessor_ProcessServer,
) error {
	for {
		req, err := srv.Recv()
		if err != nil {
			return status.Errorf(codes.Unknown, "error receiving request: %v", err)
		}

		log.Printf("Received request: %+v\n", req)

		// Prepare the response to be returned to Envoy.
		resp := &extProcPb.ProcessingResponse{}

		// Only process response headers, not request headers.
		if respHeaders := req.GetResponseHeaders(); respHeaders != nil {
			log.Println("Processing Response Headers...")

			resp = &extProcPb.ProcessingResponse{
				Response: &extProcPb.ProcessingResponse_ResponseHeaders{
					ResponseHeaders: &extProcPb.HeadersResponse{
						Response: &extProcPb.CommonResponse{
							HeaderMutation: &extProcPb.HeaderMutation{
								SetHeaders: []*configPb.HeaderValueOption{
									{
										Header: &configPb.HeaderValue{
											Key:      "x-extproc-hello",
											RawValue: []byte("Hello from ext_proc"),
										},
									},
								},
							},
						},
					},
				},
			}
			log.Printf("Sending response: %+v\n", resp)
			// Send the response back to Envoy.
			if err := srv.Send(resp); err != nil {
				return status.Errorf(codes.Unknown, "error sending response: %v", err)
			}
		} else {
			// If it is not a callback in the response header stage, do not make any modifications and continue processing the next event.
			// For request_headers or other events, do not modify & ensure that Envoy will not be stuck.
			// An empty processing can be returned for request_headers, or it can be skipped in envoy.yaml.
			// Here, simply continue to wait for the next event.
			continue
		}
	}
}

func main() {
	lis, err := net.Listen("tcp", ":9000")
	if err != nil {
		log.Fatalf("Failed to listen: %v", err)
	}

	grpcServer := grpc.NewServer()
	// Register the ExternalProcessorServer with the gRPC server.
	extProcPb.RegisterExternalProcessorServer(grpcServer, &extProcServer{})

	log.Println("Starting gRPC server on :9000...")
	if err := grpcServer.Serve(lis); err != nil {
		log.Fatalf("Failed to serve: %v", err)
	}
}

预期结果:请求返回状态码 200,响应头中包含自定义头 x-extproc-hello: Hello from ext_proc。如果缺少该头,检查以下内容:

  • gRPC 服务是否正常运行:确认 gRPC 服务器是否已启动并监听端口 :9000
  • Envoy 配置是否正确:检查 Envoy 配置文件,确保 ext_proc 过滤器已启用,并且 ext_proc_cluster 配置无误。
  • 日志和错误排查:查看 Envoy 和 gRPC 服务器的日志,排查潜在错误。

在本地运行 Envoy 和 gRPC 服务后,使用 curl 进行测试:

envoy -c envoy.yaml
go run main.go
curl -v http://localhost:8080

你将看到包含自定义头 x-extproc-hello: Hello from ext_proc 的响应。

你将看到如下图所示的结果。

image
示例结果

在 curl 请求的响应中包含了我们自定义的 header x-extproc-hello: Hello from ext_proc

统计与监控

ext_proc 输出的统计信息位于 http.<stat_prefix>.ext_proc. 命名空间,其中 stat_prefix 是 HTTP 连接管理器的前缀。常用统计信息包括:

指标名称 类型 描述
streams_started Counter 启动的 gRPC 流数量
streams_msgs_sent Counter 发送的消息数量
streams_msgs_received Counter 接收的消息数量
spurious_msgs_received Counter 接收的违反协议的意外消息数量
streams_closed Counter 成功关闭的流数量
streams_failed Counter 产生 gRPC 错误的流数量
failure_mode_allowed Counter 错误被忽略的次数(根据配置)
message_timeouts Counter 配置超时内未收到响应的消息数量
rejected_header_mutations Counter 被拒绝的头部更改数量
clear_route_cache_ignored Counter 忽略的清理路由缓存请求数量
clear_route_cache_disabled Counter 被禁用的清理路由缓存请求数量

详见 Envoy 文档

应用场景与优化策略

常见应用场景

  • 身份验证:外部身份验证服务检查用户凭证。
  • 数据审计:记录请求和响应的数据以满足合规要求。
  • 流量管理:根据动态分析调整流量路由策略。

配置说明与优化策略

  • 故障恢复与负载均衡:部署多实例 gRPC 服务,使用负载均衡自动转移请求。

  • 消息超时与重试配置:

    http_filters:
      - name: envoy.filters.http.ext_proc
        config:
          grpc_service:
            envoy_grpc:
              cluster_name: ext_proc_server
          processing_mode:
            request_header_mode: SEND
            response_header_mode: SEND
          message_timeout: 500ms
          max_message_timeout: 1000ms
          failure_mode_allow: false
    
  • 元数据选项与安全策略:

    metadata_options:
      forwarding_namespaces:
        untyped: ["custom_namespace"]
    

总结

Envoy 的 ext_proc 过滤器通过灵活的请求和响应处理能力,为微服务架构中的服务治理、数据转换和请求检查提供了强大的支持。正确配置和优化 ext_proc 可以显著提高系统的灵活性和可扩展性,满足多样化的业务需求。

参考

深入 Istio Ambient 模式:从 ztunnel 到 Waypoint 代理的 L7 流量路径解析

2024-12-12 18:44:52

在 Istio Ambient 模式下,ztunnel 是节点级安全代理,在 L4 层拦截并加密服务间流量。但不负责 L7(如 HTTP)层处理。Ambient 模式中,L7 处理由 Waypoint 代理负责。当 ztunnel 发现目标服务需 L7 处理时,通过 HBONE 协议将流量转发给 Waypoint 代理进行 HTTP 层策略应用和可观察性处理,再由 Waypoint 代理经 ztunnel 转发给目标 Pod,本文将详细阐述这条 L7 流量转发链路。

Waypoint 代理的角色与责任

在 Istio Ambient 模式中:

  • ztunnel 负责透明捕获 Pod 间的 L4 流量,提供 mTLS 加密和身份认证。

  • Waypoint 代理 是一个基于 Envoy 的 L7 代理,处理 HTTP 层的高级路由、策略和可观察性。

当一个请求需要 L7 层策略时(如 productpage 调用 reviews-v1 服务),ztunnel 将流量通过 HBONE 隧道转发到 Waypoint Proxy,由 Waypoint 执行 HTTP 路由和策略。

L7 流量在 Ambient 模式中的处理路径

下图展示了 L7 流量在 Ambient 模式中的处理路径。

image
L7 流量在 Ambient 模式中的处理路径

下面两张图片分别展示了源 Pod 和目标 Pod 在同节点和跨节点情况下的 L7 流量处理路径。

image
源 pod 和目标 pod 在同一节点上的 L7 流量路径
image
源 pod 和目标 pod 在不同节点上的 L7 流量路径

下面是详细的流量路径。

1. 应用请求发出

假设 productpage 应用需要访问 reviews 服务。productpage Pod 内的应用向 reviews.default.svc.cluster.local:9080 发起 HTTP 请求。

2. ztunnel L4 透明捕获与识别

productpage Pod 的出站请求首先被所在节点上的 ztunnel 拦截。ztunnel 查看从 Istio 控制面下发的配置,根据目标服务(reviews)的身份和策略,得知该服务需要经过 Waypoint 代理进行 L7 层处理。

3. 通过 HBONE 协议转发至 Waypoint

ztunnel 并非使用传统的 Envoy-to-Envoy XDS 或原生 TCP+mTLS 隧道,而是通过 HBONE 协议 与 Waypoint 代理通信。HBONE 是 Istio Ambient 模式中专门设计的无 Sidecar L7 路由协议,基于 HTTP/2,可在透明模式下对流量进行叠加转发,从而实现灵活的服务拓扑和策略控制。

在这一阶段,ztunnel 会将 L4 流量封装到 HBONE 隧道中,发送给相应的 Waypoint 代理。

4. Waypoint 代理的 L7 策略与遥测处理

Waypoint 代理(目前仍基于 Envoy 实现)收到通过 HBONE 隧道传来的流量后,通过 TLS 配置和客户端证书校验,确保下游(ztunnel)是已被认证的受信主体。它将下游客户端的身份信息(SPIFFE ID)和其他上下文元数据提取出来,以便在 L7 层策略决策中使用。

执行的操作包括:

  • 基于 HTTP Path/Host 的路由和流量拆分
  • 基于 Headers 的访问控制和认证策略
  • 故障注入、熔断、限流
  • 遥测数据收集(请求时延、错误率、Tracing、Metrics、Logs)

完成 L7 处理后,Waypoint 代理再通过 HBONE 将流量传回到目标节点的 ztunnel。

5. 流量到达目标 Pod

目标节点上的 ztunnel 会从 Waypoint 代理接收处理过的流量(同样通过 HBONE 隧道传递),然后解封装并将流量传递给对应的 reviews Pod 中的应用容器端口。

洞察与关键点总结

1. Waypoint 并不知道 ztunnel 的存在

  • Waypoint 代理只知道目标 Pod 的 IP 地址,但目标端口被重写为 15008
  • Kubernetes iptables 规则将流量透明重定向到 ztunnel。

2. 流量安全性:端到端加密与身份认证

  • 双向 TLS(mTLS)和 SPIFFE ID 校验确保了端到端安全。
  • 无法绕过 ztunnel,确保了零信任架构的完整实施。

3. 完全透明的流量控制

  • 应用开发人员无需更改任何代码。
  • 流量控制、策略和可观察性完全在数据面层面透明执行。

如何调试?

在 Ambient 模式下,调试方式也有了一些变化:

  • ztunnel 调试

    • Istio 引入了新的 istioctl ztunnel 子命令来协助查看和调试 ztunnel 的配置与状态。
  • waypoint 调试

    • 虽然 Waypoint 代理仍然是 Envoy,所以仍然可以使用 istioctl pcistioctl ps 来查看其路由、集群和监听器配置。
    • istioctl waypoint 提供了更直观的配置查看和状态检查功能。

总结

Istio Ambient 模式通过 ztunnel 来处理 L4 流量并实现零信任加密与传输,再通过 Waypoint 代理为需要 L7 策略的请求提供集中处理。两者之间通过 HBONE 协议进行高效、透明的通信,实现比传统 Sidecar 模式更轻量且易于运维的架构。

探索 AnythingLLM:借助开源 AI 打造私有化智能知识库

2024-12-11 21:50:21

随着大语言模型(LLM)的快速发展,将企业内部知识库与 AI 工具结合成为热门解决方案。作为一名技术探索者,我对构建私有知识库充满兴趣,也希望测试 LLM 的能力,尤其是像 Ollama 和千问这类模型。此外,AnythingLLM 是一个开源项目,具有较高的社区关注度,因此我决定对其进行深入调研。

基于 RAG(检索增强生成)技术,AnythingLLM 提供了从数据处理到用户界面的全栈解决方案,支持构建企业内部的智能知识库。其模块化架构和灵活部署方式,使其成为企业和个人开发者进行知识管理和 AI 项目实践的重要工具。

RAG 原理概述

简介

RAG(Retrieval-Augmented Generation) 是一种结合了信息检索和语言模型的技术。它通过从大规模的知识库中检索相关信息,并利用这些信息来指导语言模型生成更准确和深入的答案。这种方法由 Meta AI 研究人员在 2020 年提出,旨在解决大型语言模型在信息滞后、模型幻觉、私有数据匮乏和内容不可追溯等问题。

RAG 就是可以开卷回复的 LLM。其发展历程:Naive RAG 包含索引、检索、生成三步,存在 召回率低、Prompt 拼接问题Advanced RAG 优化索引与检索,引入 预检索、后检索策略与数据清洗 提升效率。Modular RAG 实现 模块化流水线与端到端训练,具备更高的 灵活性与适应性

背景与挑战

尽管 LLM 在处理复杂任务方面表现出色,但在以下三个方面存在局限:

  • 知识局限性:大模型的训练数据来自公开数据源,无法访问非公开和实时数据。
  • 幻觉问题:模型有时会生成错误答案,特别是在缺少特定领域知识时。
  • 数据安全性:涉及内部私有数据时,企业面临数据泄露风险。

RAG 技术通过向量检索与生成模型结合,显著提高了数据处理的深度和准确性。

工作原理

RAG 的工作流程包括两个主要阶段:

  1. 数据准备阶段

    • 将内部私有数据向量化存入数据库,构建检索索引。
  2. 用户应用阶段

    • 根据用户的 Prompt 检索相关内容,将结果与原 Prompt 组合,生成模型回答。

通过这种方式,RAG 可以搭建团队内部的本地知识库,弥补大模型的知识局限性,解决幻觉和数据隐私问题。然而,RAG 也存在一些主要限制:

  • 数据依赖性强:RAG 系统的效果严重依赖于内置知识库的数据质量和覆盖范围。

  • 检索准确性受限:检索算法可能因索引构建不完善或查询表达模糊导致相关性降低。

  • 模型推理成本高:大型语言模型的推理消耗大量资源,尤其在频繁查询和大规模应用场景中。

  • 技术复杂度高:构建和维护 RAG 系统需要强大的数据管理与模型集成能力,涉及嵌入、索引构建和检索优化等多个复杂组件。

  • 响应延迟与性能瓶颈:在高负载下,检索与推理过程可能导致响应速度变慢,尤其在硬件性能受限的环境中。

AnythingLLM 简介

AnythingLLM 是 Mintplex Labs Inc. 开发的一款开源 ChatGPT 等效工具,用于在安全的环境中与文档进行交互。它融合了从数据处理到用户界面的所有技术,适用于构建个人或企业私有化的知识库。

核心特点

  • 多用户支持和权限管理:支持多个用户和不同权限设置。
  • 支持多种文档类型:PDF、TXT、DOCX、JSON 等。
  • 内置数据连接器:GitHub、GitLab、YouTube、链接抓取、Confluence 等。
  • 多种向量数据库支持:如 LanceDB(默认)、Pinecone、Weaviate 等。
  • 灵活的 LLM 集成:支持 OpenAI、Azure OpenAI、Ollama、LM Studio、LocalAI 等。
  • 成本节约措施:大文档只需嵌入一次,显著降低成本。
  • 开发者 API 支持:便于自定义和扩展。
image
在 AnythingLLM 中选择 LLM

技术架构

  • 收集器(Collector):将本地或在线资源转化为 LLM 可用格式。
  • 前端(Frontend):基于 ViteJS 和 React 构建的用户界面。
  • 服务器(Server):基于 NodeJS 和 Express 的后端,管理数据库和 LLM 交互。

构建自己的知识库:详细步骤

要在 AnythingLLM 中构建一个私有知识库,可以按照以下步骤操作:

  1. 上传文档:将 PDF、TXT、DOCX、JSON 等支持的文档格式上传到系统中。

  2. 嵌入向量生成(Embedding)

    • 使用配置的嵌入模型(如 OpenAI、Azure OpenAI、LocalAI)将文档转化为向量数据。
    • 确保配置正确的嵌入模型以匹配项目需求。
  3. 存储到向量数据库

    • 选择适合的向量数据库,如 LanceDB(默认)、Pinecone、Weaviate。
    • 配置数据库连接,保证数据安全和高效检索。
  4. 查询与回答

    • 用户输入查询,系统将其转化为查询向量。
    • 向量数据库检索最匹配的内容,调用大语言模型(如 OpenAI GPT)生成答案。
    • 返回最终答案,链接相关文档和参考。
流程图示:
image
构建知识库流程

通过该流程,可以有效构建支持高效查询和生成回答的智能知识库。

在 Docker 中安装 AnythingLLM

参考:Docker 安装指南

export STORAGE_LOCATION=$HOME/anythingllm && \
mkdir -p $STORAGE_LOCATION && \
touch "$STORAGE_LOCATION/.env" && \
docker run -d \
--cap-add SYS_ADMIN \
--network host \
--add-host=host.docker.internal:host-gateway \
-v ${STORAGE_LOCATION}:/app/server/storage \
-v ${STORAGE_LOCATION}/.env:/app/server/.env \
-e STORAGE_DIR="/app/server/storage" \
mintplexlabs/anythingllm

注意:使用 host network,否则容器中无法与 Ollama 通信。

若要在本机运行 Ollama,可以使用下面的命令:

ollama run qwen2.5:14b --keepalive 0

这将会运行 qwen2.5:14b,你也可以选择其他大模型。

打开浏览器:http://localhost:3001

注意:必须选择要接入的 LLM,可以使用 localcloud

Desktop 部署

AnythingLLM 内置的 LLM 引擎支持下载流行的模型如 LLama-3、Phi-3 等,支持 CPU 和 GPU。本地运行适用于试用其基本功能。

参考:Desktop 安装概览

局限性:缺少多用户支持、浏览器插件、用户和 Workspace 管理等功能。

image
AnythingLLM 的对话界面

使用体验与问题记录

如果你的电脑性能堪忧的话,强烈不建议你在本地运行大模型。你会遇到各种性能问题,例如下面看到的,在上传文件嵌入到 Workspace 时卡住了。

image
本地运行大模型时遇到性能问题

性能与硬件限制

  • 构建向量数据库特别慢:支持的文档格式很多,但在我的 MacBook Pro 2015(16G 内存,无 M 系列芯片)上,构建向量数据库的过程非常耗时。这是因为文档需要被嵌入模型处理成高维向量,并存储到数据库中。该过程涉及复杂的计算和大量内存操作,导致处理一个 7M 的 JSON 数据需要 3 分钟,而嵌入(Embed)到 Workspace 则需十几分钟,且时常失败。
  • 高性能需求:由于硬件性能受限,运行本地 LLM 十分吃力。运行 Ollama 尚可,但进行 RAG 操作时性能明显不足。

查询与响应延迟

  • 响应慢:在聊天模式下,系统反馈非常慢,通常需要等待几分钟才能得到回复。

常见错误提示与解决方案

如何改善用户体验

  1. 使用商用大模型 API

    • 如果硬件资源有限,可以考虑使用 OpenAI、Azure OpenAI 等商用大模型 API。这些服务在稳定性和性能方面具有优势,尤其适用于大规模文档处理和实时查询。
  2. 优化硬件环境

    • 使用带有 GPU 加速的现代硬件,推荐内存不低于 32GB,显卡支持 CUDA 的 GPU(如 NVIDIA RTX 系列)来显著提升向量嵌入和模型推理速度。
  3. 调整 AnythingLLM 配置

    • Chat Setting(聊天设置):配置聊天相关参数,包括模型选择、响应超时、查询历史记录存储策略等。
    • Agent 设置:根据项目需求启用不同类型的代理,如检索代理、对话代理和任务代理。
    • 资源分配与性能优化:在 Docker 或 Kubernetes 部署环境中,设置 CPU、内存和 GPU 加速参数。调整嵌入批处理大小(Batch Size)、线程池大小等性能参数,优化推理与检索性能。
  4. 分布式部署与扩展

    • Kubernetes 集群部署
      • 使用 Kubernetes 编排多个 AnythingLLM 实例,确保高可用性和自动扩展能力。
      • 部署配置包括 ReplicaSet、Pod 自动缩放(HPA)、负载均衡(Service)、存储卷(PersistentVolumeClaim)等。
    • 云服务部署
      • 在云平台上运行托管服务,使用容器服务管理。
      • 配置高性能数据库(如 RDS、Firestore),并启用 CDN 加速文件传输。
    • 数据库和缓存扩展
      • 使用分布式数据库(如 Redis、Pinecone、Weaviate)提高查询速度。
      • 启用数据库主从复制与自动备份,确保数据持久性和高可用性。
  5. 升级数据库存储方案

    • 替换默认数据库 LanceDB,考虑使用更高性能的向量数据库如 Pinecone、Weaviate 等,以减少查询延迟。
  6. 代码优化与插件扩展

    • 定制插件来适配特定任务,并启用数据缓存机制以减少频繁查询对资源的消耗。

总结与展望

AnythingLLM 是一个功能全面的 RAG 解决方案,适用于企业内部知识库构建。通过结合向量检索与大语言模型,该平台提供了强大的文档问答能力。然而,部署和定制化需要一定的技术投入。未来的改进方向包括增强多数据库支持、更灵活的嵌入模型选择以及提升文档解析能力。

从 MeshConfig 迁移到 Istio Telemetry API:提升网格观测性和灵活性

2024-12-11 15:04:01

Istio 的 Telemetry API 是替代传统 MeshConfig 遥测配置的现代化方式,提供了更灵活的工具来定义服务网格中的 TracingMetricsAccess Logging。相比传统的 EnvoyFilterMeshConfig,Telemetry API 更具模块化、动态更新和跨层次配置能力。

在本篇中,我们将详解如何使用 Telemetry API 配置 Istio 遥测功能,涵盖 Tracing、Metrics 和 Logging 的具体实现,同时展示如何迁移过时的 MeshConfig 配置。

Telemetry API 发展历程

Istio 的遥测能力在早期版本中依赖于较为传统的配置方法,如 MixerMeshConfigconfigOverride,这些方法虽然能够满足基本需求,但在复杂场景下显得力不从心。为了解决这些问题,Istio 引入了基于 CRD 的 Telemetry API

关键版本更新

为了帮助读者了解 Telemetry API 的进化过程,以下是一些重要版本的更新信息:

  1. Istio 1.11:引入 Telemetry API(Alpha),提供了基本的指标和日志自定义功能。
  2. Istio 1.13:支持 OpenTelemetry 日志记录、自定义追踪服务名称,以及更强的日志过滤功能。
  3. Istio 1.18:默认不再安装 Prometheus 的 EnvoyFilter,完全依赖 Telemetry API 定义遥测行为。
  4. Istio 1.22:Telemetry API 升级为稳定版(v1),全面支持生产环境需求。

为什么迁移到 Telemetry API?

尽管传统的 MeshConfig 和 EnvoyFilter 提供了基础的遥测能力,但它们的配置方式在灵活性、动态性和扩展性方面存在诸多限制。为了更清晰地理解这些局限性,我们将从几个关键维度展开说明。

使用 MeshConfig 和 EnvoyFilter 的复杂性

在介绍具体问题之前,我们先了解一下 MeshConfig 和 EnvoyFilter 的定位:MeshConfig 适用于全局配置,而 EnvoyFilter 用于细粒度的自定义。但正是这种分工,导致了它们在管理上的复杂性。

1. 配置方式分散

  • MeshConfig 用于集中定义全局网格行为,例如访问日志路径、追踪采样率和指标维度。虽然适合简单场景,但无法满足命名空间级或工作负载级的需求。

  • EnvoyFilter 则可以覆盖或扩展 Envoy 的配置,允许更细粒度的控制。但这种方式直接操作 Envoy 内部结构(xDS 字段),配置语言复杂且容易出错。

    示例:通过 MeshConfig 配置访问日志

    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
      meshConfig:
        accessLogFile: /dev/stdout
    

    问题

    • 无法为特定服务或命名空间设置不同的日志路径。
    • 需要重新应用整个配置,动态性不足。

    示例:通过 EnvoyFilter 自定义指标

    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: custom-metric-filter
      namespace: mynamespace
    spec:
      workloadSelector:
        labels:
          app: myapp  # 选择特定的工作负载
      configPatches:
        - applyTo: HTTP_FILTER
          match:
            context: SIDECAR_INBOUND  # 匹配入站流量
          patch:
            operation: ADD
            filterClass: STATS  # 指定为统计过滤器
            value:
              name: istio.request_operation  # 自定义指标名称
              typed_config:
                "@type": type.googleapis.com/udpa.type.v1.TypedStruct
                type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
                value:
                  config:
                    configuration: |
                      "attributes": [
                        {
                          "output_attribute": "istio_operationId",
                          "match": [
                            {
                              "value": "GetReviews",
                              "condition": "request.url_path == '/reviews' && request.method == 'GET'"
                            }
                          ]
                        }
                      ]                  
                  vm_config:
                    runtime: envoy.wasm.runtime.null
                    code:
                      local: { inline_string: "envoy.wasm.attributegen" }
    

    问题

    • 配置语法复杂且冗长,需深入理解 Envoy 的结构。
    • 易于出错,调试和维护成本高。

2. 动态性不足

虽然现代微服务环境强调动态调整配置,但 MeshConfig 和 EnvoyFilter 的动态性支持有限:

  • MeshConfig:修改配置通常需要重启代理或重新应用整个配置,导致服务中断。
  • EnvoyFilter:更新流程复杂,调整单个参数也需重新部署相关代理实例。

3. 多租户支持困难

在多租户环境中,针对不同命名空间或工作负载自定义遥测配置非常重要。然而:

  • MeshConfig:无法针对命名空间或工作负载进行差异化设置。
  • EnvoyFilter:需要编写多个过滤器配置,增加了管理复杂性。

4. 难以扩展和调试

  • MeshConfig 和 EnvoyFilter 对新需求(如 OpenTelemetry)支持较慢。
  • EnvoyFilter 的调试难度高,需要深入分析 Envoy 日志和行为。

弃用传统 MeshConfig 的遥测配置

鉴于上述局限性,Istio 社区已经将传统的 MeshConfig 遥测配置标记为弃用。以下示例展示了这些配置的使用方式及其不足之处:

  • Access Logging 配置

    meshConfig:
      accessLogFile: /dev/stdout
    
  • Trace Sampling 配置

    meshConfig:
      enableTracing: true
      extensionProviders:
      - name: zipkin
        zipkin:
          service: zipkin.istio-system.svc.cluster.local
          port: 9411
    
  • 自定义 Metrics 标签

    meshConfig:
      telemetry:
        v2:
          prometheus:
            configOverride:
              inboundSidecar:
                metrics:
                  - name: requests_total
                    dimensions:
                      user-agent: request.headers['User-Agent']
    

通过上述例子可以看出,这些配置的灵活性和扩展性明显不足,难以应对复杂的生产环境需求。

Telemetry API 的优势

在传统配置方式的基础上,Telemetry API 带来了多项改进,使其更适合现代化的服务网格管理需求:

  1. 模块化设计:Tracing、Metrics 和 Access Logging 独立配置,清晰简洁。
  2. 动态更新:支持实时更新配置,无需重启代理。
  3. 层级化支持:允许全局、命名空间和工作负载级别的配置覆盖。
  4. 简单直观:使用声明式语法,无需深入理解 Envoy 的内部结构。

Istio Telemetry API 配置示例

全局配置示例

为帮助理解 Telemetry API 的具体使用,我们以全局配置示例作为开始:

apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
  name: mesh-default
  namespace: istio-system
spec:
  accessLogging:
  - providers:
    - name: envoy # better to use a built-in one
  tracing:
  - providers:
    - name: "skywalking"
    randomSamplingPercentage: 100.00
  metrics:
  - overrides:
    - match:
        metric: REQUEST_COUNT
        mode: CLIENT
      tagOverrides:
        x_user_email:
          value: |
            'x-user-email' in request.headers ? request.headers['x-user-email'] : 'empty'            
    providers:
    - name: prometheus

使用 Telemetry API 配置 SkyWalking

我们再以配置 SkyWalking 的采样率和 span tag 为例,演示如何使用 Telemetry API。

检查 Istio 版本与 CRD

  • 如果使用 Istio 1.22 或更高版本,使用 telemetry.istio.io/v1
  • 对于 Istio 1.18 至 1.21 的用户,使用 telemetry.istio.io/v1alpha1

通过以下命令检查 Telemetry API 的 CRD 是否已安装:

kubectl get crds | grep telemetry

部署 SkyWalking

在集群中部署 SkyWalking OAP 服务:

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.24/samples/addons/extras/skywalking.yaml

检查服务状态:

kubectl get pods -n istio-system -l app=skywalking-oap

配置 MeshConfig 添加 SkyWalking 提供商

在 Istio 的 MeshConfig 中定义 SkyWalking 提供商。

apiVersion: v1
kind: ConfigMap
metadata:
  name: istio
  namespace: istio-system
data:
  mesh: |-
    enableTracing: true
    extensionProviders:
    - name: "skywalking"
      skywalking:
        service: "tracing.istio-system.svc.cluster.local"
        port: 11800    

使用 Telemetry API 配置采样率

通过 Telemetry API,将 SkyWalking 设置为默认的 Tracing 提供商,并定义采样率。

你可以从使用 Telemetry API 从多个层级配置采样率,为了节约篇幅,我们仅演示在命名空间范围配置采样率,其他层级的配置请参考 Telemetry API

apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
  name: namespace-override
  namespace: default
spec:
  tracing:
  - providers:
      - name: skywalking
    randomSamplingPercentage: 50
    customTags:
      env:
        literal:
          value: production

说明:

  • providers.name:指定 SkyWalking 为默认的 Tracing 提供商。
  • randomSamplingPercentage:覆盖命名空间级别配置,设置 50% 的采样率。
  • customTags:为所有追踪数据添加 env=production 标签。

验证配置

访问网格中的服务(如 Bookinfo 示例应用)生成流量:

curl http://$GATEWAY_URL/productpage

查看追踪数据:

istioctl dashboard skywalking

打开浏览器访问 http://localhost:8080,在追踪界面中查看生成的追踪信息。

image
Skywalking Tracing

点击一个span后,你可以看到其中的追加的 env: production tag。

image
Skywalking Span

总结

Telemetry API 通过其模块化设计、动态更新和多层级支持,大幅降低了服务网格中遥测配置的复杂性。相比 MeshConfig 和 EnvoyFilter,Telemetry API 是一套更灵活、高效的现代化解决方案。我们强烈推荐迁移到 Telemetry API,以充分利用其功能。

韩国旅行回忆:首尔、釜山与仁川的真实体验

2024-12-04 09:46:07

韩国,是我去了一次,可能不会去第二次的国家。难怪韩国人喜欢往外跑,原来是因为他们国家真的没啥好玩的。虽然文化上有不少相似之处,但实际体验却让我感到复杂而矛盾。借着最近韩国发生的政治风波,写下这篇关于我去年韩国之行的记录,既是对旅行的回顾,也是对这个国家的一些思考。

题记

2023 年 10 月,我从中国距离韩国最近的城市威海出发,仅需 1 小时的飞行便抵达仁川机场。韩国与中国一衣带水,但这却是我第一次踏上这片土地。之前,我曾去过两次日本,这两个与中国邻近的国家,旅行体验却有着天壤之别。

这次行程从仁川入境,先前往首尔,再坐火车南下釜山。在釜山停留较久后,返回首尔,从仁川飞回中国。

首尔:匆忙与拥挤

到达仁川机场后,我直接坐火车前往首尔。其间发生了一个小插曲。由于携带的行李较多,在仁川机场买火车票时弄丢了一件。眼看我要买票的那趟火车即将到来,我才发现行李少了一件。当时我火急火燎地出了站台,赶往机场到达大厅。但因为对环境不熟悉,找不到路。正在这时,火车进站检票处的工作人员问我是不是丢了行李。我跟他确认了行李内的物品和身份信息后,取回了丢失的行李,并使用之前购买的火车票重新进站。工作人员很热情,用流利的英语跟我对话。东西失而复得,而且是在火车即将开车之前找回,实在是庆幸。

在首尔的第一晚,我选择住在明洞。这里是一个繁华的商业区,同时也是许多抗议和文化活动的集中地。漫步在明洞街头,我还看到了大量的法轮功宣传。另外韩国还有大量的教会,我在釜山住的地方就靠近一个教会。这种对比让我对韩国的社会氛围有了更深的思考。

我的行程恰逢中秋节,韩国也放假。去南山塔的公交车站挤满了人,等了许久才上车。南山塔俯瞰整个首尔,但繁华和拥挤是我对这座城市最深的感受。

image
首尔南山塔公交站

釜山:更喜欢这里的舒适节奏

比起首尔,我更喜欢釜山的节奏。釜山依山傍海,有美丽的沙滩和繁忙的港口。这里让我想起家乡威海,但更加繁华,也更加国际化。釜山也是韩国与日本贸易的重要港口,这里的一切都洋溢着开放的气息。

image
甘川文化村

在釜山旅行的一个亮点是购买了 Busan Pass,这种专为外国游客设计的旅行通票可以带你游览许多官方景点。釜山的乐天乐园是其中之一,既适合家庭游玩,又充满现代化气息。

image
釜山乐天乐园

另一个难忘的经历是在釜山国际电影节上近距离见到了周润发,并在电影节的特别放映中重温了经典电影《卧虎藏龙》。

image
周润发在参加釜山电影节

仁川:历史与现代的碰撞

行程的最后一天,我在仁川停留了一天,夜晚去了仁川登陆纪念公园。这是一个值得参观的地方,纪念了朝鲜战争期间联合国军队的仁川登陆战役。

image
仁川纪念联合国军的纪念碑

韩国文化:熟悉又陌生

历史建筑,景福宫像袖珍版的故宫,尤其是宫殿内的陈设,很像影视剧中拙劣的道具。但是韩国人还是不遗余力的推广自己的文化,很多白人、黑人穿着他们的传统服装在景福宫内拍照。

image
景福宫

韩国的便利店里有很多种泡面,吃起来味道感觉一般,我个人更喜欢吃杯面。甚至在汉阳公园的 711 里还有专门泡面的机器。

image
汉江公园里的自助泡面机

韩国人喝咖啡真多,咖啡店到处都是,可以说咖啡流淌在韩国人的血液里了。最让我念念不忘的就是 blu shaak 咖啡,既便宜又好喝,这种咖啡有一种咸味。

image
在釜山喝到的 blu shaak 咖啡

韩国景福宫内随处可见的“中国文化”。

image
景福宫公园中的十二生肖

博物馆中很多介绍都只有韩文和英文,没有中文介绍。

image
景福宫内某博物馆中的汉字帖子

韩国美食:单调的味觉体验

韩餐部分吃起来还不错,不过大部分都是泡菜、酱汤、米饭、炸鸡、烤肉之类的,花样太少,远不如中国的饮食丰富,还没有早餐可以吃。

image
韩餐

而且,在韩国便利店里买到的各种小零食,大多也不好吃,这点远不如日本,我觉得在日本的便利店里买到的东西口感都还不错。在韩国我就像一个文盲,一个韩文也不认识,而翻译软件经常翻译的莫名其妙,很多招牌和菜单上都没有英文或汉字,甚至连图片都没有,让人很无语。

image
莫名奇妙的韩文翻译

评价:下次可能不会再来了

总结这次韩国之行,虽然有些亮点,但总体体验不尽如人意。语言障碍、文化隔阂,以及相比之下单调的饮食和高昂的住宿费用,让我感到再来一次的动力不足。不过,釜山的电影节和咖啡,以及仁川的历史氛围,还是让我留下了些许回味的瞬间。

如果你没去过韩国,可以去体验一次;但对于我来说,这一次可能就是最后一次了。

Istio sidecar 和 ambient 模式的网络成本对比

2024-12-02 12:17:21

在服务网格架构不断演进的过程中,了解不同部署模式下的网络成本对于优化性能和资源效率至关重要。本文将对比 Istio 的 sidecar 模式和 ambient 模式的网络成本,分享我在这篇文章中的一些观点。

Sidecar 模式

Istio 的 sidecar 模式通过在每个 pod 旁部署 sidecar 代理来拦截服务间的流量。这种架构引入了额外的网络跳转,可能会增加延迟和计算资源使用量。然而,该模式内置了重要的性能优化特性:本地性感知

图 1 展示了 Application 1 在 Istio sidecar 模式下访问位于不同可用区(AZ)的 Application 2 的流量路径。

image
图 1:Application 1 在 Istio sidecar 模式下访问位于不同可用区(AZ)的 Application 2 的流量路径。

Sidecar 模式的本地化感知

在 Sidecar 模式下,可以使用以下命令查看端点表中的本地性信息,从而更好地理解本地性管理:

istioctl proxy-config endpoint <pod-name[.namespace]> -o yaml

以下是一个示例输出片段,显示了集群 outbound|9080||reviews.default.svc.cluster.local 的端点信息:

- addedViaApi: true
  circuitBreakers:
    thresholds:
    - maxConnections: 4294967295
      maxPendingRequests: 4294967295
      maxRequests: 4294967295
      maxRetries: 4294967295
    - maxConnections: 1024
      maxPendingRequests: 1024
      maxRequests: 1024
      maxRetries: 3
      priority: HIGH
  edsServiceName: outbound|9080||reviews.default.svc.cluster.local
  hostStatuses:
  - address:
      socketAddress:
        address: 10.244.0.98
        portValue: 9080
    healthStatus:
      edsHealthStatus: HEALTHY
    locality:
      region: us-central1
      zone: us-central1-c
    stats:
    - name: cx_connect_fail
    - name: cx_total
    - name: rq_error
    - name: rq_success
    - name: rq_timeout
    - name: rq_total
    - name: cx_active
      type: GAUGE
    - name: rq_active
      type: GAUGE
    weight: 1
  - address:
    # 省略
  - address:
    # 省略
  name: outbound|9080||reviews.default.svc.cluster.local
  observabilityName: outbound|9080||reviews.default.svc.cluster.local;

从中可以看到 sidecar 模式下对 Envoy 代理对 pod 基于负载均衡的细粒度控制,例如 maxConnections, maxRequests, maxRetries 等 circuit breaker 配置,同时包含流量指标和健康状态。这些细节帮助在 Pod 级别管理流量的健康度、稳定性和延迟。

流量负载均衡考虑到 Locality,如 zone 和 region。Envoy 使用这些信息对流量执行更加精准的区域感知流量分配策略(如优先使用同一 zone 内的服务)。

每个 sidecar 代理都会优先将流量路由至同一可用区(AZ)或区域内的服务。这一设计减少了不必要的跨 AZ 流量,从而降低了由数据传输产生的高延迟和高成本。通过将流量限制在本地区域,sidecar 模式能够优化网络路径,避免跨区域的瓶颈。

尽管 sidecar 架构计算密集,但其本地性感知功能在维护高效流量路由方面起到了关键作用,尤其是在多区域云部署中,该功能有助于降低跨区域流量成本。

Ambient 模式

下图展示的 Istio ambient 模式的架构。

image
图 2:Istio ambient 模式

Istio ambient 模式包含两层:

  1. Ztunnel 安全层(L3/L4 流量处理):在此模式下,ambient 模式仅依赖 zTunnel 进行流量管理,主要处理三层和四层的流量,即网络和传输层。这一方式可减少开销,确保基本的连接和安全要求得到满足。

  2. Waypoint 代理层(L7 流量处理):此模式下引入了 waypoint 代理,以扩展至应用层流量,处理高级路由、观测性和策略执行。然而,waypoint 代理的部署位置对性能至关重要。为避免跨 AZ 流量,建议将 waypoint 代理分布于各个 AZ 内,以确保最佳性能。

Ambient 模式的本地化感知

相比之下,ambient 模式通过 ztunnel 和 waypoint 代理实现不同的架构。zTunnel 确保本地感知的流量路由,类似于 sidecar 模式,优先在同一 AZ 内路由流量,从而限制跨 AZ 流量并减少相应的网络成本。

图 3 展示了 Application 1 在 Istio ambient 模式下访问位于不同 AZ 的 Application 2 的流量路径。

image
图 3:Application 1 在 Istio ambient 模式下访问位于不同可用区(AZ)的 Application 2 的流量路径。

注意:图中 Waypoint Proxy 为演示目的单独显示;在实际中,它并不绑定到特定节点,可以与 Ztunnel 同节点部署。

可以通过以下命令查看 Ambient 模式中 Ztunnel 的详细配置和流量分布:

istioctl ztunnel-config workload -o yaml

以下是一个示例输出:

- applicationTunnel:
    protocol: ""
  canonicalName: productpage
  canonicalRevision: v1
  clusterId: Kubernetes
  hostname: ""
  locality:
    region: us-central1
    zone: us-central1-c
  name: productpage-v1-d5789fdfb-gmw5r
  namespace: default
  node: gke-cilium-default-pool-63a77182-f699
  protocol: HBONE
  serviceAccount: bookinfo-productpage
  status: Healthy
  trustDomain: cluster.local
  uid: Kubernetes//Pod/default/productpage-v1-d5789fdfb-gmw5r
  workloadIps:
    - 10.28.2.14
  workloadName: productpage-v1
  workloadType: deployment

从中可以看到 ztunnel 隧道的本地化信息,ztunnel 可以对进出该节点所有 pod 的流量进行集中式管理,比如统一执行负载均衡、健康检查和区域感知等操作。

Waypoint 代理优化

然而,waypoint 代理并非自动具有 AZ 感知功能。关键问题在于它们的部署位置。为优化成本与性能,waypoint 代理需要跨所有 AZ 进行扩展,以便本地处理流量。否则,可能导致跨 AZ 流量和额外成本。此外,当流量进入 waypoint 代理时,原始本地性信息可能被隐藏,进一步增加了路由优化的难度。

为优化性能和成本,建议 waypoint 代理在各个 AZ 内分布,以便能够本地处理流量。此外,ztunnel 与 waypoint 代理的通信设计为接近感知,从而确保流量被路由至最近的 waypoint 代理。这一特性进一步减少了跨 AZ 费用和延迟。

使用 Kiali dashboard 进行可视化

在对比 sidecar 和 ambient 模式时,为了更直观地理解本地性和路由行为,建议使用 Kiali dashboard。Kiali 能够直观展示不同模式下的流量路径,有助于理解 ambient 模式在复杂性上的表现。

image
图 4:Kiali 页面

总结

在对比 Istio 的 sidecar 和 ambient 模式的网络成本时,两种架构都提供了本地性感知的路由以减少跨 AZ 流量。然而,sidecar 模式在每个代理的本地性管理上更加完善,而 ambient 模式需要谨慎管理 waypoint 代理以避免额外成本。此外,需要考虑 ambient 模式的两种子模式(有或无 waypoint 代理)来理解它们对网络成本和性能的不同影响。

如果希望深入了解四种主要的服务网格数据平面部署模式,建议阅读[深入解析服务网格的四种数据平面部署模式:性能、安全性与成本分析]/blog/service-mesh-data-plane-deployment-modes/)。