说明

版本格式

  • 主版本号:表示重大更改,如新功能、架构变化等。主版本号的增加通常意味着项目已经发生根本性的变化
  • 次版本号:表示较小的功能更新和改进。次版本号的增加通常不会导致用户需要进行大量的学习或适应
  • 修订号:表示已修复的错误和漏洞。修订号的增加通常不会影响项目的主要功能和结构

示例版本

  • 代码版本: 主版本号.次版本号.修正版本号
  • 镜像版本: 主版本号.次版本号
  • 服务版本: v. 主版本号.次版本号

版本示例

主版本更新影响原接口和结构: 代码版本: 1.0.0 -> 2.0.0, 镜像版本:1.0->2.0, 服务版本: v1.0->v2.0

次版本更新新增功能: 代码版本: 1.0.0 -> 1.1.0, 镜像版本:1.0->1.1, 服务版本: v1.0->v1.1

修订错误功能: 代码版本: 1.0.0 -> 1.0.1, 镜像版本:1.0->1.0, 服务版本: v1.0->v1.0

示例代码

代码仓库

接口版本: web-server-user:release/1.0.x 网关配置: gateway:v1.0

接口版本: web-server-user:release/1.1.x 网关配置: gateway:v1.1

接口版本: web-server-user:release/2.0.x 网关配置: gateway:v2.0

脚本说明

  • push.sh: 输入镜像版本后执行构建镜像并推送到远程镜像仓库
  • kubernetes.sh: 申请所有 kubernetes资源,需要注意申请的deployment 为未带版本的的文件

版本控制

示例中的*.deployment.yaml 文件为上一个版本的配置, 申请当前版本资源需要指定新版本的文件, 例如1.1版本需要额外执行 kubectl apply -f user.deployment-1.1.yml

修订更新

按照版本示例修订错误镜像的次版本不会变动,只需要通过重启正在进行的 deployment 即可实现平滑更新

$ kubectl rollout restart deployment {{$deploymentName}}

使用示例代码修改文件 router.user.go版本 v1.0.1, 后执行脚本 ./kubernetes.sh。服务会启动完成新的1.0镜像后删除旧的1.0镜像

baseRouter.GET("version", func(ctx *gin.Context) {
    ctx.JSON(http.StatusOK, gin.H{
        "msg": "v1.0.0",
    })
})

次版本更新

版本从1.0更新到1.1可以临时共存双版本,将少数入站流量分发到1.1版本, 检测链路无异常后, 流量全部分发到1.1版本后删除1.0版本镜像

新版本配置

配置入站路由后的服务流量规则

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: user-web-server
spec:
  host: auth
  subsets:
    - name: v1 # gateway匹配的subset名称
      labels:
        version: v1.0 # 对应deployment version 版本
    - name: v1-last # gateway匹配的subset名称
      labels:
        version: v1.1 # 对应deployment version 版本

修改入站配置, 75%的流量请求到1.0版本, 25%的流量请求到1.1版本, 此配置忽略部分内容,详细内容传送门

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: qvbilam-gateway
spec:
  hosts:
    - "*"
  gateways:
    - qvbilam-gateway
  http:
    # user
    - match:
        - uri:
            prefix: /user
      route:
        - destination:
            port:
              number: 9701
            host: user-web-server
            subset: v1
          weight: 75
        - destination:
            port:
              number: 9701
            host: user-web-server
            subset: v1-last
          weight: 25

重新加载 gateway1.1 全部配置

$ kubectl apply -f destinationRule.yml
$ kubectl apply -f gateway.yml
$ kubectl apply -f serviceEntry.yml
$ kubectl apply -f virtualService.yml

如果已运行了1.0版本的镜像, 申请1.1版本资源, 否则执行.kubernetes.sh 运行成功后再申请1.1版本资源。

$ kubectl apply -f user.deployment-1.1.yaml

执行web-server-user:release/1.1.x脚本shell.sh请求接口100次可以

$ ./curl.sh
{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.1.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.1.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.1.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}{"msg":"v1.0.0"}

更新新版本

通过流量图可以看出1.1版本进入了少部分流量且返回值都是正常的,说明1.0版本接口可以平滑更新到1.1

image-20240807093603851

修改网关配置,将流量全部更新到1.1,将v1-last标签修改为v1, 删除1.0版本

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: qvbilam-gateway
spec:
  hosts:
    - "*"
  gateways:
    - qvbilam-gateway
  http:
    # user
    - match:
        - uri:
            prefix: /user
      route:
        - destination:
            port:
              number: 9701
            host: user-web-server
            subset: v1 # 将v1-last标签修改为v1
          weight: 100

修改流量规则配置.将subset:v1对应1.1版本的镜像

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: user-web-rule
spec:
  host: user-web-server
  subsets:
    - name: v1
      labels:
        version: v1.1

重新申请网关配置

$ kubectl apply -f destinationRule.yml
$ kubectl apply -f virtualService.yml

请求测试成功,流量全部进入1.1版本,即可删除旧版本 kubectl delete deployment user-web

image-20240807165744257

主版本更新

1.02.0为重大更新,应长期使不同版本共存, 通过客户端请求的版本来控制路由到不同的版本接口中,可让用户选择不同版本使用,避免强制更新

如果已运行了1.1版本的镜像, 申请2.0版本资源, 否则执行.kubernetes.sh 运行成功后再申请2.0版本资源。

$ kubectl apply -f user.deployment-2.0.yaml

修改流量规则配置.新增subset:v2对应2.0版本的镜像

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: user-web-rule
spec:
  host: user-web-server
  subsets:
    - name: v1
      labels:
        version: v1.1
    - name: v2
      labels:
        version: v2.0

修改网关配置,匹配请求头X-App-Version值前缀为2的进入2.0版本, 不满足条件的流量进入1.1版本

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: qvbilam-gateway
spec:
  hosts:
    - "*"
  gateways:
    - qvbilam-gateway
  http:
    # user v2
    - match:
        - uri:
            prefix: /user
          headers:
            X-App-Version:
              prefix: "2"
      route:
        - destination:
            port:
              number: 9701
            host: user-web-server
            subset: v2
    # user v1
    - match:
        - uri:
            prefix: /user
      route:
        - destination:
            port:
              number: 9701
            host: user-web-server
            subset: v1

申请配置

$ kubectl apply -f virtualService.yml
$ kubectl apply -f destinationRule.yml

请求测试

# 请求不带版本默认进入1.1镜像
$ curl -X GET localhost:8080/user/version
{"msg":"v1.1.0"}%

# 请求带版本默认进入1.1镜像
$ curl -X GET localhost:8080/user/version -H "X-App-Version: 1.1.0"
{"msg":"v1.1.0"}%

# 请求带版本匹配前缀版本进入2.0镜像
$ curl -X GET localhost:8080/user/version -H "X-App-Version: 2.0.0"
{"msg":"v2.0.0"}%

# 请求带版本匹配前缀版本进入2.0镜像
$ curl -X GET localhost:8080/user/version -H "X-App-Version: 2.0.1"
{"msg":"v2.0.0"}%

image-20240809133443042

Last modification:August 9th, 2024 at 01:35 pm