istio in action之流量控制与路由
当流量进入集群后,我们如何确保它能被精确地路由到正确的服务?特别是当我们需要发布新版本时,如何在不中断服务的前提下,安全地将用户引入到新版本?这正是我们今天要深入探讨的精细化流量控制,看看 Istio 如何帮助我们实现这一点。
我们先来回顾一下大家可能都熟悉的蓝绿部署。这个方法确实很直观,就像图里展示的,蓝色版本是当前的稳定军,绿色版本是准备好的后备军。发布的时候把流量全部切到绿色。这听起来很完美,对吧?零停机时间,有问题还能切回去。但问题在于,一旦切换到绿色,就是所有用户,一起上阵,这本质上还是个大爆炸式发布。如果新版本有个隐藏的bug,或者性能突然下降,那影响范围可就大了。所以,我们需要更精细的控制手段。
要解决这个问题,关键在于区分“部署”和“发布”这两个动作。部署,就是把代码、容器,实实在在地放到生产环境里去,这时候还没有任何真实用户流量进来。这时候,我们可以在生产环境中进行各种测试,比如烟雾测试,看看基本功能是否正常,监控指标是否符合预期。只有当部署完成,我们才开始考虑“发布”,也就是把生产流量逐步引导到新部署的版本上。这个发布过程,完全可以是渐进式的、可控的。这种解耦,是实现低风险发布的基石。
解耦之后,我们就可以玩出花样了。最常见的就是金丝雀发布。大家知道矿井里的金丝雀,对环境变化特别敏感,可以用来预警。在发布新版本时,我们也可以选一小部分用户,比如内部员工,作为我们的金丝雀,让他们先体验新版本。
通过 Istio,我们可以轻松配置,比如只给内部用户路由到 v2 版本,其他人还是走 v1。如果金丝雀表现良好,我们就逐步扩大范围。这种方式的好处显而易见:风险可控,反馈及时,而且万一出了问题,随时可以回滚到旧版本,对大部分用户几乎没有影响。
那么,Istio 是如何实现这些精细路由的呢?核心就是两个关键的资源:VirtualService 和 DestinationRule。
- 可以把 VirtualService 理解为路由规则,告诉 Istio 如何处理流量。
- 而 DestinationRule 则用来定义服务的版本,也就是所谓的子集。
比如,我们可以通过 Kubernetes 的标签来区分 v1 和 v2 版本,然后在 DestinationRule 里把这些标签关联起来。这样,VirtualService 就能根据这些子集来决定流量该去向何方。
举个例子,我们想让所有带有 x-istio-cohort : internal 请求头的请求都去 v2 版本,就可以在 VirtualService 的 match 部分指定这个条件,然后在 route 部分指定目标子集为 version v2。
让我们来看一个具体的例子。假设我们已经部署了 catalog 服务的 v1 和 v2 两个版本,并且在 DestinationRule 中定义了 version v1 和 version v2 两个子集。现在,我们想创建一个 VirtualService,让所有带有 x-istio-cohort : internal 请求头的请求都路由到 v2。配置就是这样的
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: catalog-vs-from-gw
spec:hosts:- "catalog.istioinaction.io"gateways:- catalog-gatewayhttp:- match:- headers:x-istio-cohort:exact: "internal"route:- destination:host: catalogsubset: version-v2- route:- destination:host: catalogsubset: version-v1
在 match 部分,我们指定 headers 下 x-istio-cohort 的值必须是 exact internal。在 route 部分,我们指定 destination 的 host 是 catalog,subset 是 version-v2。如果请求没有这个特定的头,那么 Istio 会按照后续的 route 规则,通常是默认的,把流量路由到 version-v1。这样,我们就实现了基于请求头的精细路由。
以上的示例是从网关进入的流量,但 Istio 的路由能力远不止于此。它同样可以在服务内部的调用链中发挥作用。比如,我们有一个 apigateway 服务,它需要调用 catalog 服务。我们可以在 apigateway 的 VirtualService 中,设置一个规则,当 apigateway 收到请求时,它内部调用 catalog 时,也要根据请求头来决定是调用 v1 还是 v2。配置的关键在于,将 gateways 字段设置为 mesh,表示这条规则适用于所有网格内部的请求。这样,我们就可以在应用层实现复杂的路由逻辑,比如根据不同的用户请求,调用不同的后端服务版本。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: catalog
spec:hosts:- cataloggateways:- mesh # 设置gateways为meshhttp:- match:- headers:x-istio-cohort:exact: "internal"route:- destination:host: catalogsubset: version-v2- route:- destination:host: catalogsubset: version-v1
除了基于请求头的路由,还有一种更常见的渐进式发布方式,就是加权路由。就是把总流量按照一定的比例分配给不同的服务版本。比如,我们可以设置 90% 的流量继续走 v1,同时把 10% 的流量导向新版本 v2。这样,新版本上线后,只有少量用户会受到影响,我们可以密切监控 v2 的性能和稳定性。如果一切顺利,我们可以逐步增加 v2 的权重,比如 10%、20%、30%,直到最终全部 100% 的流量都切换到 v2。这种方式的好处是平滑过渡,风险可控。而且,如果发现 v2 有问题,只需要把权重调回 0 就行了,非常容易回滚。我们再来看一个具体的配置。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: catalog
spec:hosts:- cataloggateways:- meshhttp:- route:- destination:host: catalogsubset: version-v1weight: 90- destination:host: catalogsubset: version-v2weight: 10
假设我们要把 10% 的流量导向 v2。在 VirtualService 的 route 部分,我们定义两个 destination。第一个是 catalog 的 version v1,weight 设为 90。第二个是 catalog 的 version v2,weight 设为 10。这样,Istio 会自动将 90% 的流量发送到 v1,10% 的流量发送到 v2。
为了验证效果,我们可以用 curl 命令发送大量请求,比如 100 次,然后统计返回结果中带有 v2 特征字段imageUrl 的数量。理论上,应该接近 10 次。如果想改成 50/50 的分配,只需要把两个 weight 的值都改成 50 即可。
前面我们讲的路由和加权转移,虽然风险可控,但毕竟还是有真实流量经过了新版本,万一新版本处理有问题,还是可能影响用户体验。有没有更彻底的零风险验证方法呢?答案是肯定的,那就是流量镜像。这个技术非常巧妙,它会把每一个生产请求复制一份,然后把这份副本悄悄地发送给新版本 v2 去处理。但是,v2 的处理结果会被丢弃,完全不影响主请求的正常路径。这意味着,我们可以用真实流量来测试新版本,获取性能指标,观察日志,但用户完全感觉不到任何变化。这就像给新版本做一次全面的体检,而且是用真实环境的体检报告。在 Istio 中配置流量镜像也很简单。
https://blog.christianposta.com/microservices/traffic-shadowing-with-istio-reduce-the-risk-of-code-release/
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: catalog
spec:hosts:- cataloggateways:- meshhttp:- route:- destination:host: catalogsubset: version-v1weight: 100mirror: # 设置流量镜像host: catalogsubset: version-v2
在 VirtualService 里,我们仍然可以指定主路由,比如 100% 的流量都去 v1。然后,添加一个 mirror 字段,告诉 Istio 把流量镜像到哪里。mirror 字段里也包含 host 和 subset,指向我们要镜像的 v2 服务。这样,每个请求都会同时到达 v1 和 v2。我们可以通过检查 v2 的日志来确认镜像是否成功。注意,Istio 会自动修改镜像流量的 Host 头,加上一个 shadow 后缀,比如 Host: 10.12.1.178~shadow:8080。应用程序可以根据这个特殊的 Host 头来判断自己是处理的主请求还是镜像请求,从而优化处理逻辑,比如避免不必要的数据库写入。
聊完了内部的流量控制,我们再来看看外部边界。默认情况下,Istio 允许任何出站流量。但这种做法存在安全隐患。如果某个服务不幸被攻破,攻击者可能会利用这个服务,偷偷摸摸地连接到外部的恶意服务器,进行数据窃取或者其他破坏活动。为了防止这种“外联”风险,我们可以收紧 Istio 的出站策略。
通过配置 ~meshConfig.outboundTrafficPolicy.mode`,我们可以把它从默认的 `ALLOW_ANY` 改为 `REGISTRY_ONLY`。这意味着,只有那些被明确添加到 Istio 服务注册表中的外部服务,才能被网格内的服务访问。其他所有出站请求,都会被 Istio 拦截。这是一种基本的安全防御纵深,可以有效阻止恶意的“外联”行为。在生产环境中我们通常会修改 IstioOperator 的configmap配置来实现。
$ istioctl install --set profile=demo \
--set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
Istio 提供了 ServiceEntry 这个资源,可以把 ServiceEntry 理解为一个“通行证”,它允许我们把外部服务的信息,比如主机名、端口、协议,添加到 Istio 的内部服务注册表里。这样,当网格内的服务需要访问这些外部服务时,Istio 就知道该去哪个地址,用什么协议去访问。
配置也很简单,只需要指定 hosts、ports、resolution 和 location 等参数。让我们来看一个具体的例子。
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:name: jsonplaceholder
spec:hosts:- jsonplaceholder.typicode.comports:- number: 80name: httpprotocol: HTTPresolution: DNSlocation: MESH_EXTERNAL # 指定mesh外部服务
假设我们有一个名为 forum 的服务,它需要调用一个外部的论坛 API,地址是 jsonplaceholder.typicode.com。我们先创建一个 ServiceEntry,名称为 jsonplaceholder,spec.hosts 指定为 jsonplaceholder.typicode.com,spec.ports 定义了 HTTP 端口 80,resolution 设置为 DNS,location 设置为 MESH_EXTERNAL。创建好 ServiceEntry 之后,我们再尝试从网格内部的某个服务比如 curl 客户端去访问 forum 服务的接口,这个接口会调用到 jsonplaceholder.typicode.com。
如果一切配置正确,这次调用应该就能成功了。这证明了 ServiceEntry 确实让我们的服务能够安全地访问到需要的外部服务。
相关文章:

istio in action之流量控制与路由
当流量进入集群后,我们如何确保它能被精确地路由到正确的服务?特别是当我们需要发布新版本时,如何在不中断服务的前提下,安全地将用户引入到新版本?这正是我们今天要深入探讨的精细化流量控制,看看 Istio 如…...
图像处理篇---opencv实现坐姿检测
文章目录 前言一、方法概述使用OpenCV和MediaPipe关键点检测角度计算姿态评估 二、完整代码实现三、代码说明PostureDetector类find_pose()get_landmarks()cakculate_angle()evaluate_posture() 坐姿评估标准(可进行参数调整):可视化功能&…...

优选算法——前缀和
目录 1. 数组的中心下标 2. 除自身以外数组的乘积 3. 和为k的子数组 4. 和可被K整除的子数组 5. 连续数组 6. 矩阵区域和 1. 数组的中心下标 题目链接:724. 寻找数组的中心下标 - 力扣(LeetCode) 题目展示: 题目分析&am…...

用AI写简历是否可行?
让AI批量写简历然后投简历是绝对不行的!!! 为什么不行,按照 "招聘经理" 工作经历举例: ai提示词:请帮我写一份招聘经理的工作经历内容: 招聘经理 | XXX科技有限公司 | 2020年…...

力扣题解:2、两数相加
个人认为,该题目可以看作合并两个链表的变种题,本题与21题不同的是,再处理两个结点时,对比的不是两者的大小,而是两者和是否大于10,加法计算中大于10要进位,所以我们需要声明一个用来标记是否进…...
C语言_函数hook方案
背景 单体测试中测试一个函数时,该函数调用的其他函数,需要按照测试case,依赖其他函数进行调用参数检查,返回特定值。但是其他函数,不容易做到参数检查和返回特定值,这时需要将其他函数进行hook,hook函数用户自己实现,比较容易实现参数检查和返回值特定值。 本文主要…...

IPM IMI111T-026H 高效风扇控制板
概述: REF-MHA50WIMI111T 是一款专为风扇驱动设计的参考开发板,搭载了英飞凌的IMI111T-026H iMOTION™智能功率模块(IPM)。这个模块集成了运动控制引擎(MCE)、三相栅极驱动器和基于IGBT的功率级,全部封装在一个紧凑的DSO22封装中。REF-MHA50…...
Qt 关于获取postgres time with time zone类型字段存在无效值的情况
Qt 获取 postgres time with time zone类型字段存在无效值的情况 事件起因 在使用Qt获取pg数据库中time with time zone类型字段时偶发出现时间获取失败,体现为获取结果为无效值 QVariant vt sqlQuery->value(i); // QVariant(QTime, QTime(Invalid))查看源码 查看Qt q…...

武汉火影数字|数字科技馆打造:开启科技探索新大门
足不出户,就能畅游科技的奇幻世界,你相信吗?数字科技馆就能帮你实现!在这个数字化的时代,数字科技馆如同一颗璀璨的新星,照亮了我们探索科学的道路。 那么,数字科技馆究竟是什么呢? …...

suricata之日志截断
一、背景 在suricata的调试过程中,使用SCLogXXX api进行信息的输出,发现输出的日志被截断了,最开始以为是解析逻辑有问题,没有解析完整,经过排查后,发现SCLogXXX api内部进行了长度限制,最长2K…...
leetcode 2918. 数组的最小相等和 中等
给你两个由正整数和 0 组成的数组 nums1 和 nums2 。 你必须将两个数组中的 所有 0 替换为 严格 正整数,并且满足两个数组中所有元素的和 相等 。 返回 最小 相等和 ,如果无法使两数组相等,则返回 -1 。 示例 1: 输入…...

简易图片编辑工具,支持抠图和替换背景
软件介绍 Photo Retouch是一款由微软官方商店推出的免费图片处理软件,具有抠图、换背景、修复等功能,操作便捷且效率极高,非常值得尝试。 功能详解 这款软件提供五大功能,包括删除物体、快速修复、一键抠图、背景调整和裁剪…...

Java Bean容器详解:核心功能与最佳使用实践
在Java企业级开发中,Bean容器是框架的核心组件之一,它通过管理对象(Bean)的生命周期、依赖关系等,显著提升了代码的可维护性和扩展性。主流的框架如Spring、Jakarta EE(原Java EE)均提供了成熟的…...

Spring Security 深度解析:打造坚不可摧的用户认证与授权系统
Spring Security 深度解析:打造坚不可摧的用户认证与授权系统 一、引言 在当今数字化时代,构建安全可靠的用户认证与授权系统是软件开发中的关键任务。Spring Security 作为一款功能强大的 Java 安全框架,为开发者提供了全面的解决方案。本…...

Selenium模拟人类行为,操作网页的方法(全)
看到有朋友评论问,用selenium怎么模仿人类行为,去操作网页的页面呢? 我想了想,这确实是一个很大的点,不应该是一段代码能解决的, 就像是,如果让程序模拟人类的行为。例如模拟人类买菜,做饭&am…...
HNUST湖南科技大学-软件测试期中复习考点(保命版)
使用说明:本复习考点仅用于及格保命。软件测试和其他专业课不太一样,记忆的太多了,只能说考试的时候,想到啥就写啥,多写一点!多写一点!多写一点!(重要事情说三遍…...
如何使用极狐GitLab 软件包仓库功能托管 python?
极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 软件包库中的 PyPI 包 (BASIC ALL) 在项目的软件包库中发布 PyPI 包。然后在需要将它们用作依赖项时安装它们。 软件包库适用…...

右值引用的剖析
引入:为什么要有右值引用? 右值引用的存在,就是为了解决左值引用解决不了的问题! 左值引用的问题: 我们知道,左值引用在做参数和做返回值都可以提高效率;但是有时候,我们无法用左…...
tmpfs和普通文件系统相比有哪些优缺点
tmpfs 是一种基于内存的文件系统,与普通文件系统相比,在读写速度、数据安全性等方面存在明显差异,以下是其优缺点对比: 优点 读写速度快:普通文件系统读写数据时,需要通过硬盘等存储设备进行 I/O 操作&…...

高效Python开发:uv包管理器全面解析
目录 uv简介亮点与 pip、pip-tools、pipx、poetry、pyenv、virtualenv 对比 安装uv快速开始uv安装pythonuv运行脚本运行无依赖的脚本运行有依赖的脚本创建带元数据的 Python 脚本使用 shebang 创建可执行文件使用其他package indexes锁定依赖提高可复现性指定不同的 Python 版本…...
配置指定地址的conda虚拟Python环境
创建指定路径的 Conda 环境 在创建环境时,使用 --prefix 参数指定自定义路径: conda create --prefix/your/custom/path/my_env python3.8 说明: /your/custom/path/my_env:替换为你希望存放环境的路径(如 D:\projec…...
《解锁React Native与Flutter:社交应用启动速度优化秘籍》
React Native和Flutter作为当下热门的跨平台开发框架,在优化应用启动性能方面各有千秋。今天,我们就深入剖析它们独特的策略与方法。 React Native应用的初始包大小对启动速度影响显著。在打包阶段,通过精准分析依赖,去除未使用的…...

【Linux系统编程】进程属性--进程状态
1.进程的状态 1.1进程的状态在PCB中就是一个变量 一般用宏来定义,例如: #define RUNNING 1 #define BLOCK 2 struct task_struct中的int status 1.2并行和并发 CPU执行代码,不是把进程代码执行完毕,才执行下一个࿰…...
Go Modules 的基本使用
在 Go Modules 项目中,首次运行时下载依赖包的正确流程需要根据项目情况区分处理。以下是详细步骤和最佳实践: 一、首次初始化项目的标准流程 1.1 创建项目目录并初始化模块 mkdir myproject && cd myproject go mod init github…...
光流 | 基于深度学习的光流估计算法汇总,原理,公式,流程图,代码
基于深度学习的光流算法 一、光流估计的基本原理二、基于深度学习的光流估计算法1. **FlowNet系列**2. **FlowNet 2.0**3. **PWC-Net**4. **RAFT(Recurrent All-Pairs Field Transformers)**5. **LiteFlowNet系列**三、算法流程图示例FlowNet2.0架构PWC-Net金字塔处理流程四、…...

高精度之加减乘除之多解总结(加与减篇)
开篇总述:精度计算的教学比较杂乱,无系统的学习,且存在同法多线的方式进行同一种运算,所以我写此篇的目的只是为了直指本质,不走教科书方式,步骤冗杂。 一,加法 我在此讲两种方法: …...

dify插件接入fastmcp示例
文章目录 1. 使用python完成mcp服务1.1 准备环境(python安装fastmcp)1.2 mcp服务端示例代码1.3 启动mcp服务端 2. dify接入2.1 安装MCP SSE和 Agent 策略(支持 MCP 工具) 插件2.2 dify agent插件配置mcp:2.3 mcp服务配置ÿ…...

c++——二叉树进阶
1. 内容安排说明 二叉树在前面C数据结构阶段已经讲过,本节取名二叉树进阶是因为: 1. map和set特性需要先铺垫二叉搜索树,而二叉搜索树也是一种树形结构 2. 二叉搜索树的特性了解,有助于更好的理解map和set的特性 3. 二叉树中部…...
MySQL 中如何进行 SQL 调优?
在MySQL中进行SQL调优是一个系统性工程,需结合索引优化、查询改写、性能分析工具、数据库设计及硬件配置等多方面策略。以下是具体优化方法及案例说明: 一、索引优化:精准提速的关键 索引类型选择 普通索引:加速频繁查询的列&…...
【C++游戏引擎开发】第33篇:物理引擎(Bullet)—射线检测
一、射线检测核心理论体系 1.1 射线检测的数学基础 1.1.1 参数化射线方程 射线在三维空间中的数学表达采用参数方程: r ( t ) = o + t d ^ ( t ∈ [...