说明
版本格式
- 主版本号:表示重大更改,如新功能、架构变化等。主版本号的增加通常意味着项目已经发生根本性的变化
- 次版本号:表示较小的功能更新和改进。次版本号的增加通常不会导致用户需要进行大量的学习或适应
- 修订号:表示已修复的错误和漏洞。修订号的增加通常不会影响项目的主要功能和结构
示例版本
- 代码版本:
主版本号
.次版本号
.修正版本号
- 镜像版本:
主版本号
.次版本号
- 服务版本:
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
修改网关配置,将流量全部更新到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
主版本更新
1.0
到2.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"}%