MoreRSS

site iconJimmy Song | 宋净超修改

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

Inoreader Feedly Follow Feedbin Local Reader

Jimmy Song | 宋净超的 RSS 预览

Istio 安装方式深度剖析——选择与实践指南

2025-02-27 13:47:35

随着 Istio 版本迭代,其的安装方式和工具链也在不断演进。从 istioctl 到 Helm,再到曾经的 Istio Operator,用户常常会面临选择困境:到底哪种方式最适合我的场景?在最近的交流中,我经常遇到关于 Istio 安装方式选择的问题,特别是围绕 IstioOperator API 和已废弃的 Istio Operator 组件的区别。今天,我将以技术实践者的视角,带你梳理 Istio 的安装之道,拆解关键问题,并给出生产级建议。

Istio 安装方式一览

Istio 提供了多种安装路径,每种方式都有其设计初衷和适用场景。以下是当前主流选项:

  • istioctl:官方推荐的安装工具,集验证、定制和运维于一体,几乎是生产环境的标配。
  • Helm:Kubernetes 生态的包管理利器,适合 Helm 重度用户或 CI/CD 集成场景。
  • Istio Operator(已废弃):曾经的集群内管理方案,如今已退出历史舞台。

接下来,我们逐一剖析这些方式的核心特点,以及背后的取舍逻辑。

istioctl:生产环境的不二之选

在 Istio 中,istioctl 被官方定位为首选安装工具。它的优势显而易见:

  • 强大的配置验证:在安装前,istioctl 会对配置进行静态检查,避免潜在问题。比如,使用 istioctl analyze 可以快速定位配置文件中的错误。
  • 灵活的定制能力:通过 IstioOperator API,你可以精确控制安装细节,比如只启用 Pilot 或调整网关配置。
  • 生产就绪的特性:从健康检查(istioctl verify-install)到增量升级,istioctl 提供了全生命周期支持。
  • 安全优先:相较于集群内控制器,istioctl 在本地运行,避免了高权限组件带来的安全隐患。

实践中的一个简单例子:

istioctl install --set profile=default -y

这会快速部署默认配置。如果需要更细粒度的控制,可以搭配 YAML 文件(后文详解)。

适用场景:生产环境、新用户、需要高度定制的场景。

Helm:生态集成下的备选方案

Helm 是 Kubernetes 生态的老朋友,Istio 也提供了官方 Helm chart。它的亮点在于:

  • 与 Helm 生态无缝对接:如果你的集群已经在用 Helm 管理资源,Istio 的 Helm 安装可以直接融入现有工作流。
  • 自动化友好:Helm chart 的版本化和声明式特性,非常适合 CI/CD 管道。

但 Helm 并非没有短板:

  • 验证能力不足:相比 istioctl,Helm 的配置检查较弱,错误往往在运行时暴露。
  • 组件管理复杂:比如安装 Egress Gateway,Helm chart 的支持不够完善,社区反馈中常有人提到需要额外调整(参考 GitHub Issue #43826)。

适用场景:已有 Helm 工作流、CI/CD 驱动的项目。

Istio Operator 的兴衰

如果你接触过早期 Istio,可能会对 Istio Operator 有所耳闻。这是一个运行在集群内的控制器,负责根据配置管理 Istio 安装。然而,从 1.23 版本起,它已被官方废弃。原因何在?

  • 安全考量:集群内高权限组件容易成为攻击目标,增加了运维风险。
  • 功能冗余:社区调查显示,其使用率不足 10%,而 istioctl 已能完全覆盖其功能(参考 GitHub Discussion #166)。

现有用户可以继续运行旧版本,但无法升级到 1.24+。对于新项目,我的建议是直接跳过这一选项。

拨云见日:IstioOperator API vs. Istio Operator

讨论中常出现的一个困惑是:IstioOperator API 和 Istio Operator 有什么区别?让我们一次性讲清楚:

  • IstioOperator API:一个声明式的配置接口,用于定义 Istio 安装的期望状态。它并未废弃,而是 istioctl 的核心依赖。
  • Istio Operator:已废弃的集群内控制器,过去负责解析 API 并执行安装。

类比一下:API 是设计图纸,Operator 是施工队。现在,istioctl 取代了施工队,效率更高,风险更低。

实战:如何使用 IstioOperator API

IstioOperator API 是 Istio 安装的灵魂,允许你通过 YAML 文件灵活定制配置。以下是一个典型流程:

  1. 编写配置文件

    假设我们要启用 Egress Gateway:

    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
      profile: default
      components:
        egressGateways:
          - name: istio-egressgateway
            enabled: true
    
  2. 部署配置

    执行:

    istioctl install -f istio-config.yaml
    

    这种方式的好处在于声明式管理,修改后重新运行即可实现增量更新。比如,要调整资源限制,只需更新 YAML 并再次应用。

组件更新与扩展

安装完成后,如何添加或更新组件(如 Egress Gateway)?istioctl 的答案简单直接:

  • 编辑 YAML,添加新配置。

  • 运行:

    istioctl install -f updated-config.yaml
    

    istioctl 会自动计算差异,完成增量部署。

Helm 更新则稍显繁琐,可能涉及 chart 调整或手动干预,尤其在非常规组件上。

总结与生产建议

通过这次深入剖析,我们可以得出以下结论:

  • istioctl 是王道:它兼具安全性、灵活性和生产就绪特性,适合绝大多数场景。
  • Helm 有其一席之地:如果你深陷 Helm 生态,不妨一试,但要做好额外配置的准备。
  • Istio Operator 已成历史:新项目无需考虑,现有用户应规划迁移。

作为一个在开源领域摸爬滚打的实践者,我建议从 istioctl 入手,结合 IstioOperator API,既能快速上手,又能满足复杂需求。Istio 的安装看似复杂,但掌握核心逻辑后,你会发现它其实很有条理。

有任何疑问,欢迎留言交流,一起解锁服务网格的更多玩法!

参考资料

Istio Ambient 模式:图解及概念解读

2025-02-13 18:20:14

Istio 的 Ambient 模式是一种创新的、无 Sidecar 的服务网格部署方式,通过 ztunnel 和 waypoint proxy 分离数据平面功能,简化了操作并降低了资源消耗。本篇博客将通过一份详细的术语表,帮助你更好地理解 Istio Ambient 模式中的关键概念及其背后的技术实现。

Ambient 模式

image
Ambient 模式架构图
  • 定义:Istio 的一种无 Sidecar 的数据平面模式,通过 ztunnel 和 waypoint proxy 实现服务之间的安全通信和管理。相较于 Sidecar 模式,Ambient 模式更加轻量,降低了资源消耗并简化了配置。
  • 架构:数据平面功能分为 L4 层的安全覆盖层(由 ztunnel 提供)和 L7 层的策略处理层(由 waypoint proxy 提供)。

控制平面与数据平面

image
控制平面与数据平面
  • 定义:在 Ambient 模式中,控制平面(istiod)负责管理集群内 ztunnel 和 waypoint proxy 的配置和策略,而数据平面由 ztunnel 和 waypoint proxy 组成,负责处理实际的网络流量。
  • 组件交互:ztunnel 使用 xDS APIs 从 istiod 获取配置并执行策略,管理 Pod 之间的 L4 和 L7 流量。

Istio Control Plane (istiod)

  • 定义:Istio 的控制平面组件,负责与 ztunnel 和 waypoint proxy 通信,提供 xDS 接口用于动态配置。
  • 功能istiod 使用 xDS APIs 进行配置推送,动态管理 Ambient 模式中的流量策略、证书分发以及与 Kubernetes 集群的交互。

透明性与非侵入性

  • 定义:Ambient 模式的架构旨在减少对应用的侵入性,应用无需感知数据平面的存在,Pod 无需重启或注入 Sidecar 即可加入网格。
  • 优势:提高了服务网格的灵活性,降低了操作复杂度,使应用和基础设施的生命周期更加解耦。

Sidecar Proxy

image
Sidecar 模式
  • 定义:传统 Istio 中的 Envoy 代理,与应用容器共同部署在一个 Pod 中。
  • 问题:对应用具有侵入性,Sidecar 必须在 Pod 中注入并伴随应用运行,增加了资源开销,并且使应用与代理的生命周期耦合。

Ztunnel (Zero-Trust Tunnel)

image
ztunnel
  • 定义:Ambient 模式中的关键组件,部署为 DaemonSet,为每个节点提供 L4 层的零信任隧道。
  • 功能:
    • 安全:提供 mTLS 加密和基于 SPIFFE ID 的身份验证,确保节点和工作负载之间的安全通信。
    • 可观测性:收集 L4 层的 TCP 指标和日志。
    • 连接多路复用和均衡:在节点之间建立安全的流量隧道,以优化连接和网络性能。
    • 多租户架构:单个 ztunnel 可以代表同一节点上的多个工作负载进行 L4 数据平面功能处理,这与每个应用 Pod 拥有自己代理的 Sidecar 模式形成对比。
    • 证书管理:ztunnel 代表节点内的所有 Pod 从 Istio 控制平面 (istiod) 获取 mTLS 证书,并负责证书的管理和轮换。
  • 接口:
    • pistioinpistioout:用于与节点上的 istioinistioout 接口通过 GENEVE 隧道连接。

Waypoint Proxy

image
Waypoint Proxy
  • 定义:Ambient 模式中的 L7 层代理,部署在每个命名空间级别,用于处理 L7 层请求。
  • 功能:提供 L7 授权策略,如基于 HTTP headers 的访问控制、L7 级别的遥测等。Waypoint Proxy 只处理需要的 L7 代理流量,其他 L4 流量由 ztunnel 处理。

GENEVE 隧道 (Generic Network Virtualization Encapsulation)

image
GENEVE 协议组成
  • 定义:用于在 Kubernetes 节点之间建立虚拟隧道连接,将流量从节点上的 Pod 转发到 ztunnel。
  • 在 Ambient 模式中的应用:GENEVE 隧道用于连接节点上的虚拟网络接口(istioinistioout)与 ztunnel 内的接口(pistioinpistioout)。

HBONE (HTTP-Based Overlay Network Environment)

image
HBONE 数据包格式
  • 定义:Istio 特有的安全隧道协议,用于在 Ambient 模式组件之间传输数据。HBONE 是一种基于 HTTP/2 和 HTTP CONNECT 建立的安全 mTLS 加密通道。
  • 实现方式:通过 HTTP/2 进行多路复用,通过 HTTP CONNECT 建立隧道,并使用 mTLS 确保安全性。详见 Istio 文档

Istioin 和 Istioout 虚拟接口

image
Ambient 模式中两个位于两个不同节点上的 Pod 访问路径
  • 定义:由 Istio CNI 插件在每个节点上配置的两个虚拟接口,用于处理进入和离开节点的流量。
  • 功能istioin 处理进入节点的流量,istioout 处理离开节点的流量。两者通过 GENEVE 隧道连接到 ztunnel 中相应的接口。

iptables 和流量重定向

  • 定义:用于配置 Linux 内核中的流量规则,将来自 Ambient 工作负载的流量进行重定向和标记。
  • 在 Ambient 模式中的应用:Istio CNI 插件通过 iptables 规则,将流量标记并重定向到 istioinistioout,然后通过 GENEVE 隧道传递给 ztunnel。

流量拦截与重定向 (Traffic Redirection)

  • 定义:Ambient 模式中,ztunnel 负责透明拦截所有进出 “in-mesh” Pod 的流量并将其加密后重定向到其他节点上的目标 Pod,确保网络流量符合服务网格的安全策略。
  • 机制:通过 Istio CNI 插件安装的 iptables 规则或 eBPF 程序,ztunnel 能够透明地捕获工作负载的流量,并在不改变客户端应用的情况下进行安全代理。

流量路径分类

  • Out of Mesh:Pod 没有加入服务网格,流量不会被 Ambient 数据平面处理。
  • In Mesh:Pod 被纳入 Ambient 数据平面,L4 层的流量被 ztunnel 拦截和处理,提供 L4 授权和安全加密。
  • In Mesh, Waypoint Enabled:Pod 被纳入 Ambient 数据平面且启用了 waypoint proxy,L7 层的流量通过 waypoint 进行高级策略处理。

TPROXY

image
TPROXY 作为透明代理,客户端和服务端都对其无感知
  • 定义:Linux 内核功能,用于透明拦截和重定向网络流量。
  • 在 Ambient 模式中的应用:ztunnel 使用 TPROXY 来拦截和处理流量,保留原始源 IP 和端口信息,从而实现透明代理功能。

Mutual TLS (mTLS)

image
Istio 中的安全身份架构(以 Sidecar 模式为例)
  • 定义:一种双向 TLS 认证机制,确保通信双方的身份验证和数据加密。
  • 在 Ambient 模式中的应用:通过 ztunnel 和 waypoint proxy 确保工作负载之间的 mTLS 加密,实现零信任安全。

详见 如何理解 Istio 中的 MTLS 流量加密?

SPIFFE ID

image
SPIFFE ID 格式

Istio 服务网格中所有工作负载将根据其服务账户注册 SPIFFE 标准的服务身份格式:spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>

  • 定义:用于标识工作负载的身份标识符,在服务网格中用于身份管理。
  • 在 Ambient 模式中的应用:SPIFFE ID 被用于对节点和工作负载进行身份验证,以确保网络通信的安全性。

详见 为什么 Istio 要使用 SPIRE 做身份认证?

eBPF (Extended Berkeley Packet Filter)

  • 定义:eBPF 是 Linux 内核中的一种技术,用于在内核空间中运行沙盒程序,实现网络数据包处理等功能。
  • 在 Ambient 模式中的应用:eBPF 可以替代传统的 iptables 和 GENEVE 隧道,用于流量重定向和管理。eBPF 更高效、复杂度更低且易于管理。
  • eBPF 程序:
    • 应用入站
    • 应用出站
    • Ztunnel 主机入站
    • Ztunnel 入站
  • 作用:Istio CNI 使用 eBPF 程序将它们挂载在特定的 TC 点,用于处理应用和 ztunnel 的网络流量。

Waypoint Proxy 的弹性扩展

image
Waypoing Proxy 作为 Deployment 部署在 Kubernetes 中
  • 定义:在 Ambient 模式中,waypoint proxy 可以根据流量需求动态扩展,而无需为每个工作负载实例部署独立代理。
  • 优势:通过动态扩展 waypoint proxy,可以降低基础设施成本并提高资源利用率。

Ztunnel 的弹性和故障恢复

  • 定义:ztunnel 部署为 DaemonSet,如果 ztunnel 容器失效,Kubernetes 会自动重新调度,以确保节点流量的继续处理。
  • 特点:使得故障的影响范围最小化,仅影响该节点上的工作负载。

IP Set 和 ztunnel-pods-ips

  • 定义:IP Set 是用于存储 IP 地址的工具,ztunnel-pods-ips 是每个节点上用于存储 Ambient 网格 Pod IP 的集合。
  • 在 Ambient 模式中的应用:Istio CNI 插件会将每个加入 Ambient 网格的 Pod IP 添加到 ztunnel-pods-ips 中,以确保这些 Pod 的流量可以被 iptables 规则识别和处理。

连接多路复用 (Connection Multiplexing)

  • 定义:在单个物理连接中传输多条逻辑连接的技术。
  • 在 Ambient 模式中的应用:ztunnel 实现了连接多路复用,使多个工作负载可以共享相同的连接,提升网络效率。

节点网络的虚拟接口对 (veth)

  • 定义:每个 Pod 在运行时会在节点上创建一个虚拟接口对,用于将 Pod 的网络连接到节点的网络。
  • 在 Ambient 模式中的应用:veth 接口用于将 Pod 的流量连接到节点的虚拟接口(如 istioinistioout),从而将流量引导至 ztunnel 进行处理。

Waypoint Proxy 的流量路径

image
Waypoint Proxy 的流量路径
  • 定义:Waypoint Proxy 只参与服务器端的流量路径,作为 L7 代理执行服务端的请求。
  • 应用场景:当部署了 Waypoint Proxy 时,来自同一服务账户的工作负载将通过 ztunnel 重定向至 Waypoint Proxy 进行处理,然后到达目标 Pod,确保 L7 级别的策略和认证得以执行。

Istio CNI (Container Network Interface)

  • 定义:Istio 的容器网络接口插件,用于在 Kubernetes 集群中自动配置流量拦截规则。
  • 功能:Istio CNI 负责为每个新创建或加入网格的 Pod 设置必要的网络重定向规则。它通过修改 iptables 规则或应用 eBPF 程序来确保所有流量能够被 ztunnel 或 waypoint proxy 拦截和处理,从而实现服务网格的透明流量管理。
  • Istio CNI Node Agent:Istio CNI Node Agent 负责在每个节点上安装 Istio CNI 插件,并更新节点的 CNI 配置,确保当 Pod 加入服务网格时能够正确地配置流量重定向规则。在 Sidecar 模式中,CNI 插件通过 iptables 配置 Pod 的网络。在 Ambient 模式中,CNI 插件负责将新的 Pod 事件推送到 Ambient 监控服务器,以便配置 Pod 的网络重定向规则。

总结

Istio Ambient 模式通过将数据平面功能分为 L4 和 L7 层的独立组件,为用户提供了更轻量且灵活的服务网格解决方案。这种方式不仅简化了服务的部署,还大幅降低了资源开销。通过术语表的方式,我们探讨了 Ambient 模式中的各种核心概念,从 ztunnel 到 waypoint proxy,再到 iptables 和 eBPF 的使用,帮助你全面了解 Istio Ambient 模式的架构和运行机制。如果你对服务网格感兴趣或正在考虑如何优化微服务通信,希望这篇文章对你有所帮助。

免费的 AI 绘图工具推荐:Raphael.app

2025-01-21 10:02:05

在如今各种 AI 工具层出不穷的时代,找到一个好用又免费的绘图工具真的不容易。而 Raphael.app 就是一款非常值得一试的 AI 绘图工具。它简单易用,而且用英文提示词就能生成效果不错的图片。

image
Raphael.app 页面

Raphael 简介

这款以文艺复兴三杰之一拉斐尔(Raphael,全名:Raffaello Sanzio da Urbino,1483 年 4 月 6 日-1520 年 4 月 6 日)命名的工具,有以下特点:

  1. 完全免费:市面上很多 AI 绘图工具要么功能受限,要么需要订阅才能解锁更多功能,而 Raphael 完全免费(至少到撰写本文为止,网站中承诺免费),无需付费也能用它创造出不错的作品。
  2. 支持英文提示:只需要用英文简单描述你想要的图片,比如“A cat-like colorful cat”,Raphael 就可以根据提示生成对应的画面。
  3. 效果还不错:虽然和一些高端付费工具相比还有提升空间,但 Raphael 生成的图片已经足够让人满意了,尤其对于新手或尝试 AI 绘图的人来说,它完全够用。

谁适合用 Raphael?

  • 艺术爱好者:可以用它来寻找创作灵感。
  • 内容创作者:为博客、视频或社交媒体增加独特的视觉元素。
  • 学生和老师:为作业或课件增添一些创意。
  • AI 绘图初学者:零成本尝试 AI 艺术创作。

如何使用?

操作非常简单:

  1. 打开 raphael.app,无需注册或登录。
  2. 输入你想要的图片描述,用英文提示词效果会更好。
  3. 点击“生成”,等待 10 秒钟左右 AI 生成图片,这一步可能需要经过 CloudFlare 的自动人机验证。
  4. 你还可以选择对生成的图片进行精修。
  5. 下载或者直接分享生成的作品。
image
使用 Raphael 生成的图片(一只长的像猫的五彩缤纷的鸟)

总结

Raphael 是一个用起来特别方便的 AI 绘图工具,既免费又能生成效果不错的图片。不管你是想找灵感还是单纯玩玩 AI,都非常值得一试。

探索云原生可观测性:技术与团队协作的深度结合

2025-01-20 16:50:25

最近读了 TheNewStack 发布的电子书《Cloud Native Observability for DevOps Teams》,虽然这本书是 2022 年出品的,但给我了很大的启发。它不仅讨论了技术工具,还深入探讨了团队协作、文化建设和未来趋势的结合点。在这本书里,“观察”不仅仅是看到数据,而是看清背后的意义。可以说,它从根本上改变了我对可观测性的理解。

核心内容

本书从基础定义到实际操作,系统地阐述了云原生可观测性的重要性及其实现方式。通过具体的工具和策略,它帮助读者理解如何整合指标、日志、追踪和混沌工程等维度,全面掌控分布式系统的健康状况,为 DevOps 团队提供高效的决策支持。

可观测性的定义与价值

书中开篇就点明:可观测性是通过系统的外部信号推断内部状态的能力。不仅是传统的指标(Metrics)、日志(Logs)、追踪(Tracing)三根支柱的组合,而是一种综合性、全局化的分析方法。正如作者所说:

“Observability isn’t just the ability to see each piece at a time; it’s also the ability to understand the broader picture and how these pieces combine.”

云原生环境的挑战

书中特别强调了 Kubernetes 环境中日志和监控的复杂性。Kubernetes 没有内置的完整可观测性解决方案,只提供了基础功能,比如 kubectl 查看对象状态,而更高级的功能需要依赖第三方工具如 Fluentd 和 Prometheus。

实践指南

书中在实践部分提到了多种实现可观测性的具体策略和工具:

  • 应用日志:通过 Fluentd 或类似工具采集容器内的标准输出日志,帮助开发者定位应用问题。
  • 集群日志:收集 Kubernetes 核心组件如 kube-apiserver 和 etcd 的日志,适合排查系统级别的故障。
  • 事件日志:利用 kubectl get events 快速了解集群中资源的状态变化。
  • 审计日志:记录 API 请求,便于安全审查和权限问题的定位。
  • 混沌工程:利用工具如 Chaos Mesh 和 Litmus Chaos,验证系统在高压或异常情况下的表现。

这些实践指南强调了工具与策略的结合,从而实现全面的可观测性。

我的思考与观点

超越数据本身的“观察力”

书中强调,单纯收集数据并不能解决问题,关键在于跨维度数据的整合与分析。例如,在性能问题排查时,指标和追踪往往无法直接关联,而这正是现有工具的短板。未来,统一数据存储和分析视角的工具,比如 OpenTelemetry 提倡的标准化方法,可能是突破口。

AI 与可观测性的结合

随着 AI 技术的发展,可观测性工具也可以更智能化。例如,通过机器学习预测异常,或是自动推荐优化策略。这不仅能减少人为干预,还能提升故障响应速度。正如作者在混沌工程部分提到的:

“Instead of waiting for something to happen and finding out how your application fares, you put it through duress under controlled conditions to identify weaknesses and fix them.”

从团队协作到文化转型

书中提到“DevOps 的终极目标是跨团队的协作与同理心”,这点深有共鸣。尤其是在复杂分布式系统中,开发和运维团队往往各自为战,导致沟通断层。跨团队协作的关键在于工具提供的透明性与共享视角,而不仅仅是技术能力。

总结

这本书的独到之处在于它从技术和人文两个角度同时切入,它让我意识到,可观测性不仅是一组工具的集合,而是一种文化、一种能力,帮助我们更深刻地理解系统,推动团队协作,并在复杂的云原生环境中建立起真正的“透明化”。

最后,我想引用书中一段非常打动我的话来结尾:

“Observability lets you see the beautiful and complete picture that is your production software systems.”

使用 Envoy 实现 HTTP/2 CONNECT 隧道:原理与实践

2025-01-14 18:28:37

在最近对 Istio Ambient 模式的研究中,我发现 HTTP2 Connect 方法被用作创建隧道的核心技术,以实现透明流量的拦截和转发。HTTP/2 CONNECT 隧道是一种强大的工具,可以在已有的 HTTP/2 连接中创建高效的隧道,用于传输原始的 TCP 数据。这篇文章通过一个简单的 Demo,展示了如何使用 Envoy 来实现 HTTP/2 CONNECT 隧道的基本功能。

什么是 HTTP2 Connect 方法以及 HBONE 隧道?

HTTP2 Connect 方法是一种标准化的方式来创建隧道,用于透明地传输数据。特别是在 Istio 的 Ambient 模式中,它为代理数据平面之间的通信提供了一种高效的手段。HBONE(HTTP-Based Overlay Network Environment)隧道则是基于这种 HTTP2 Connect 技术的实现,用于 Istio 中的透明流量拦截和转发。通过使用 HBONE,数据可以有效地通过 HTTP2 隧道安全传输,替代了传统的 Sidecar 模式。这一创新设计极大地简化了服务网格的管理和部署。

HBONE 是 Istio 特有的术语,它是一种安全隧道协议,用于在 Istio 组件之间进行通信。在当前的 Istio 实现中,HBONE 协议包含了三个开放标准:

  • HTTP/2
  • HTTP CONNECT
  • Mutual TLS (mTLS)

HTTP CONNECT 用于建立隧道连接,mTLS 用于安全地加密连接,而 HTTP/2 用于在单一安全隧道中多路复用应用连接流并传输附加的流级元数据。更多关于 HBONE 隧道的细节可以参考官方文档:HBONE 详细介绍

使用 HTTP2 Connect 建立隧道的基本原理

HTTP2 Connect 方法允许我们创建一个类似于 VPN 的隧道,通过这个隧道可以安全地传递数据。建立隧道的基本步骤如下:

  1. 首先,客户端向代理发送一个普通的 TCP 或 HTTP 链接请求。
  2. 代理接收到请求后,代表客户端向目标服务器发送一个带有 CONNECT 方法的 HTTP2 请求。
  3. 如果服务器允许建立隧道,那么它会返回一个 HTTP2 200 OK 的响应给代理。
  4. 随后,客户端、代理和服务器之间的双向流数据就可以通过这个隧道进行传输。

这种方法能够使得数据的传输过程更加透明且安全,特别适用于需要高效通信和端到端加密的场景。

下图展示了 HTTP2 Connect 方法建立隧道的基本过程。

image
HTTP2 Connect 方法建立隧道的基本过程

Demo:使用 Envoy 与上游 Server 建立 HTTP/2 Connect 隧道

本示例展示了一个基础场景:

  1. 客户端:向 Envoy 代理发送文本消息。
  2. Envoy:接收客户端的 TCP 数据,将其封装为 HTTP/2 CONNECT 请求,并与上游服务器建立加密隧道。
  3. 服务器:接收来自 Envoy 的 HTTP/2 CONNECT 流量,解封装并返回响应给客户端。

架构图如下:

image
架构图

我们将使用 Node.js 来编写客户端和服务端,并将服务端和 Envoy 代理运行在容器中,在本地通过客户端访问 Envoy 代理从而达到访问客户端的目的。

完整的目录结构如下:

envoy-http2-tunnel/
├── certs/
│   ├── openssl.cnf
│   ├── server.crt
│   ├── server.key
├── client/
│   └── client.js
├── docker-compose.yml
├── envoy.yaml
└── server/
    ├── Dockerfile
    └── server.js

核心功能展示

1. HTTP/2 CONNECT 隧道的基本实现

  • 客户端通过普通的 TCP 连接与 Envoy 通信。
  • Envoy 将 TCP 数据封装为 HTTP/2 CONNECT 请求,发送到上游服务器。
  • 服务器接收并解封装隧道中的数据,进行处理后返回响应。
  • 隧道通信对客户端完全透明。

2. Envoy 的透明代理能力

  • Envoy 作为中间代理,将客户端与服务器之间的通信逻辑完全封装。
  • 客户端无需支持复杂的协议(如 HTTP/2 或 TLS),Envoy 代理完成所有协议转换。

3. 加密通信的实现

  • Envoy 与服务器之间的通信通过 TLS 加密,确保隧道内的数据安全。
  • 服务器终止 TLS,处理解密后的数据。

4. 隧道的简化使用场景

  • 通过该 Demo,可以快速理解 HTTP/2 CONNECT 隧道的建立和基本数据传输流程。

环境准备

1. 安装 Node.js

确保你的系统已安装 Node.js(版本 >= 10.10.0),因为 http2 模块在该版本后稳定。

2. 安装 Docker 和 Docker Compose

3. 创建项目目录

在你的工作空间中创建一个新目录并进入:

mkdir envoy-http2-tunnel
cd envoy-http2-tunnel

生成自签名证书

由于 Envoy 和服务器之间需要加密通信,我们需要生成包含正确配置的自签名证书。

1. 创建证书目录和 OpenSSL 配置文件

创建 certs 目录:

mkdir certs
cd certs

创建 openssl.cnf,内容如下:

[ req ]
default_bits       = 2048
default_md         = sha256
prompt             = no
distinguished_name = dn
req_extensions     = req_ext

[ dn ]
C            = US
ST           = California
L            = San Francisco
O            = My Company
OU           = My Division
CN           = server

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1   = server
DNS.2   = localhost

2. 生成密钥和证书

运行以下命令生成密钥和证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout server.key -out server.crt -config openssl.cnf

这将在 certs 目录中生成 server.keyserver.crt 文件。

配置 Envoy 代理

我们需要配置 Envoy,使其能够接受客户端的普通 TCP 连接,将数据通过 HTTP/2 CONNECT 隧道传递给服务器。

1. 创建 Envoy 配置文件

在项目根目录创建 envoy.yaml,内容如下:

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.filters.network.tcp_proxy
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
          stat_prefix: tcp_stats
          cluster: tunnel_cluster
          tunneling_config:
            hostname: server:8080
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
              log_format:
                json_format:
                  start_time: "%START_TIME%"
                  method: "%REQ(:METHOD)%"
                  path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
                  protocol: "%PROTOCOL%"
                  response_code: "%RESPONSE_CODE%"
                  response_flags: "%RESPONSE_FLAGS%"
                  bytes_received: "%BYTES_RECEIVED%"
                  bytes_sent: "%BYTES_SENT%"
                  duration: "%DURATION%"
                  upstream_service_time: "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%"
                  x_forwarded_for: "%REQ(X-FORWARDED-FOR)%"
                  user_agent: "%REQ(USER-AGENT)%"
                  request_id: "%REQ(X-REQUEST-ID)%"
                  upstream_host: "%UPSTREAM_HOST%"
                  upstream_cluster: "%UPSTREAM_CLUSTER%"
                  downstream_local_address: "%DOWNSTREAM_LOCAL_ADDRESS%"
                  downstream_remote_address: "%DOWNSTREAM_REMOTE_ADDRESS%"
  clusters:
  - name: tunnel_cluster
    connect_timeout: 5s
    type: LOGICAL_DNS
    lb_policy: ROUND_ROBIN
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        sni: server
        common_tls_context:
          validation_context:
            trusted_ca:
              filename: "/certs/server.crt"
          alpn_protocols: [ "h2" ]
    http2_protocol_options: {}
    load_assignment:
      cluster_name: tunnel_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: server
                port_value: 8080

2. 关键点

  • Envoy 监听 TCP 连接,将流量通过 HTTP/2 CONNECT 隧道转发到服务器。
  • 客户端只需与 Envoy 建立 TCP 连接,发送文本消息。
  • Envoy负责隧道的建立和加密,客户端无需感知。

实现服务器

1. 创建服务器目录和文件

在项目根目录创建 server 目录:

mkdir server

server 目录中创建 server.jsDockerfile

2. 编写 server.js

server/server.js 中添加以下代码:

const http2 = require('http2');
const fs = require('fs');

const server = http2.createSecureServer({
  key: fs.readFileSync('/certs/server.key'),
  cert: fs.readFileSync('/certs/server.crt'),
});

server.on('stream', (stream, headers) => {
  const method = headers[':method'];
  const path = headers[':path'];

  if (method === 'CONNECT') {
    console.log(`Received CONNECT request for ${path}`);

    // 响应 200,建立隧道
    stream.respond({
      ':status': 200,
    });

    // 在隧道内处理数据
    stream.on('data', (chunk) => {
      const message = chunk.toString();
      console.log(`Received from client: ${message}`);

      // 回应客户端
      const response = `Echo from server: ${message}`;
      stream.write(response);
    });

    stream.on('end', () => {
      console.log('Stream ended by client.');
      stream.end();
    });
  } else {
    // 对于非 CONNECT 请求,返回 404
    stream.respond({
      ':status': 404,
    });
    stream.end();
  }
});

server.listen(8080, () => {
  console.log('Secure HTTP/2 server is listening on port 8080');
});

注意:

  • 监听 secureConnection 事件,直接处理 TLS 连接后的 socket。
  • 在 socket 上接收数据,处理来自客户端的文本消息,并回复。

3. 创建 Dockerfile

server/Dockerfile 中添加以下内容:

FROM node:14

WORKDIR /app

COPY server.js .

EXPOSE 8080

CMD ["node", "server.js"]

实现客户端

1. 创建客户端目录和文件

在项目根目录创建 client 目录:

mkdir client

client 目录中创建 client.js

2. 编写 client.js

client/client.js 中添加以下代码:

const net = require('net');

// 创建与 Envoy 的 TCP 连接
const client = net.createConnection({ port: 10000 }, () => {
  console.log('Connected to Envoy.');

  // 发送消息给服务器
  let counter = 1;
  const interval = setInterval(() => {
    const message = `Message ${counter} from client!`;
    client.write(message);
    counter += 1;
  }, 1000);

  // 关闭连接
  setTimeout(() => {
    clearInterval(interval);
    client.end();
  }, 5000);
});

client.on('data', (data) => {
  console.log(`Received from server: ${data.toString()}`);
});

client.on('end', () => {
  console.log('Disconnected from server.');
});

client.on('error', (err) => {
  console.error('Client error:', err);
});

说明:

  • 客户端Envoy 建立普通的 TCP 连接,发送文本消息。
  • 该客户端的存在只是为了触发 Envoy 与服务器建立隧道。

创建 Docker Compose 文件

在项目根目录创建 docker-compose.yml

version: '3.8'

services:
  envoy:
    image: envoyproxy/envoy:v1.32.1
    volumes:
      - ./envoy.yaml:/etc/envoy/envoy.yaml
      - ./certs:/certs  # 挂载证书目录
    ports:
      - "10000:10000"
    networks:
      - envoy_network
    depends_on:
      - server
    command: /usr/local/bin/envoy -c /etc/envoy/envoy.yaml --service-cluster envoy --log-level debug

  server:
    build:
      context: ./server
    networks:
      - envoy_network
    expose:
      - "8080"
    volumes:
      - ./certs:/certs  # 挂载证书目录

networks:
  envoy_network:

运行示例

1. 启动 Docker Compose

在项目根目录下,运行:

docker-compose up --build

预期输出:

  • Envoy 容器: 显示启动信息和调试日志。
  • 服务器容器: 显示 Secure HTTP/2 server is listening on port 8080

2. 运行客户端

打开新的终端窗口,进入 client 目录:

cd client

运行客户端:

node client.js

预期输出:

Connected to Envoy.
Received from server: Echo from server: Message 1 from client!
Received from server: Echo from server: Message 2 from client!
Received from server: Echo from server: Message 3 from client!
Received from server: Echo from server: Message 4 from client!
Received from server: Echo from server: Message 5 from client!
Disconnected from server.

3. 检查服务器日志

在 Docker Compose 的输出中,你应该能看到服务器的日志:

envoy_1   | {"downstream_remote_address":"192.168.65.1:46306","path":null,"request_id":null,"bytes_sent":160,"protocol":null,"upstream_service_time":null,"bytes_received":88,"response_code":0,"user_agent":null,"downstream_local_address":"172.21.0.3:10000","upstream_host":"172.21.0.2:8080","start_time":"2024-12-03T11:37:59.542Z","upstream_cluster":"tunnel_cluster","duration":5012,"response_flags":"-","method":null,"x_forwarded_for":null}
server_1  | Secure HTTP/2 server is listening on port 8080
server_1  | New secure connection established.
server_1  | Received from client: Message 1 from client!
server_1  | Received from client: Message 2 from client!
server_1  | Received from client: Message 3 from client!
server_1  | Received from client: Message 4 from client!
server_1  | Received from client: Message 5 from client!
server_1  | Connection ended by client.

4. 检查 Envoy 日志

在 Envoy 的日志中,你可以看到它使用 HTTP/2 CONNECT 隧道与服务器建立连接的记录。

测试通信

  • 客户端通过 TCP 连接向 Envoy 代理发送文本消息。
  • Envoy将客户端的 TCP 流量通过 HTTP/2 CONNECT 隧道转发给 服务器
  • 服务器接收到来自客户端的消息,处理并回复。
  • Envoy将服务器的回复通过隧道传回给 客户端
  • 客户端收到服务器的回复。

注意事项

  • 证书管理: 确保证书正确配置,并在 Envoy 和服务器中正确使用。
  • Docker 网络: 使用 Docker Compose 定义的网络,容器可以通过服务名称互相通信。
  • 端口冲突: 确保端口 10000(Envoy)和 8080(服务器)未被占用。
  • TLS 配置: 在示例中,Envoy 与服务器之间的通信使用 TLS 和 HTTP/2,确保了安全性。

隧道建立过程

下图展示了客户端、Envoy 代理和服务器之间的交互,反映了数据的传递和隧道连接的建立的流程。

image
隧道建立流程

说明:

  1. 客户端与 Envoy 建立 TCP 连接

    • 客户端向 Envoy 发起 TCP 连接请求。
    • Envoy 接受连接,建立新的 TCP 代理会话(ConnectionId: 0)。
  2. Envoy 创建到服务器的连接

    • Envoy 尝试连接上游集群 tunnel_cluster,创建新的连接(ConnectionId: 1)。
  3. 建立 HTTP/2 CONNECT 隧道

    • Envoy 与服务器建立 HTTP/2 连接。
    • Envoy 发送 HTTP/2 CONNECT 请求,目标主机名为 server:8080
    • 服务器响应 200 OK,隧道建立成功。
  4. 数据传输

    • 消息传递循环
      • 客户端发送数据(Message N)到 Envoy。
      • Envoy 将数据通过隧道转发给服务器。
      • 服务器处理数据并返回响应(Echo Message N)给 Envoy。
      • Envoy 将响应转发给客户端。
    • 日志记录
      • 服务器记录收到的消息,例如 Received from client: Message N from client!
  5. 连接关闭

    • 客户端发送 FIN 请求,通知关闭连接。
    • Envoy 将 FIN 转发给服务器,关闭隧道。
    • 服务器响应 ACK 确认关闭。
    • Envoy 向客户端发送 ACK,完成连接关闭。
  6. 日志记录

    • Envoy 记录连接关闭日志,包括 ConnectionId 和统计信息。
    • 服务器记录日志,显示流已由客户端结束,例如 Stream ended by client.

结语

虽然这是一个入门示例,但它为理解和进一步探索 HTTP/2 CONNECT 隧道功能提供了坚实的基础。在下一篇博客中讲解通过两个 Envoy 代理实现的隧道,带你进一步了解 Istio ambient 模式中的 HBONE 透明隧道。

参考

AI 工具推荐 Napkin.ai:让复杂想法一键变成直观图表

2025-01-09 18:26:54

在工作中,我们经常需要清晰地传达复杂的想法,但单靠文字有时候实在不够直观。这时候,一张清晰的图表往往能让人一眼看懂你的思路。

image
抽象概念可视化的好处(本图使用 napkin.ai 生成)

今天想给大家推荐一个特别好用的工具——Napkin.ai。它可以自动把你的文字内容变成图表,比如信息图、流程图等等,让你的想法更容易被理解和传播。

image
Napkin 界面

Napkin.ai 的核心功能

  1. 文本自动变图表:把文字粘贴到 Napkin.ai,系统会自动生成相关的图表,完全不用自己动手画。
  2. 图表样式多样:根据你的内容,Napkin.ai 会提供多种图表样式,你可以选择最适合的那个。
  3. 支持自定义:图表生成后还能调整,比如更改图标、颜色、字体等,让它看起来更符合你的风格。
  4. 多种格式导出:生成的图表可以导出为 PNG、SVG 或 PDF,用起来很方便。

适合谁用

image
Napkin 如何提升沟通效率(本图使用 napkin.ai 生成)

不管你是市场营销人员、内容创作者,还是需要做商业演示的专业人士,Napkin.ai 都能帮你提升沟通效果,让你的内容更吸引人。

如何开始?

  1. 打开 napkin.ai
  2. 注册一个账号(免费),目前高级版本还在 beta 阶段,暂未收费,未来的收费还未公开。
  3. 粘贴文字,生成图表,然后根据需要调整。
  4. 导出图表,用在你的工作或分享中。

这款工具真的非常方便,试一次就会爱上!支持中文,而且免费使用,无次数限制。如果你也需要一个帮手来把复杂想法变得更直观,赶紧去试试吧!