使用Istio灰度发布

目录

  • 灰度发布
    • [1. Istio](#1. Istio)
      • [1.1 Istio介绍](#1.1 Istio介绍)
      • [1.2 Istio是如何工作的](#1.2 Istio是如何工作的)
    • [2. 安装Istio](#2. 安装Istio)
      • [2.1 环境](#2.1 环境)
      • [2.2 得到二进制文件](#2.2 得到二进制文件)
      • [2.3 安装istio](#2.3 安装istio)
    • [3. 部署bookinfo模拟业务](#3. 部署bookinfo模拟业务)
      • [3.1 v1页面](#3.1 v1页面)
      • [3.2 v2页面](#3.2 v2页面)
      • [3.3 v3页面](#3.3 v3页面)
    • [4. 模拟灰度发布](#4. 模拟灰度发布)
      • [4.1 业务版本v2](#4.1 业务版本v2)
      • [4.2 灰度发布到v3版本](#4.2 灰度发布到v3版本)
    • [5. Kiali](#5. Kiali)
      • [5.1 安装普罗米修斯](#5.1 安装普罗米修斯)
      • [5.2 修改svc类型](#5.2 修改svc类型)

灰度发布

什么叫灰度发布?

灰度发布也就是在我们发布新版本的业务的时候,不是直接将所有流量切到新版本上去,而是新旧版本共存,并且将流量逐步的从旧版本切换到新版本的过程叫做灰度发布

灰度发布的好处

灰度发布对比全量发布的好处是,先由一少部分用户体验新版本,观察新版本的情况,有没有出现bug,服务错误之类的问题,如果遇到了这种问题,可以直接将流量给切回旧版本,因为体验新版本的用户不是特别多,所以不会造成特别大的事故,而如果使用全量发布,等到发布完之后发现业务有bug,这时候所有在用的用户都受到了这个bug的影响,此时回退版本的影响肯定是大于灰度发布造成的影响的

1. Istio

1.1 Istio介绍

Istio 是一种开源服务网格,可透明地分层到现有的分布式应用程序上。 Istio 的强大功能提供了一种统一且更高效的方式来保护、连接和监控服务。 Istio 是实现负载均衡、服务到服务身份验证和监控的途径 - 几乎无需更改服务代码。它为您提供:

  • 使用双向 TLS 加密、强大的基于身份的身份验证和鉴权在集群中保护服务到服务通信
  • HTTP、gRPC、WebSocket 和 TCP 流量的自动负载均衡
  • 使用丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制
  • 支持访问控制、限流和配额的可插入策略层和配置 API
  • 集群内所有流量(包括集群入口和出口)的自动指标、日志和链路追踪

1.2 Istio是如何工作的

Istio 使用代理来拦截您的所有网络流量,从而根据您设置的配置允许使用一系列应用程序感知功能。

控制平面采用您所需的配置及其对服务的视图,并动态地编程代理服务器,并根据规则或环境的变化对其进行更新。

数据平面是服务之间的通信。如果没有服务网格,网络就无法理解正在发送的流量,也无法根据流量类型、流量来源或目的地做出任何决策。

Istio 支持两种数据平面模式:

  • Sidecar 模式,它会与您在集群中启动的每个 Pod 一起部署一个 Envoy 代理,或者与在虚拟机上运行的服务一同运行。
  • Ambient 模式,它使用每个节点的四层代理,并且可选地使用每个命名空间的 Envoy 代理来实现七层功能。

2. 安装Istio

安装Istio之前我们需要有一个Kubetnetes集群,自行部署一个集群即可

我是用Istioctl方式去安装,也可以使用helm安装,自行查阅官方文档即可

2.1 环境

k8s版本 IP地址
1.28.2 192.168.200.156

2.2 得到二进制文件

由于二进制压缩包是在github上的,所以国内下载会很慢甚至是无法下载,所以我这里使用了我自己的github下载代理

bash 复制代码
[root@master ~]# wget https://github.030814.xyz/https://github.com/istio/istio/releases/download/1.25.0/istio-1.25.0-linux-amd64.tar.gz

等待下载结束,版本可以更换为自己想安装的版本

然后解压文件,并移动二进制文件到环境变量下

bash 复制代码
[root@master ~]# tar -zxvf istio-1.25.0-linux-amd64.tar.gz -C /opt
[root@master ~]# cd /opt/istio-1.25.0/
[root@master istio-1.25.0]# mv bin/istioctl /usr/local/bin/

2.3 安装istio

我们现在可以使用istioctl来安装了

bash 复制代码
[root@master istio-1.25.0]# cd
[root@master ~]# istioctl install --set profile=demo 

这里由于我的是学习环境,所以我安装的是demo,demo会安装所有的组件,如果是生产环境建议安装default,缺什么组件再自行安装即可,等待安装完成即可

bash 复制代码
❗ detected Calico CNI with 'bpfConnectTimeLoadBalancing=TCP'; this must be set to 'bpfConnectTimeLoadBalancing=Disabled' in the Calico configuration
This will install the Istio 1.25.0 profile "demo" into the cluster. Proceed? (y/N) y
✔ Istio core installed ⛵️                                                                                                                                     
✔ Istiod installed 🧠                                                                                                                                        
✔ Egress gateways installed 🛫                                                                                                                               
✔ Ingress gateways installed 🛬                                                                                                                              
✔ Installation complete 

出现这个就是安装完成了,我们可以查看一下pod

bash 复制代码
[root@master ~]# kubectl get pods -n istio-system 
NAME                                    READY   STATUS    RESTARTS      AGE
istio-egressgateway-6567d885cb-799dg    1/1     Running   0             51s
istio-ingressgateway-6688b98758-x7dsw   1/1     Running   0             51s
istiod-5f89f8b9ff-5dvjk                 1/1     Running   0             53s

这几个pod都running了说明已经没问题了

3. 部署bookinfo模拟业务

安装完成之后我们需要对某个命名空间开启sidecar的自动注入,因为sidecar会拦截流量并分流,如果我们没有开启这个那么istio是无法管理流量的走向的

bash 复制代码
[root@master ~]# kubectl label ns default istio-injection=enabled

接下来我们使用官方提供的bookinfo来模拟业务,因为bookinfo是由多个语言,并且每个业务也是由多个版本的,所以我们来模拟一下灰度发布

bash 复制代码
[root@master ~]# kubectl apply -f /opt/istio-1.25.0/samples/bookinfo/platform/kube/bookinfo.yaml 

接下来我们等待pod都运行

bash 复制代码
[root@master ~]# kubectl get pods 
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-649d7678b5-nh782       2/2     Running   0          6s
productpage-v1-5c5fb9b4b4-qgsjt   2/2     Running   0          6s
ratings-v1-794db9df8f-bj9bh       2/2     Running   0          6s
reviews-v1-7f9f5df695-h5jhp       2/2     Running   0          6s
reviews-v2-65c9797659-ld965       2/2     Running   0          6s
reviews-v3-84b8cc6647-mzzjc       2/2     Running   0          6s

所有的pod都是running并且ready都是2/2之后说明bookinfo就部署好了,接下来我们访问

bash 复制代码
[root@master ~]# kubectl apply -f /opt/istio-1.25.0/samples/bookinfo/platform/kube/productpage-nodeport.yaml
service/productpage configured

将productpage页面映射出去我们使用浏览器访问

bash 复制代码
[root@master ~]# kubectl get svc 
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
details       ClusterIP   10.101.159.198   <none>        9080/TCP         2m34s
kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP          40h
productpage   NodePort    10.105.75.208    <none>        9080:31592/TCP   2m34s
ratings       ClusterIP   10.106.211.56    <none>        9080/TCP         2m34s
reviews       ClusterIP   10.110.28.147    <none>        9080/TCP         2m34s

这里可以看到映射出来的端口是31592,那我们到浏览器访问这个端口

这里我们就访问到了bookinfo的界面了,刚刚也说过了,它是由多个版本构成的,那么现在我们进行刷新页面

3.1 v1页面

3.2 v2页面

3.3 v3页面

这样就是3个版本的页面了,多进行刷新就可以看到了

4. 模拟灰度发布

4.1 业务版本v2

现在我们模拟业务版本是v2,然后需要使用灰度发布到v3版本,先来编写一个yaml文件,让所有的流量都走向v2

文件名为 v2.yaml

yaml 复制代码
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: reviewsdr
spec:
  host: reviews                  # 指定reviews的svc地址,可以通过kubectl get svc得到
  subsets:
  - name: v1                     # 指定等会需要往带有哪些标签的pod上转发流量,这里是v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
---
apiVersion: networking.istio.io/v1    
kind: VirtualService            # 创建虚拟服务
metadata:
  name: reviewvs 
spec:
  hosts: 
  - reviews                    # 这里的hosts也是svc地址
  http:
  - route:
    - destination:
        host: reviews
        subset: v2            # 指定v2版本

然后我们apply这个文件

bash 复制代码
[root@master istio]# kubectl apply -f v2.yaml 

回到浏览器刷新页面,现在你无论如何去刷新,他都是黑色的星星,也就是v2版本

4.2 灰度发布到v3版本

我们只需要对刚刚的yaml文件进行修改即可

bash 复制代码
[root@master istio]# vim v2-v3.yaml
[root@master istio]# cat v2-v3.yaml 
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: reviewvs
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2
      weight: 90                   # v2的权重是90%
    - destination:
        host: reviews
        subset: v3
      weight: 10                   # v3的权重是10%

现在根据我们定义的规则,就是会有10%的用户会看到v3的版本,也就是红星那个页面,接下来我们apply

bash 复制代码
[root@master istio]# kubectl apply -f v2-v3.yaml 
virtualservice.networking.istio.io/reviewvs configured

回到浏览器刷新页面,多刷新几次

你会看到有很多次是黑色星星,只有极少数是红星,这就是那极少部分用户所看到的页面,后续我们只需要更改刚刚的yaml文件里面的权重值即可,知道完全发布v3版本

5. Kiali

刚刚我们实现了灰度发布,但是我们看不到流量的走向,我想要可视化的界面,也是有的,那就是Kiali

5.1 安装普罗米修斯

Kiali是需要依赖于普罗米修斯采集到的数据的,所有我们需要先部署一个监控,但是部署也是非常的简单,我们之前下载的istio的包里面就有

bash 复制代码
[root@master ~]# cd /opt/istio-1.25.0/samples/addons/
[root@master ~]# kubectl apply -f .

由于我是采用的安装整个目录的yaml文件,所以会安装一些其他的组件,我们不管即可

bash 复制代码
[root@master addons]# kubectl get pods -n istio-system 
NAME                                    READY   STATUS    RESTARTS   AGE
grafana-58856dc744-2k8ds                1/1     Running   0          2m4s
istio-egressgateway-6567d885cb-799dg    1/1     Running   0          34m
istio-ingressgateway-6688b98758-x7dsw   1/1     Running   0          34m
istiod-5f89f8b9ff-5dvjk                 1/1     Running   0          34m
jaeger-6bf648bcdc-j4tjv                 1/1     Running   0          2m4s
kiali-c584b499b-h8xc4                   1/1     Running   0          2m3s
loki-0                                  0/2     Pending   0          2m3s
prometheus-7fb6d49999-hsxt7             2/2     Running   0          2m3s

我们可以看到普罗米修斯以及我们kiali界面都被安装好了并且running了,接下来我们访问图形化界面

5.2 修改svc类型

现在kiali的svc类型是clusterIP,集群外是无法访问的,所以我们需要将svc改为nodeport

bash 复制代码
[root@master addons]# kubectl edit -n istio-system svc kiali 

将这个地方原本的类型改为NodePort即可

然后我们查看端口访问

bash 复制代码
[root@master addons]# kubectl get svc -n istio-system  |grep kiali
kiali                  NodePort       10.106.227.72    <none>        20001:32239/TCP,9090:30962/TCP  

我们可以看到将pod的20001端口使用32239端口映射了,接下来我们访问32239即可

这个就是他的界面了,接下来我们点击旁边的第二个

然后选择命名空间

这个时候页面还没有任何的东西,是因为没有持续的流量,所以我们来写一个脚本让他一直发请求

bash 复制代码
[root@master addons]# watch -n 1 curl -o /dev/null -s -w %{http_code} localhost:31592/productpage

注意自己替换一个端口,回到浏览器

选择所展示的就是这样的了,我们来调整一些参数

将展示的参数给勾选一个,意思就是展示所分配的流量,可以看到大部分流量是在v2版本上的,有一少部分流量是在v3版本

因为我们设置的权重是90%和10%,但是他工作起来也并不可能一定就是10个人里面9个人是v2版本,1个人是v3版本,所以这里的流量分配会是在我们设置的数值附近浮动,而不是正好是我们设置的那个值,当然,也会出现就是我们设置的那个值的这种情况。这就是灰度发布的流程了