2025-04-18 16:31:36
本文旨在帮助当前依赖 ingress-nginx
的用户迁移至 Envoy Gateway 并采用 Gateway API。我们将介绍迁移的动因,提供一个基于 Minikube 的实操示例,并展示如 ingress2gateway
工具如何简化整个迁移流程。
Kubernetes 中的 Ingress 控制器是网络流量管理的基础组件,许多团队在初期会选择使用 ingress-nginx,因为它易于部署且社区广泛支持。然而,随着生产环境需求的提升,传统 Ingress API 与 nginx 控制器的局限性也日益显现,比如依赖注解的配置方式难以理解,更新配置时容易导致流量中断等问题。
更值得注意的是,近期的安全漏洞(如 CVE-2025-1974)暴露了继续依赖 ingress-nginx 所带来的安全风险。此外,维护团队已宣布,ingress-nginx 将在 18 个月后进入维护模式(参考视频),这意味着现在是时候评估更现代、更具可扩展性的替代方案了。
Envoy Gateway 是一个值得关注的选择,它原生支持 Kubernetes Gateway API,具备更强的可观测性和可扩展性,能够更好地满足企业级流量管理的需求。
Envoy Proxy 是一个现代的、为云原生设计的代理,具备可观测性、热更新和良好的可运维性。Envoy Gateway(EG) 基于 Envoy 构建,提供了基于 Kubernetes Gateway API 的强大 Ingress 解决方案。
与传统的 Ingress API 不同,Gateway API 提供了 Gateway
、HTTPRoute
和 GatewayClass
等结构化资源,支持更清晰、无注解的配置方式。EG 支持如下高级特性:
这些特性往往可以替代额外的 API Gateway 产品。Envoy Gateway 是完全开源的,并由 CNCF 社区治理。
在动手迁移之前,先来了解 ingress2gateway
工具的工作原理。这个 CLI 工具会扫描现有的 Kubernetes Ingress 资源(特别是为 ingress-nginx
配置的资源),并将其转换为 Gateway API 的资源,即 Gateway
和 HTTPRoute
。该工具不会生成 GatewayClass
,因此用户需要提前创建好并进行引用。借助此工具,用户无需重写所有配置,就能平滑过渡至 Gateway API 和现代的 Ingress Controller(如 Envoy Gateway)。
下面我们将以 macOS 上的 Minikube 为例,演示从 ingress-nginx
迁移至 Envoy Gateway 的完整过程。
minikube start
minikube addons enable ingress
kubectl apply -f - << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
labels:
app: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
containers:
- name: httpbin
image: kennethreitz/httpbin
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
spec:
selector:
app: httpbin
ports:
- port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: httpbin
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: httpbin.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpbin
port:
number: 80
EOF
minikube tunnel
curl -H "Host: httpbin.local" http://127.0.0.1/get
helm install eg oci://docker.io/envoyproxy/gateway-helm \
--version v1.3.2 \
-n envoy-gateway-system --create-namespace
kubectl apply -f - << EOF
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
EOF
安装工具:
go install github.com/kubernetes-sigs/ingress2gateway@latest
转换配置:
ingress2gateway print --providers ingress-nginx | kubectl apply -f -
如果 Ingress 不在
default
命名空间,需添加--namespace
参数。
测试路由:
curl --header 'Host: httpbin.local' http://127.0.0.1/get
终止 tunnel 并关闭 ingress 插件:
minikube addons disable ingress
通过迁移到 Envoy Gateway,你可以获得更加结构化、功能丰富的 Ingress 配置方式。这种方式由 CNCF 社区驱动,支持速率限制、身份认证和 Web 防护等开箱即用的功能,且标准一致、可移植性强。
2025-04-17 20:12:11
注意:本文基于 Envoy Gateway v1.3.2 编写。
在大规模微服务架构中,可观测性是理解与运维系统的核心能力。Envoy Gateway 构建于 Envoy Proxy 之上,提供了丰富的可观测性功能,包括指标、日志和追踪。本文将通过动手实践的方式,讲解如何基于 Prometheus、Loki 和 Tempo 等开源后端,为 Envoy Gateway 的数据平面(即 Envoy proxy 本身)配置可观测性功能。
在开始配置之前,请确保你已经完成 Envoy Gateway 的基本安装。下图展示了 Envoy Gateway 的可观测性组件架构:
OpenTelemetry Collector 是一个可插拔的数据中转组件,负责接收、处理和转发可观测性数据(如指标和追踪),来源包括 Envoy Gateway 等系统。通过将数据生成与数据消费解耦,它能够灵活对接多种可观测性后端(如 Prometheus、Tempo、Jaeger),同时支持数据增强、格式转换和多路导出。
按照官方 快速开始指南 安装 Envoy Gateway:
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.3.2 -n envoy-gateway-system --create-namespace
kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.3.2/quickstart.yaml -n default
使用官方 Helm chart 安装可观测性组件:
helm install eg-addons oci://docker.io/envoyproxy/gateway-addons-helm --version v1.3.2 -n monitoring --create-namespace --set opentelemetry-collector.enabled=true
注意:OpenTelemetry Collector 默认未启用,需显式开启。
安装完成后,将部署以下组件:
组件 | 角色 | 描述 |
---|---|---|
FluentBit | 日志收集器 | 收集并转发日志到 Loki |
Grafana | 可视化界面 | 展示指标、日志和追踪的仪表盘 |
Loki | 日志存储 | 聚合和索引日志 |
OpenTelemetry Collector | 遥测收集器 | 将指标/追踪数据导出到 Prometheus / Tempo |
Prometheus | 指标后端 | 收集并存储 Prometheus 指标数据 |
Tempo | 追踪后端 | 存储和查询分布式追踪数据 |
为了测试可观测性组件,我们可以向 Envoy Gateway 发送一些简单的请求。由于使用的是 Minikube,本地可通过端口转发的方式访问:
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')
kubectl port-forward -n envoy-gateway-system svc/${ENVOY_SERVICE} 8888:80
curl --verbose --header "Host: www.example.com" http://localhost:8888/get
通过以下配置禁用默认的 Prometheus 指标输出,并启用 OpenTelemetry Sink:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
namespace: envoy-gateway-system
spec:
gatewayClassName: eg
infrastructure:
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: unified-telemetry
listeners:
- name: http
protocol: HTTP
port: 80
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: unified-telemetry
namespace: envoy-gateway-system
spec:
telemetry:
metrics:
prometheus:
disable: true
sinks:
- type: OpenTelemetry
openTelemetry:
host: otel-collector.monitoring.svc.cluster.local
port: 4317
EOF
下图展示了 Envoy Proxy 指标可观测性的整体流程:Envoy 原生采集网络流量等关键指标,并通过 /stats/prometheus
接口暴露,Prometheus 进行抓取并在 Grafana 中可视化。此外,Envoy 还支持自定义指标,并可选集成 StatsD 等系统,实现灵活的监控体系。
本地暴露 Prometheus:
kubectl port-forward -n monitoring svc/prometheus 9090:80
访问 http://localhost:9090 并执行如下查询:
topk(1,envoy_cluster_upstream_cx_connect_ms_sum)
kubectl port-forward -n monitoring svc/grafana 3000:80
打开 http://localhost:3000,默认账户密码为 admin/admin
。
详细配置参考 Proxy Metrics 指南。
Envoy Gateway 使用访问日志(Access Log)进行流量记录,支持格式和输出目标的自定义。
应用以下配置,启用将日志发送至 OpenTelemetry Sink:
kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/refs/heads/main/examples/kubernetes/accesslog/otel-accesslog.yaml
通过 Loki 查询日志示例:
curl -s "http://localhost:3100/loki/api/v1/query_range" --data-urlencode "query={exporter=\"OTLP\"}" | jq '.data.result[0].values'
你将看到类似以下格式的输出:
[
[
"1693314563284333000",
"{"body":"[2025-04-17T13:09:23.284Z] \"- - HTTP/1.1\" 400 DPE 0 11 0 \"-\" \"-\" \"-\" \"-\" \"-\"\n","resources":{"cluster_name":"default/eg","k8s.cluster.name":"cluster-1","log_name":"otel_envoy_accesslog","node_name":"envoy-default-eg-64656661-6fccffddc5-662np","zone_name":""}}"
]
]
下图展示了日志可观测性流程:Envoy 支持自定义日志格式、输出到文件/stdout/syslog/HTTP 目标,亦支持按需采样、过滤,并可包含安全相关字段用于审计。
日志配置详情参考 Proxy Access Logs 指南。
kubectl port-forward -n monitoring svc/grafana 3000:80
打开浏览器访问 http://localhost:3000,首次登录使用 admin/admin
。
点击左侧导航栏的齿轮图标 → Data sources,确保 Loki 数据源配置正确,地址为 http://loki:3100
。
下载并导入日志仪表盘:envoy-gateway-logs-dashboard.json
打开 Envoy Gateway Logs 仪表盘,即可查询和过滤日志数据:
追踪提供了请求路径的详细可视化,是定位性能瓶颈的重要手段。
Envoy Gateway 原生支持 OpenTelemetry 格式的追踪,生成带有 Trace ID 和 Span ID 的请求链路数据,可通过配置发送到 Tempo、Zipkin 等支持 OpenTracing 协议的后端。
启用追踪:
kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/refs/heads/main/examples/kubernetes/tracing/default.yaml
暴露 Tempo:
kubectl port-forward svc/tempo 3100:3100 -n monitoring
查询 trace 概览:
curl -s "http://localhost:3100/api/search" --data-urlencode "q={ component=envoy }" | jq .traces
示例输出:
[
{
"traceID": "8010d4fd89e024c0626d984621babd71",
"rootServiceName": "eg.default",
"rootTraceName": "ingress",
"startTimeUnixNano": "1693377719403756000"
}
]
查询指定 trace:
curl -s "http://localhost:3100/api/traces/<trace_id>" | jq
返回信息将包含完整的 trace span 数据,包括服务名、请求起止时间、状态码、上下游节点等详细字段。
详细参考 Proxy Tracing 指南。
在 Grafana 左侧导航栏点击 Data sources,确认已配置名为 tempo
的 Tempo 数据源,地址为 http://tempo:3100
。
下载并导入追踪仪表盘:envoy-gateway-traces-dashboard.json
打开 Envoy Gateway Traces 仪表盘,浏览可用的 trace 数据:
点击任意 trace 可查看其详细的 span 结构:
通过本文的实践操作,你已掌握了如何为 Envoy Gateway 的数据平面启用完整的可观测性功能。结合 OpenTelemetry Collector 的中转能力,以及 Prometheus、Loki 和 Tempo 等后端系统,你可以构建一个具备可扩展性、可插拔性和一致性的可观测性体系,帮助你在无需修改应用代码的前提下,实现对系统流量、性能和错误的深入洞察与排障能力。
2025-04-14 13:16:35
注意:本文基于 Envoy Gateway v1.3.2。
Envoy Gateway 构建在 Envoy Proxy 之上,提供了一套丰富的功能。然而,在某些情况下,你可能希望使用 Envoy Proxy 的一些功能,而这些功能并未通过 Envoy Gateway 的 API 暴露出来。这时就可以使用从 Envoy Gateway v0.5.0 引入的 EnvoyPatchPolicy API。它允许你自定义 Envoy Gateway 生成的 xDS 资源。本文将指导你如何启用该 API,并实现一个非常实用的功能 —— 本地响应修改(Local Reply Modification)。
我们将从前置条件开始介绍,然后讲解如何启用 EnvoyPatchPolicy、如何编写自定义响应逻辑,并最终验证效果。
在开始之前,请确保你已正确安装 Envoy Gateway 和示例资源清单。运行以下命令完成环境准备并确保可以通过 HTTP 访问示例 backend:
# 安装 Envoy Gateway 和示例清单
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.3.2 -n envoy-gateway-system --create-namespace
kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.3.2/quickstart.yaml -n default
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 &
默认情况下,EnvoyPatchPolicy 是关闭的。启用该功能需要创建一个配置文件 ConfigMap,并将其挂载到 Envoy Gateway。执行以下命令:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: envoy-gateway-config
namespace: envoy-gateway-system
data:
envoy-gateway.yaml: |
apiVersion: config.gateway.envoyproxy.io/v1alpha1
kind: EnvoyGateway
provider:
type: Kubernetes
gateway:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
extensionApis:
enableEnvoyPatchPolicy: true
EOF
使用 EnvoyPatchPolicy API,你可以修改 Envoy Gateway 生成的 xDS 资源。目前仅支持 JSONPatch 类型。
Envoy 提供了修改本地响应内容的能力,你可以通过配置 mappers 来指定需要变更的响应内容。每个 mapper 包含一个 filter 和多个改写规则,例如:
Envoy 会按顺序处理这些 mapper,匹配成功后即应用对应改写规则。
我们来构建一个案例:当后端返回 404 时,Envoy Gateway 将其替换为 406,并附带一段自定义文本提示。
下面是该案例的架构图:
执行以下配置:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: custom-response-patch-policy
namespace: default
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: eg
type: JSONPatch
jsonPatches:
- type: "type.googleapis.com/envoy.config.listener.v3.Listener"
name: default/eg/http
operation:
op: add
path: "/default_filter_chain/filters/0/typed_config/local_reply_config"
value:
mappers:
- filter:
status_code_filter:
comparison:
op: EQ
value:
default_value: 404
runtime_key: key_b
status_code: 406
body:
inline_string: "could not find what you are looking for"
EOF
然后我们需要修改示例中的 HTTPRoute,仅匹配 /get
路径:
kubectl patch httproute backend --type=json -n default --patch '[{
"op": "add",
"path": "/spec/rules/0/matches/0/path/value",
"value": "/get",
}]'
接下来我们访问 /find
路径进行验证:
curl --header "Host: www.example.com" http://localhost:8888/find
你将看到如下响应:
could not find what you are looking for
如前所述,由于 EnvoyPatchPolicy 依赖底层的 Envoy 和 Gateway API 结构,未来版本可能存在差异,请关注官方文档并做好兼容性准备。
尽情探索这个强大的扩展机制,让你的 Envoy Gateway 实现更强的可编程能力吧!
2025-04-13 19:22:45
上周,我前往伦敦参加了 KubeCon + CloudNativeCon Europe 2025,这是云原生领域在欧洲一年一度的盛会。今年的大会汇聚了超过 12,500 名开发者、维护者和用户,场面热烈、话题深度十足。
为了更好地总结这次大会的内容和趋势,我制作了一份 HTML/PDF 格式的报告,对重点主题进行了归纳,包括:
欢迎你阅读报告,也欢迎通过评论、邮件等方式与我交流你对大会趋势的看法!
2025-03-27 14:57:27
过去一年中,我一直享有 GitHub Copilot 的免费使用资格,但是由于种种原因,我并没有深入地使用它。最近看到了 GitHub 官方发布的一篇关于 Copilot 的博客《Mastering GitHub Copilot: When to use AI agent mode》,让我对如何更好地使用 Copilot 有了新的灵感和思考。
在这篇文章里,我想和大家分享一下我对 Copilot 强大功能的理解,尤其是 Copilot Edits 和 Agent Mode 这两个模式之间的差异和使用场景。最后,我还想呼吁所有开源项目的贡献者:如果你符合条件,一定要去积极申请 Copilot 免费使用资格,让自己的开发效率更上一个台阶!
大多数开发者在接触 AI 辅助编码工具(比如 GitHub Copilot)时,都会或多或少地遇到一些状况,比如:
其实,这些小挫折往往不在于工具本身,而在于你是否找对了使用方式。GitHub Copilot 内部包含多个侧重点各不相同的功能,它们各自适合在不同的情景下使用。正确地选择合适的功能,就是解锁 Copilot 真正实力的关键。
Copilot Edits 的功能就像是给你配备了一个能读懂上下文的“超级编辑器”。你可以快速发出命令,让它在有限范围内对现有代码进行改动,并在提交前查看 diff
,随时保持对改动的掌控。
与 Copilot Edits 相比,Agent Mode 更像是一个能够宏观统筹全局的 AI 助手。它不只是在一个文件里给你提建议,更可以去你的整个项目里做深度搜索、自动找出依赖关系、创建或修改多个文件,甚至可以帮你在终端里运行命令、编译、测试项目等。
UserService
写测试并确保全部通过”。博主(也就是我)在给个人网站的 GitHub Action 中增加一个更新索引文件的工作,可以告诉 Copilot Agent:
“给我的 GitHub Action 中增加一个更新 search index 的任务并在本地测试”
然后 Copilot Agent 会扫描我的代码库,聪明地在我的 GitHub Action 配置文件中帮我插入相应的任务,并会自动的安装依赖软件并运行测试。
这就是 Agent Mode 的强大之处,它可以一次性处理全局级别的改动,真正让 AI 成为你的“对等”开发伙伴。
无论你是想使用 Copilot Edits 还是 Agent Mode,你都会用到 VS Code 里的 Copilot Chat 窗口:
/explain
理解复杂代码片段。/fix
让 Copilot 帮你调试。/tests
为给定代码自动生成测试用例。记住:你提供的上下文信息越完整,Copilot 生成的回答就越准确。请不要吝啬给它多一些提示!
原文中强调了一点:Copilot Edits 和 Agent Mode 并不是二选一的对立关系,而是相辅相成。
AI 只是辅助,我们才是项目的主导者,无论在任何模式下,你都随时拥有最终的决定权。与 AI 协作的关键是:在发起需求时确保“意图”足够清晰,并在生成代码后自行进行必要的审查和测试。
verifyUserToken
”。diff
,确认无误后再点「接受更改」。在国内外,你的个人和团队如果对开源社区有贡献——比如在 GitHub 上维护或积极参与开源项目,就有机会免费申请 GitHub Copilot,这对提高工作效率、让团队更专注于关键业务逻辑而言非常有帮助。
建议把你的 GitHub Profile、开源项目链接、贡献度、Stars 等信息准备好,申请通过后就可以体验到 Copilot 的强大功能。
别担心! 只要你确实为开源生态做出过贡献,GitHub 官方是很鼓励你去申请 Copilot 的免费使用资格的。需要注意的是该免费资格是按月赋予的!
从最初的 GitHub Copilot 到如今逐渐涌现的各种 AI 编程工具,比如 Cursor、Amazon CodeWhisperer、Google Gemini Code Assist、以及基于大语言模型的各种插件等等,AI 编程助手已经不再是新鲜事。Cursor 的特点在于提供类似 IDE 的环境,可直接在其编辑器里集成对话式的 AI 辅助;Replit 的 Ghostwriter 则充分利用 Replit 在线编程环境的优势,为多人协作和实时预览提供极大方便。和 Copilot 相比,这些工具可能在对话交互深度、代码质量、或对特定语言和生态的支持范围上各有所长。但总体而言,它们都在让开发者摆脱那些冗杂、重复、机械的编程工作,从而腾出更多时间和精力进行架构和创新。
“AI 不会取代程序员,但会取代那些拒绝与 AI 合作的程序员。”
如果你正在或即将投入开源项目的开发,或者在商业项目中想要挖掘更多高阶生产力,都推荐你去尝试并深入学习这些 AI 编程工具。在 GitHub 官方文档 中,你还可以找到一份从入门到进阶的 Copilot 教程系列——从最初的安装到高级用法,让你快速掌握 Copilot 的精髓。也欢迎试用其他同类工具,对比各种功能优缺点,探索适合自己团队的工作流。
让我们一起拥抱 AI,做更高效的开发者吧!
如果你对 AI 编程、云原生和开源技术感兴趣,也欢迎访问我的个人博客 jimmysong.io,一起交流讨论。祝大家编码愉快,效率倍增!
2025-03-22 14:45:55
欢迎阅读我的这篇博客——“超越 Sidecar:深入解析 Istio Ambient Mode 的流量机制与成本效益”。本文内容源自我在 KCD 北京的一次演讲。主要探讨的是 Istio 全新推出的一种数据面模式 —— Ambient Mode。它的核心理念是去除 Sidecar,减少资源开销与运维复杂度。本文将带大家了解 Ambient Mode 的出现背景、核心组件、流量路径机制以及与现有 Sidecar 模式的对比,从而帮助你快速评估并上手这项新特性。
首先,我们来思考一个问题:为什么要关注、甚至尝试这种新模式?Sidecar 在服务网格里一直都用得好好的,为什么要“去 Sidecar”呢?
让我们看看当前服务网格面临的一些问题和挑战。
思考:有没有一种方式在保留服务网格核心能力(安全、可观测、流量控制)的同时,减少对每个 Pod 的侵入和额外资源消耗?
服务网格架构一直在探索代理部署位置的多种可能性。例如:
这些模式在功能、安全、性能和管理复杂度上都有不同的侧重。Istio Ambient Mode 则是针对 Sidecar 带来的高资源消耗和运维成本,而提出的新尝试。
以下表格是对比常见服务网格部署模式的一些简要特点:
模式 | 安全性 | 效率 | 可管理性 | 性能 |
---|---|---|---|---|
Sidecar 模式 | 高安全性,隔离的代理 | 资源使用率高 | 集中化管理但较为复杂 | 增加一定延迟 |
Ambient 模式 | 通过 ztunnel 提供安全性,仍在发展中 | 更高效,共享代理 | 管理更简单但功能在完善中 | 良好;跨可用区时需注意网络开销 |
Cilium mesh | 中等安全性,基于 eBPF | 内核级效率 | 配置复杂 | 可视场景不同而异 |
gRPC | 应用集成安全,依赖应用自身 | 高效 | 更新管理复杂 | 低延迟,适用于实时场景 |
接下来我们正式进入第二部分,深入看看 Ambient Mode 的具体组件,包括 ztunnel、Waypoint Proxy 以及 Istio CNI 在其中扮演的角色。
istio-init
容器,负责流量劫持在 Ambient 模式下,Istio 数据面可分为两层:
Control Plane 依然由 Istiod 提供,主要负责给 ztunnel、Waypoint 下发配置和证书。
istio-init
容器,使安装更加清晰简洁。iptables REDIRECT
规则。这张图简单示意了 Istio CNI 如何与 Kubernetes 本身的网络插件(如 Calico、Cilium 等)组合在一起。它修改了本机的 CNI 配置,增加了 CNI 链,在 Kubernetes 分配完 Pod IP 后,紧接着就会执行 Istio CNI 的拦截逻辑,把网络流量规则注入到 Pod netns。并且为不同模式中 Pod 配置不同的 iptables 规则。 这样就与原本的 CNI 配置(包括网络策略)形成一个链式流程,不会相互冲突。
这张图详细描绘了当 Pod 启动时,Istio CNI 会怎么做:
介绍完组件之后,我们来看看最核心的“流量路径”。zTunnel 和 Waypoint 究竟是怎么拦截并转发流量的?我们会从透明流量拦截、HBONE 协议等角度进行解析。
在 Ambient 模式中,Istio CNI 会在 Pod 网络命名空间中注入 iptables 规则,将出站流量透明拦截到所在节点的 ztunnel 进程。之后由 ztunnel 决定是直接进行 L4 转发,还是将流量转发至 Waypoint Proxy 做进一步的 L7 处理。
如图所示,Kubelet 在节点上启动了一个 Pod,这个事件被 Istio CNI Agent 监听到,Istio CNI Agent 进入 Pod 的网络空间,设置 iptables 规则将流量重定向到本地 socket,并将 Pod 的文件描述符(FD)发送为 ztunnel。ztunnel 获取到 FD 之后就可以在 Pod 的网络空间中创建 socket。
Pod 在发送流量时,本该直连目标地址,但是 iptables 规则会把它拦截到本节点的 ztunnel 进程里,然后 ztunnel 决定这条流量需不需要交给 Waypoint 做 L7 代理。 如果不需要,就直接在 L4 层把它加密转发到目标 Pod;如果要 L7,例如鉴权,就再把流量隧道给 Waypoint。
Ambient 模式中,zTunnel 与 Waypoint 之间使用 HBONE (HTTP/2 + CONNECT) 协议来建立安全隧道,实现 mTLS 加密 和多路复用,减少额外的连接开销,简化代理转发流程。
下面是一个简化的 HBONE CONNECT 请求示例,利用 x-envoy-original-dst-host
、x-istio-auth-userinfo
等头信息来传递路由和身份认证所需上下文。
:method: CONNECT
:scheme: https
:authority: Pod_B_IP:9080
:path: /api/v1/users?id=123
x-envoy-original-dst-host: Pod_B_IP:9080
x-forwarded-proto: hbone
x-istio-attributes: ...
...
在这个示例里,假设 ztunnel A 需要把流量发送给 目标节点 B,我们可以看到外层的 TCP 连接其实是从 ztunnel_A_IP:52368 连到 Node_B_IP:15008。这是 ztunnel A 和 ztunnel B 之间的隧道端口,15008 就是 HBONE 监听端口。
进入到 HTTP/2 层后,就会有一个 CONNECT 请求,里面的 :authority
显示的是 Pod_B_IP:9080,表示实际上要连到 Pod B 的 9080 端口。x-envoy-original-dst-host
里也能看出相同信息。
同时我们看到了一些自定义头,比如 x-forwarded-proto
、x-istio-attributes 等,用来给目标 ztunnel 或后续代理带去更多上下文和安全验证信息。
可以把这个理解为:在 HTTP/2 CONNECT 之上,流量就像加了一个“内层”隧道,把应用层的请求(例如 /api/v1/users?id=123
)封装在这里面,然后在 ztunnel B 端解封装并转发到真实的 Pod B。
整个过程对应用来说是透明的,但对我们来说,通过查看这种 CONNECT 请求头,可以了解 Ambient 模式如何在 HTTP/2 层做流量路由和身份认证。这就是为什么说 HBONE 比传统的 Sidecar-to-Sidecar通信更加灵活,也更便于做 mTLS 以及 L7 扩展。
如果源 Pod 和目标 Pod 恰好在同一个节点上,流量会走 ztunnel 的 L4 加密流程。 这里显示,ztunnel 是使用 DaemonSet 部署在每个节点上的,并且使用了host Network,共享主机的网络。Istio CNI 将 Pod 的出站流量拦截到 ztunnel的15001端口,如果源和目的 pod 在同一个节点上,ztunnel 直接在内部完成加解密后将流量发送到目的地 pod。
如果需要 L7 的流量处理,比如鉴权,ztunnel 就会与 Waypoint 代理建立 HBONE 隧道,经过 Waypoint 代理的转发到目的 Pod。
这是跨节点的情况,也就是最常见的场景:
源节点的 ztunnel 把流量通过 HBONE 隧道加密后发给目标节点的 ztunnel;目标节点 ztunnel 解封装,再把明文流量递给目标 Pod。只要是纯 L4 无需 L7,就不必加一层 Waypoint,减少了代理链路。
当我们需要 L7 处理时,流量就会多经过一下 Waypoint。也就是:
这个流程比 L4 多了一次代理,但好处是只有特定流量才会被 L7 代理解析,减少不必要的开销。
对于非 Istio网格内部的流量,通过 Pod IP和端口直接访问 Pod时,为了防止这些流量逃出 ztunnel的掌控,也需要拦截这些流量。如果流量是访问的应用端口,通过判断数据包上是否带有 0x539 标记,如果没有,则将其转发到 ztunnel 监听的 15006 明文端口,经 ztunnel 处理后会带上 0x539 标记,然后就可以访问应用的目标端口了;如果流量的目的端口是 15008,那么实际上就会被 ztunnel 监听和处理,判断 HBONE 协议。
流量类型 | 处理位置 | 示例场景 |
---|---|---|
L4 | ztunnel(透明转发) | TCP 级别流量,不需应用层策略 |
L7 | ztunnel → Waypoint Proxy | HTTP/gRPC 需要鉴权、熔断、路由、可观测等高级功能 |
对于大部分只需 TCP 层加密和转发的流量,Ambient Mode 仅通过 ztunnel 即可;只有在需要 HTTP 层策略时才会额外经过 Waypoint。
有了对 Ambient 的了解后,我们还是得和原有的 Sidecar 模式做对比,来看看哪些功能还不完善,哪些场景更适合 Ambient。
与传统 Sidecar 模式相比,Ambient 目前仍有一些不完善之处:
指标 | Sidecar 模式 | Ambient 模式 |
---|---|---|
代理位置 | 每个 Pod 都运行 Envoy Sidecar | Node 级 ztunnel + 可选的 Waypoint Proxy |
资源开销 | 在大规模场景下 CPU/内存消耗相对更高 | 相对更低:代理共享在节点/命名空间级 |
运维复杂度 | 升级 Sidecar 需滚动更新所有关联 Pod,操作较繁琐 | 部署/升级集中在少数组件(ztunnel / Waypoint),运维更简单 |
性能 | 每个 Pod 都有 Envoy,使得隔离性更强,但整体有额外代理开销 | L4 性能较好,L7 场景需要多经过一次 Waypoint 转发 |
功能完整度 | 成熟稳定,支持多集群、VM、混合网络 | 尚在演进,多网络、VM 等高级场景支持仍在完善 |
典型使用场景 | 注重严格隔离或依赖特定的 EnvoyFilter、WASM 插件等深度定制 | 大规模集群、需要轻量化管理且大部分流量以 L4 为主的场景 |
好的,最后我们来总结一下 Ambient Mode 的优缺点,以及当前适合哪些场景。
你也可以通过 jimmysong.io 网站找到更多云原生相关的文章和实践分享。如果对此文或 Istio 有任何疑问,欢迎给我留言或在社区中交流。谢谢!