灰度发布 K8s-服务网格实战-配置 Mesh

在上一篇 k8s-服务网格实战-入门Istio中分享了如何安装部署 Istio,同时可以利用 Istio 实现 gRPC 的负载均衡 。
【灰度发布 K8s-服务网格实战-配置 Mesh】今天我们更进一步 , 深入了解使用 Istio 的功能 。

灰度发布 K8s-服务网格实战-配置 Mesh

文章插图
从 Istio 的流量模型中可以看出:Istio 支持管理集群的出入口请求(gateway) , 同时也支持管理集群内的 mesh 流量,也就是集群内服务之间的请求 。
本次先讲解集群内部的请求,配合实现以下两个功能:
  • 灰度发布(对指定的请求分别路由到不同的 service 中)
  • 配置 service 的请求权重
灰度发布在开始之前会部署两个 deployment 和一个 service , 同时这两个 deployment 所关联的 Pod 分别对应了两个不同的 label,由于在灰度的时候进行分组 。
灰度发布 K8s-服务网格实战-配置 Mesh

文章插图
使用这个 yaml 会部署所需要的 deployment 和 service 。
kubectl Apply -f https://raw.Githubusercontent.com/crossoverJie/k8s-combat/mAIn/deployment/istio-mesh.yaml首先设想下什么情况下我们需要灰度发布,一般是某个重大功能的测试,只对部分进入内测的用户开放入口 。
假设我们做的是一个 App,我们可以对拿到了内测包用户的所有请求头中加入一个版本号 。
比如 versinotallow=200 表示新版本,versinotallow=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})// Serverfunc (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {md, ok := metadata.FromIncomingContext(ctx)var version stringif 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/v1alpha3kind: DestinationRulemetadata:name: k8s-combat-service-dsspec:host: k8s-combat-service-istio-meshsubsets:- name: v1labels:app: k8s-combat-service-v1- name: v2labels:app: k8s-combat-service-v2这里我们使用 Istio 的 DestinationRule 定义 subset,也就是将我们的 service 下的 Pod 分为 v1/v2 。
使用 标签 app 进行分组
注意这里的 host: k8s-combat-service-istio-mesh 通常配置的是 service 名称 。
apiVersion: v1kind: Servicemetadata:name: k8s-combat-service-istio-meshspec:selector:appId: "12345"type: ClusterIPports:- port: 8081targetPort: 8081name: app- name: grpcport: 50051targetPort: 50051也就是这里 service 的名称,同时也支持配置为 host: k8s-combat-service-istio-mesh.default.svc.cluster.local , 如果使用的简写Istio 会根据当前指定的 namespace 进行解析 。
Istio 更推荐使用全限定名替代我们这里的简写,从而避免误操作 。
当然我们也可以在 DestinationRule 中配置负载均衡的策略,这里我们先略过:
apiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata:name: k8s-combat-service-dsspec:host: k8s-combat-service-istio-meshtrafficPolicy:loadBalancer:simple: ROUND_ROBIN
灰度发布 K8s-服务网格实战-配置 Mesh

文章插图
这样我们就定义好了两个分组:
  • v1:app: k8s-combat-service-v1
  • v2:app: k8s-combat-service-v2
之后就可以配置路由规则将流量分别指定到两个不同的组中,这里我们使用 VirtualService 进行配置 。
apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: k8s-combat-service-vsspec:gateways:- meshhosts:- k8s-combat-service-istio-mesh # match this hosthttp:- name: v1match:- headers:version:exact: '100'route:- destination:host: k8s-combat-service-istio-meshsubset: v1- name: v2match:- headers:version:exact: '200'route:- destination:host: k8s-combat-service-istio-meshsubset: v2- name: defaultroute:- destination:host: k8s-combat-service-istio-meshsubset: v1


推荐阅读