k8s-服务网格实战-配置 Mesh(灰度发布)

news2024/11/25 23:12:58

ef0ac36f6d11e80d75e0debf8fc5beae.png

istio-02.png

在上一篇 k8s-服务网格实战-入门Istio中分享了如何安装部署 Istio,同时可以利用 Istio 实现 gRPC 的负载均衡。

今天我们更进一步,深入了解使用 Istio 的功能。365008ec03d49d03837ebe2d1fefe869.png从 Istio 的流量模型中可以看出:Istio 支持管理集群的出入口请求(gateway),同时也支持管理集群内的 mesh 流量,也就是集群内服务之间的请求。

本次先讲解集群内部的请求,配合实现以下两个功能:

  • 灰度发布(对指定的请求分别路由到不同的 service 中)

  • 配置 service 的请求权重

灰度发布

在开始之前会部署两个 deployment 和一个 service,同时这两个 deployment 所关联的 Pod 分别对应了两个不同的 label,由于在灰度的时候进行分组。3bc43919b4916fb3a7b9eafe09fd30fb.png

使用这个 yaml 会部署所需要的 deploymentservice

kubectl apply -f https://raw.githubusercontent.com/crossoverJie/k8s-combat/main/deployment/istio-mesh.yaml

首先设想下什么情况下我们需要灰度发布,一般是某个重大功能的测试,只对部分进入内测的用户开放入口。

假设我们做的是一个 App,我们可以对拿到了内测包用户的所有请求头中加入一个版本号。

比如 version=200 表示新版本,version=100 表示老版本。同时在服务端会将这个版本号打印出来,用于区分请求是否进入了预期的 Pod。

// Client 
version := r.URL.Query().Get("version")  
name := "world"  
ctx, cancel := context.WithTimeout(context.Background(), time.Second)  
md := metadata.New(map[string]string{  
    "version": version,  
})  
ctx = metadata.NewOutgoingContext(ctx, md)  
defer cancel()  
g, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})

// Server
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {  
    md, ok := metadata.FromIncomingContext(ctx)  
    var version string  
    if ok {  
       version = md.Get("version")[0]  
    }    log.Printf("Received: %v, version: %s", in.GetName(), version)  
    name, _ := os.Hostname()  
    return &pb.HelloReply{Message: fmt.Sprintf("hostname:%s, in:%s, version:%s", name, in.Name, version)}, nil  
}

对 service 分组

进行灰度测试时往往需要新增部署一个灰度服务,这里我们称为 v2(也就是上图中的 Pod2)。

同时需要将 v1 和 v2 分组:

apiVersion: networking.istio.io/v1alpha3  
kind: DestinationRule  
metadata:  
  name: k8s-combat-service-ds  
spec:  
  host: k8s-combat-service-istio-mesh  
  subsets:  
    - name: v1  
      labels:  
        app: k8s-combat-service-v1  
    - name: v2  
      labels:  
        app: k8s-combat-service-v2

这里我们使用 Istio 的 DestinationRule 定义 subset,也就是将我们的 service 下的 Pod 分为 v1/v2。

使用 标签 app 进行分组

注意这里的 host: k8s-combat-service-istio-mesh 通常配置的是 service 名称。

apiVersion: v1  
kind: Service  
metadata:  
  name: k8s-combat-service-istio-mesh  
spec:  
  selector:  
    appId: "12345"  
  type: ClusterIP  
  ports:  
    - port: 8081  
      targetPort: 8081  
      name: app  
    - name: grpc  
      port: 50051  
      targetPort: 50051

也就是这里 service 的名称,同时也支持配置为 host: k8s-combat-service-istio-mesh.default.svc.cluster.local,如果使用的简写Istio 会根据当前指定的 namespace 进行解析。

Istio 更推荐使用全限定名替代我们这里的简写,从而避免误操作。

当然我们也可以在 DestinationRule 中配置负载均衡的策略,这里我们先略过:

apiVersion: networking.istio.io/v1alpha3  
kind: DestinationRule  
metadata:  
  name: k8s-combat-service-ds  
spec:  
  host: k8s-combat-service-istio-mesh 
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
6691c8db8e3f9bd7a9dfe6ca34d514a7.png
image.png

这样我们就定义好了两个分组:

  • v1:app: k8s-combat-service-v1

  • v2:app: k8s-combat-service-v2

之后就可以配置路由规则将流量分别指定到两个不同的组中,这里我们使用 VirtualService 进行配置。

apiVersion: networking.istio.io/v1alpha3  
kind: VirtualService  
metadata:  
  name: k8s-combat-service-vs  
spec:  
  gateways:  
    - mesh  
  hosts:  
    - k8s-combat-service-istio-mesh # match this host
http:  
  - name: v1  
    match:  
      - headers:  
          version:  
            exact: '100'  
    route:  
      - destination:  
          host: k8s-combat-service-istio-mesh  
          subset: v1  
  - name: v2  
    match:  
      - headers:  
          version:  
            exact: '200'  
    route:  
      - destination:  
          host: k8s-combat-service-istio-mesh  
          subset: v2  
  - name: default  
    route:  
      - destination:  
          host: k8s-combat-service-istio-mesh  
          subset: v1

这个规则很简单,会检测 http 协议的 header 中的 version 字段值,如果为 100 这路由到 subset=v1 这个分组的 Pod 中,同理为 200 时则路由到 subset=v2 这个分组的 Pod 中。

当没有匹配到 header 时则进入默认的 subset:v1

gRPC 也是基于 http 协议,它的 metadata 也就对应了 http 协议中的 header

header=100

Greeting: hostname:k8s-combat-service-v1-5b998dc8c8-hkb72, in:world, version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=100"
Greeting: hostname:k8s-combat-service-v1-5b998dc8c8-hkb72, in:world, version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=100"
Greeting: hostname:k8s-combat-service-v1-5b998dc8c8-hkb72, in:world, version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=100"
Greeting: hostname:k8s-combat-service-v1-5b998dc8c8-hkb72, in:world, version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=100"

header=200

Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"

根据以上的上面的测试请求来看,只要我们请求头里带上指定的 version 就会被路由到指定的 Pod 中。

利用这个特性我们就可以在灰度验证的时候单独发一个灰度版本的 Deployment,同时配合客户端指定版本就可以实现灰度功能了。

配置权重

同样基于 VirtualService 我们还可以对不同的 subset 分组进行权重配置。

apiVersion: networking.istio.io/v1alpha3  
kind: VirtualService  
metadata:  
  name: k8s-combat-service-vs  
spec:  
  gateways:  
    - mesh  
  hosts:  
    - k8s-combat-service-istio-mesh # match this host  
  http:  
    - match:  
        - uri:  
            exact: /helloworld.Greeter/SayHello  
      route:  
        - destination:  
            host: k8s-combat-service-istio-mesh  
            subset: v1  
          weight: 10  
        - destination:  
            host: k8s-combat-service-istio-mesh  
            subset: v2  
          weight: 90  
      timeout: 5000ms

这里演示的是针对 SayHello 接口进行权重配置(当然还有多种匹配规则),90% 的流量会进入 v2 这个 subset,也就是在 k8s-combat-service-istio-mesh service 下的 app: k8s-combat-service-v2 Pod。

Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-**v1**-5b998dc8c8-hkb72, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&version=200"
Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$

经过测试会发现大部分的请求都会按照我们的预期进入 v2 这个分组。

当然除之外之外我们还可以:

  • 超时时间

  • 故障注入

  • 重试 具体的配置可以参考 Istio 官方文档:84498f7f03a05883805d4411fa1981fb.png当然在一些云平台也提供了可视化的页面,可以更直观的使用。69ee1d8c141c990641f87eefe3f2cdc7.png

以上是 阿里云的截图

但他们的管理的资源都偏 kubernetes,一般是由运维或者是 DevOps 来配置,不方便开发使用,所以还需要一个介于云厂商和开发者之间的管理发布平台,可以由开发者以项目维度管理维护这些功能。

本文的所有源码在这里可以访问:https://github.com/crossoverJie/k8s-combat

PS:最近也在更新视频号,也会有一些技术干货,动动小手帮主播点播关注9264d338970fa31d7133e991fd35c847.jpeg

747000e50e51d8093325bf4ceefbec40.jpeg

往期推荐

技术阅读周刊第第四期

k8s-服务网格实战-入门Istio

如何优雅重启 kubernetes 的 Pod

在 kubernetes 环境中实现 gRPC 负载均衡

67d83078a886b42a1a4b79e839d88aff.gif

点分享

c711d7a511121c3b6b358a0c86c45e6c.gif

点收藏

cd05130171f186f6a378df1904377882.gif

点点赞

b52d71a09377c61c5c97529fa8fede87.gif

点在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1186552.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flutter生态一统甜夏 @Android @ios @windowse @macos @linux @Web

(愿景)G o o g l e 中 国flutter生态一统天下(IT) Web Android ios Windowse Macos Linux Google中国https://space.bilibili.com/64169458 https://pub-web.flutter-io.cn 构建 Flutter Web 应用 构建 Flutter Web 应用 - Flutter 中文文档 - Flutter 中文开发者网站 …

2023年下半年架构案例真题及答案

案例的考点: 大数据架构 Lambda架构和Kappa架构 jwt特点 数据持久层,Redis数据丢失,数据库读写分离方案 Hibernat架构 SysML七个关系,填需求图 大数据的必选题: 某网作为某电视台在互联网上的大型门户入口&#…

【vue 仿百度分页】

vue 仿百度分页 效果图 代码 公用组件 <template><nav class"pagination_nav"><ul class"pagination"><li :class"{ disabled: current 1 }"><a href"javascript:;" click"setCurrent(current - …

【Python大数据笔记_day04_Hadoop】

分布式和集群 分布式:多台服务器协同配合完成同一个大任务(每个服务器都只完成大任务拆分出来的单独1个子任务) 集群:多台服务器联合起来独立做相同的任务(多个服务器分担客户发来的请求) 注意:集群如果客户端请求量(任务量)多,多个服务器同时处理不同请求(不同任务),如果请求量…

大型企业是否有必要进行数字化转型?_数据治理平台_光点科技

数字化转型是大型企业在现代商业环境中保持竞争力的关键。一开始我们要明确数字化转型指的是利用数字技术来改变企业的业务模式和企业文化&#xff0c;以提高效率和效益。对于大型企业而言&#xff0c;进行数字化转型有着多重必要性。 1.数字化转型可以帮助企业优化内部流程&am…

情感分析与LLMs角色扮演

深度学习自然语言处理 原创作者&#xff1a;wkk 就像人类在做一件事情的时候&#xff0c;可能需要尝试多次。LLM也是如此&#xff01;这对于情感分析任务尤其如此&#xff0c;在情感分析任务中&#xff0c;LLM需要深入推理来处理输入中的复杂语言现象&#xff08;例如&#xff…

SPASS-图表的创建编辑

点击折线图 展示图如下&#xff1a; 双击图表&#xff0c;可进行编辑 图表基本设定 选择、移动图表元素和调整图表元素的大小 鼠标点击图表元素选择Tab键进行轮换选择Ctrl键鼠标进行多个元素选择十字箭头——移动元素双头箭头——调整元素大小 更改图表的外观 文本的内容、…

MS2111多点低压差分(M-LVDS)线路驱动器和接收器

MS2111 是多点低压差分 (M-LVDS) 线路驱动器和接收器。经过 优化&#xff0c;可运行在高达 200Mbps 的信号速率下。所有部件均符合 M LVDS 标准 TIA / EIA-899 。该驱动器的输出支持负载低至 30Ω 的多 点总线。 MS2111 的接收器属于 Type-2 &#xff0c; 可在 -1…

小程序制作(超详解!!!)第十五节 自动随机变化的三色旗

1.例题描述 设计一个小程序&#xff0c;开始时界面上显示一个三色旗和一个按钮&#xff0c;当点击按钮时&#xff0c;三色旗的颜色会发生随机变化&#xff0c;即使不点击按钮&#xff0c;三色旗的颜色也会每隔一定时间自动发生变化。 2.index.wxml <view class"box&…

【笔记】结合P02项目——maven继承与聚合

maven的继承关系 P02项目大概是这个样子&#xff0c;下图展示的是其父工程 父工程配置了parent依赖springb-boot-starter-parent&#xff0c;子工程配置其parant为父工程 子工程引用common子工程 maven的版本锁定 管理子工程的版本号问题 父工程添加dependencyManageMent…

Gradle笔记 六 Gradle 中的Dependencies

文章目录 Dependencies依赖的方式依赖的下载依赖的类型api 与implementation 区别依赖冲突及解决方案 Dependencies 依赖的方式 Gradle 中的依赖分别为直接依赖&#xff0c;项目依赖&#xff0c;本地jar 依赖。案例如下&#xff1a; dependencies { //①.依赖当前项目下的某…

C# Dictionary与List的用法区别与联系

C#是一门广泛应用于软件开发的编程语言&#xff0c;其中Dictionary和List是两种常用的集合类型。它们在存储和操作数据时有着不同的特点和用途。本文将详细探讨C# Dictionary和List的用法区别与联系&#xff0c;并通过代码示例进行对比&#xff0c;以帮助读者更好地选择适合自己…

Mac使用brew搭建kafka集群

1. 第一步&#xff1a;单机搭建 单机搭建&#xff1a; 安装完后&#xff0c;默认自动安装对应版本zookeeper brew install kafka2.第二步&#xff1a;修改配置文件: 配置3个Kafka 第一个&#xff08;使用默认配置&#xff09; vi /opt/homebrew/etc/kafka/server.propertie…

C# 查询腾讯云直播流是否存在的API实现

应用场景 在云考试中&#xff0c;为防止作弊行为的发生&#xff0c;会在考生端部署音视频监控系统&#xff0c;当然还有考官方监控墙系统。在实际应用中&#xff0c;考生一方至少包括两路直播流&#xff1a; &#xff08;1&#xff09;前置摄像头&#xff1a;答题的设备要求使…

服装展示服务预约小程序的内容如何

互联网电商深入&#xff0c;很多服装商家开始线上卖货经营、会员管理及私域营销等&#xff0c;这也是当今商家们的一个优选项&#xff0c;当然除了直接卖货以外&#xff0c;展示和预约、客户交互也同样是不少商家需要的。 那么商家通过服装展示预约小程序能够实现什么效果呢&a…

uni-app:js实现数组中的相关处理-数组复制

一、slice方法-浅拷贝 使用分析 创建一个原数组的浅拷贝&#xff0c;对新数组的修改不会影响到原数组slice() 方法创建了一个原数组的浅拷贝&#xff0c;这意味着新数组和原数组中的对象引用是相同的。因此&#xff0c;当你修改新数组中的对象时&#xff0c;原数组中相应位置的…

竞赛 行人重识别(person reid) - 机器视觉 深度学习 opencv python

文章目录 0 前言1 技术背景2 技术介绍3 重识别技术实现3.1 数据集3.2 Person REID3.2.1 算法原理3.2.2 算法流程图 4 实现效果5 部分代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习行人重识别(person reid)系统 该项目…

TLS回调函数

TLS在逆向中的作用 TLS回调函数常用于反调试 TLS先于EP代码执行 TLS是什么 TLS是各线程的独立的数据存储空间 使用TLS技术可以在线程内部独立使用或修改进程的全局数据或静态数据 创建和终止某进程时&#xff0c;TLS回调函数都会自动调用执行 使用OD调试TLS函数

vTESTstudio的使用

vTESTstudio介绍 vTESTstudio是Vector公司专为ECU自动化测试而研发的测试用例编写软件&#xff0c;可用于从模型测试到系统确认的所有开发阶段。它集成了多种用例编辑方法&#xff0c;能有效提高测试人员对测试设计的效率、具有可复用性等优点。它支持Python作为测试编程语言&…

windows查看端口号占用,并杀死进程

1、查看所有运行的端口&#xff1a; netstat -ano 2、查看被占用端口对应的 PID netstat -aon|findstr "8081" 回车执行该命令&#xff0c;最后一串数字就是 PID进程号, 这里是 19232。 3、查看指定 PID 的进程 tasklist|findstr "19232" 回车执行该…