云原生-渐进式交付-纵享丝滑-金丝雀-AB Testing
前置说明
上篇把开发的 Spring Boot 应用发布到 Kubernetes, 而原生的 K8S Deployment 属于滚动更新,
本篇采用 渐进式交付,分批精细化控制流量更新。
Kruise Rollout
Kruise Rollout 支持配合流量和实例灰度的金丝雀发布、蓝绿发布、A/B Testing 发布。
官网
- https://github.com/openkruise/rollouts/blob/master/docs/tutorials/basic_usage.md
- https://openkruise.io/rollouts/user-manuals/basic-usage/
kruise-rollout 安装
helm repo add openkruise https://openkruise.github.io/charts
helm install kruise-rollout openkruise/kruise-rollout `
--set image.repository=openkruise-registry.cn-shanghai.cr.aliyuncs.com/openkruise/kruise-rollout `
--version 0.3.0
kubectl-kruise 安装
Windows 环境下载,添加扩展名 .exe 并添加到环境变量
https://github.com/openkruise/kruise-tools/releases/download/v1.0.5/kubectl-kruise-windows-amd64.tar.gz
Demo 展示
注意
更新的资源(Deployment/Service/Ingress)必须在同个命名空间内。
获取资源名称:
kubectl get deploy,svc,ingress
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-app-svc
annotations:
kubernetes.io/ingress.class: higress
spec:
rules:
- host: test.lab.com
http:
paths:
- backend:
service:
name: demo-app-svc
port:
number: 8888
path: /test/hello
pathType: Exact
hosts
- C:\Windows\System32\drivers\etc\hosts
127.0.0.1 test.lab.com
金丝雀
金丝雀发布的思想是将少量的请求引流到新版本上,因此部署新版本服务只需极小数的机器。
验证新版本符合预期后,逐步调整流量权重比例,使得流量慢慢从老版本迁移至新版本,期间可以根据设置的流量比例,
对新版本服务进行扩容,同时对老版本服务进行缩容,使得底层资源得到最大化利用。
rollout-canary.yaml
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-canary-demo-app
namespace: default
annotations:
rollouts.kruise.io/rolling-style: partition
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: demo-app-svc
strategy:
canary:
steps:
- weight: 10
pause: { }
replicas: 1
- weight: 30
pause: { }
replicas: 2
trafficRoutings:
- service: demo-app-svc
ingress:
classType: higress
name: demo-app-svc
kubectl apply -f rollout-canary.yaml
kubectl get rollouts -A
NAMESPACE NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
default rollouts-canary-demo-app Healthy 2 Completed workload deployment is completed 5m25s
pod 和 deploy (demo-app:1.0-SNAPSHOT)
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl get po,deploy -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/demo-app-svc-8669b67549-pzch2 1/1 Running 0 76m 10.244.0.61 kind-control-plane <none> <none>
pod/demo-app-svc-8669b67549-sqjmh 1/1 Running 0 76m 10.244.0.62 kind-control-plane <none> <none>
pod/demo-app-svc-8669b67549-x5drh 1/1 Running 0 91m 10.244.0.60 kind-control-plane <none> <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/demo-app-svc 3/3 3 3 131m svc registry.cn-shenzhen.aliyuncs.com/uid13/demo-app:1.0-SNAPSHOT app.kubernetes.io/instance=demo-app,app.kubernetes.io/name=svc
修改镜像版本为 demo-app:1.1-SNAPSHOT
- demo-app:1.0-SNAPSHOT
PS D:\IdeaProjects\reproduce-demo\demo-app> curl -X GET "http://test.lab.com/test/hello"
{"success":true,"data":"资源服务测试"}
容器名为: svc
容器镜像:registry.cn-shenzhen.aliyuncs.com/uid13/demo-app:1.0-SNAPSHOT
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl set image deploy demo-app-svc svc=registry.cn-shenzhen.aliyuncs.com/uid13/demo-app:1.1-SNAPSHOT -n default
deployment.apps/demo-app-svc image updated
新增了一个新版本Pod,缩减了一个旧版本Pod
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl get po,deploy -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/demo-app-svc-66d9b4f4bc-kzgqs 1/1 Running 0 3m36s 10.244.0.63 kind-control-plane <none> <none>
pod/demo-app-svc-8669b67549-sqjmh 1/1 Running 0 94m 10.244.0.62 kind-control-plane <none> <none>
pod/demo-app-svc-8669b67549-x5drh 1/1 Running 0 109m 10.244.0.60 kind-control-plane <none> <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/demo-app-svc 3/3 1 3 149m svc registry.cn-shenzhen.aliyuncs.com/uid13/demo-app:1.1-SNAPSHOT app.kubernetes.io/instance=demo-app,app.kubernetes.io/name=svc
金丝雀状态,并提示是否执行下一步更新
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl get rollouts -A
NAMESPACE NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
default rollouts-canary-demo-app Progressing 1 StepPaused Rollout is in step(1/2), and you need manually confirm to enter the next step 17m
执行步骤
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl-kruise rollout approve rollout/rollouts-canary-demo-app
rollout.rollouts.kruise.io/rollouts-canary-demo-app approved
旧版本Pod只剩1个,新版本Pod为2个
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl get po,deploy -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/demo-app-svc-66d9b4f4bc-6lqlz 1/1 Running 0 4m30s 10.244.0.64 kind-control-plane <none> <none>
pod/demo-app-svc-66d9b4f4bc-kzgqs 1/1 Running 0 17m 10.244.0.63 kind-control-plane <none> <none>
pod/demo-app-svc-8669b67549-x5drh 1/1 Running 0 122m 10.244.0.60 kind-control-plane <none> <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/demo-app-svc 3/3 2 3 162m svc registry.cn-shenzhen.aliyuncs.com/uid13/demo-app:1.1-SNAPSHOT app.kubernetes.io/instance=demo-app,app.kubernetes.io/name=svc
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl get rollouts -A
NAMESPACE NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
default rollouts-canary-demo-app Progressing 2 StepPaused Rollout is in step(2/2), and you need manually confirm to enter the next step 24m
全量发布
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl-kruise rollout approve rollout/rollouts-canary-demo-app
rollout.rollouts.kruise.io/rollouts-canary-demo-app approved
全部为新版本Pod
PS D:\IdeaProjects\reproduce-demo\demo-app> kubectl get po,deploy -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/demo-app-svc-66d9b4f4bc-6lqlz 1/1 Running 0 8m48s 10.244.0.64 kind-control-plane <none> <none>
pod/demo-app-svc-66d9b4f4bc-kzgqs 1/1 Running 0 21m 10.244.0.63 kind-control-plane <none> <none>
pod/demo-app-svc-66d9b4f4bc-v86zq 1/1 Running 0 65s 10.244.0.65 kind-control-plane <none> <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/demo-app-svc 3/3 3 3 167m svc registry.cn-shenzhen.aliyuncs.com/uid13/demo-app:1.1-SNAPSHOT app.kubernetes.io/instance=demo-app,app.kubernetes.io/name=svc
测试路由
PS D:\IdeaProjects\reproduce-demo\demo-app> curl -X GET "http://test.lab.com/test/hello"
{"success":true,"data":"2023-05-30 19:18:24"}
AB Testing
相比于基于权重方式的金丝雀发布,A/B测试基于用户请求的元信息将流量路由到新版本,这是一种基于请求内容匹配的灰度发布策略。只有匹配特定规则的请求才会被引流到新版本,常见的做法包括基于Http Header和Cookie。基于Http Header方式的例子,例如User-Agent的值为 Jazz 的请求可以访问新版本,其他请求仍然访问旧版本。
rollout-abtesting.yaml
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-abtesting-demo-app
namespace: default
annotations:
rollouts.kruise.io/rolling-style: partition
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: demo-app-svc
strategy:
canary:
steps:
- matches:
- headers:
- name: user-agent
value: Jazz
pause: { }
replicas: 1
trafficRoutings:
- service: demo-app-svc
ingress:
classType: higress
name: demo-app-svc
注意,在同个 workload 资源上同时只能有一个 rollout,若要测试 ABTesting,则先删除之前的 rollout,其他操作过程类似。
总结
相比于传统人工手动方式, Kruise Rollouts 提供了无侵入、自动化运维方式让应用发布丝滑般顺畅。
开发者无需关注发布过程中如何调整 Deployment、Ingress、Service 等资源,只需声明并管理发布策略Rollouts资源即可。
原生 Deployment 的滚动发布会自动实现为渐进式交付,让应用发布可批次、可灰度、可回滚,助力业务快速迭代发展同时,
也提高了应用发布的稳定性和效率问题。