
Kruise Rollouts 是 OpenKruise 提供的一个旁路组件,用于提供先进的渐进式交付功能。它支持金丝雀、多批次和 A/B 测试交付模式,可以帮助实现对应用程序变更的平稳和可控发布,同时它与 Gateway API 和各种 Ingress 实现的兼容性使其更容易与你现有基础架构集成。总的来说,Kruise Rollouts 对于希望优化其部署流程的 Kubernetes 用户来说是一个有价值的工具!

Kruise Rollouts
Kruise Rollouts 具有以下几个主要特点:
在更新工作负载时进行流量细粒度加权流量转移。
基于 HTTP 头和 Cookie 进行 A/B 测试,根据流量进行转移。
更多流量协议支持
Ingress 控制器集成:NGINX、ALB、Higress。
通过 Gateway API 与服务网格集成。
可插拔的 Lua 脚本,轻松扩展到其他 Kubernetes 流量协议(甚至 CRD)。
容易集成
轻松与 GitOps 风格的基于 Kubernetes 的 PaaS 集成。
和其他发布组件相比,Kruise Rollouts 有什么优势?
组件 | Kruise Rollouts | Argo Rollouts | Flux Flagger |
核心概念 | 增强现有工作负载 | 替换你的工作负载 | 管理你的工作负载 |
架构 | 旁路 | 一种新的工作负载类型 | 旁路 |
插拔式组件,热插拔 | 是 | 否 | 否 |
发布类型 | 多批次,金丝雀,A/B 测试 | 多批次,金丝雀,蓝绿部署,A/B 测试 | 金丝雀,蓝绿部署,A/B 测试 |
工作负载类型 | Deployment,StatefulSet,CloneSet,Advaned StatefulSet,DaemonSet(WIP) | Agro-Rollout | Deployment. DaemonSet |
流量类型 | Ingress、GatewayAPI、CRD(需要 Lua 脚本) | Ingress、GatewayAPI、APISIX、Traefik、SMI 等 | Ingress、GatewayAPI、APISIX、Traefik、SMI 等 |
迁移成本 | 无需迁移你的工作负载和 Pod | 必须迁移你的工作负载和 Pod | 必须迁移你的 Pod |
HPA 兼容 | 是 | 是 | 否 |
整体上对比,Kruise Rollouts 与 Argo Rollouts 有相似的架构,但是功能上 Kruise Rollouts 更加强大,支持更多的发布策略和流量路由管理策略,同时也支持更多的流量协议。Kruise Rollouts 也是一个旁路组件,不需要迁移你的工作负载和 Pod,你可以在任何时候安装它,它会自动发现你的工作负载并管理它们。而和 Flagger 相比,Kruise Rollouts 支持更多的发布策略和流量路由管理策略,同时也支持更多的流量协议。
所以,如果你想要更多的发布策略和流量路由管理策略,同时也想要更多的流量协议支持,那么 Kruise Rollouts 就是一个不错的选择!
要使用 Kruise Rollouts,需要 Kubernetes 版本 >= 1.19,如果要使用 CloneSet 作为工作负载类型,则还需要安装 OpenKruise。
这里我们使用 Helm 来安装 Kruise Rollouts,你可以使用 helm repo add 命令来添加 Kruise 的 Helm 仓库:
➜ helm repo add openkruise https://openkruise.github.io/charts/
➜ helm repo update然后可以使用 helm install 命令来一键安装 Kruise Rollouts:
➜ helm upgrade --install kruise-rollout openkruise/kruise-rollout --version 0.3.0如果你没办法访问 DockerHub,可以使用阿里云的镜像仓库:
➜ helm upgrade --install kruise-rollout openkruise/kruise-rollout --version 0.3.0 --set image.repository=openkruise-registry.cn-shanghai.cr.aliyuncs.com/openkruise/kruise-rollout该命令默认会在 kruise-rollout 命名空间中安装 Kruise Rollouts,可以通过 kubectl get pods -n kruise-rollout 命令来查看安装结果:
➜ kubectl get pods -n kruise-rollout
NAME READY STATUS RESTARTS AGE
kruise-rollout-controller-manager-b4d64789d-9kmgm 1/1 Running 0 3m18s
kruise-rollout-controller-manager-b4d64789d-gln5n 1/1 Running 0 3m18s如果想更改默认安装的命名空间,则可以通过 installation.namespace 参数来进行指定。
安装后可以看到在 kruise-rollout 命名空间中多了一个 kruise-rollout-controller-manager 的 Deployment,它是 Kruise Rollouts 的控制器,它会自动发现你的工作负载并管理它们。
同样还会安装 3 个用于 Rollout 的 CRD:
➜ kubectl get crd |grep rollout
batchreleases.rollouts.kruise.io 2023-04-08T06:44:51Z
rollouthistories.rollouts.kruise.io 2023-04-08T06:44:51Z
rollouts.rollouts.kruise.io 2023-04-08T06:44:51Z接下来我们来使用 Kruise Rollouts 来管理一个工作负载,这里我们使用 Deployment 作为示例。
首先我们创建一个如下所示的 Deployment 工作负载:
# workload-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: workload-demo
namespace: default
spec:
replicas: 10
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
containers:
- name: busybox
image: busybox:1.28.3
command: ["/bin/sh", "-c", "sleep 100d"]
env:
- name: VERSION
value: "version-1"直接应用该资源对象即可:
➜ kubectl apply -f workload-demo.yaml
➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
workload-demo-6c7764b765-69ls9 1/1 Running 0 25m
workload-demo-6c7764b765-9zxr7 1/1 Running 0 26m
workload-demo-6c7764b765-hrd55 1/1 Running 0 25m
workload-demo-6c7764b765-krhfd 1/1 Running 0 25m
workload-demo-6c7764b765-mvrdk 1/1 Running 0 25m
workload-demo-6c7764b765-qzzl2 1/1 Running 0 25m
workload-demo-6c7764b765-tgt4k 1/1 Running 0 26m
workload-demo-6c7764b765-tjgcg 1/1 Running 0 26m
workload-demo-6c7764b765-x5b94 1/1 Running 0 26m
workload-demo-6c7764b765-xj5hb 1/1 Running 0 26m多批次更新策略是 Kruise Rollouts 的一个特性,它可以让你在更新工作负载时,可以控制每批次更新的 Pod 数量,以及每批次更新的时间间隔。
接下来我们需要创建一个 Rollout 对象来管理这个工作负载,比如我们想使用多批次更新策略将 Deployment 从 version-1 升级到 version-2。

多批次更新策略
目前,多批次更新策略可以在 CloneSet、StatefulSet、Advanced StatefulSet 和 Deployment 上工作。
那么我们可以创建如下所示的 Rollout 对象:
# rollouts-demo.yaml
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
namespace: default
annotations:
rollouts.kruise.io/rolling-style: partition # 使用多批次更新策略,只能配置 "partition" or "canary"
# "partition" 意味着像 CloneSet 一样分批滚动,不会创建任何额外的 Workload
# “canary” 表示以金丝雀方式滚动,并将创建一个金丝雀工作负载,对于Deployment默认是canary
spec:
objectRef: # 定义工作负载
workloadRef: # 关联需要管理的工作负载
apiVersion: apps/v1
kind: Deployment
name: workload-demo
strategy: # 定义升级策略
canary: # 使用 Canary 策略
steps: # 定义多批次更新策略
- replicas: 1
- replicas: 50%
- replicas: 100%直接创建该 Rollout 对象即可。
➜ kubectl apply -f rollouts-demo.yaml
➜ kubectl get rollout
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollouts-demo Healthy 3 Completed workload deployment is completed 6s创建 Rollout 对象后,其实已经开始管理工作负载了,上面的 kubectl get rollout 命令可以看到 Rollout 的状态为 Healthy,但现在工作负载的版本还是 version-1,我们可以通过将 Deployment 升级到 version-2 版本,来观察下 Rollout 的状态变化。
➜ kubectl patch deployment workload-demo -p \
'{"spec":{"template":{"spec":{"containers":[{"name":"busybox", "env":[{"name":"VERSION", "value":"version-2"}]}]}}}}'稍等片刻,我们会看到 Deployment 更新了一个 Pod:
➜ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
workload-demo 10/10 1 10 30m
➜ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
workload-demo-6c7764b765 9 9 9 30m
workload-demo-6dd59d49b5 1 1 1 34s
➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
workload-demo-6c7764b765-69ls9 1/1 Running 0 30m
workload-demo-6c7764b765-hrd55 1/1 Running 0 30m
workload-demo-6c7764b765-krhfd 1/1 Running 0 30m
workload-demo-6c7764b765-mvrdk 1/1 Running 0 30m
workload-demo-6c7764b765-qzzl2 1/1 Running 0 30m
workload-demo-6c7764b765-tgt4k 1/1 Running 0 31m
workload-demo-6c7764b765-tjgcg 1/1 Running 0 31m
workload-demo-6c7764b765-x5b94 1/1 Running 0 31m
workload-demo-6c7764b765-xj5hb 1/1 Running 0 31m
workload-demo-6dd59d49b5-mpthm 1/1 Running 0 52s现在我们再查看 Rollout 的状态:
➜ kubectl describe rollout rollouts-demo
Name: rollouts-demo
Namespace: default
Labels: <none>
Annotations: rollouts.kruise.io/hash: 77cxd69w47b7bwddwv2w7vxvb4xxdbwcx9x289vw69w788w4w6z4x8dd4vbz2zbw
rollouts.kruise.io/rolling-style: partition
API Version: rollouts.kruise.io/v1alpha1
Kind: Rollout
# ......
Status:
Canary Status:
Canary Ready Replicas: 1
Canary Replicas: 1
Canary Revision: 6dd59d49b5
Current Step Index: 1
Current Step State: StepPaused
Last Update Time: 2023-04-08T07:27:24Z
Message: BatchRelease is at state Ready, rollout-id , step 1
Observed Workload Generation: 8
Pod Template Hash: 6dd59d49b5
Rollout Hash: 77cxd69w47b7bwddwv2w7vxvb4xxdbwcx9x289vw69w788w4w6z4x8dd4vbz2zbw
Stable Revision: 6c7764b765
Conditions:
Last Transition Time: 2023-04-08T07:27:16Z
Last Update Time: 2023-04-08T07:27:16Z
Message: Rollout is in Progressing
Reason: InRolling
Status: True
Type: Progressing
Message: Rollout is in step(1/3), and you need manually confirm to enter the next step
Observed Generation: 2
Phase: Progressing
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Progressing 110s rollout-controller upgrade step(1) canary pods with new versions done
➜ kubectl get rollout
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollouts-demo Progressing 1 StepPaused Rollout is in step(1/3), and you need manually confirm to enter the next step 6m17s可以看到现在 Rollout 的状态为 Progressing,并且在第 1 步,当前的金丝雀状态为 StepPaused,这是因为我们使用了 partition 策略,需要手动确认才能进入下一步。
为了方便手动确认,我们可以安装使用 kubectl-kruise 这个插件。如果你已经安装过 Krew 这个插件,那么可以直接通过 kubectl krew install kruise-tools 来安装。
如果没有安装 Krew,可以直接前往 Release 页面 下载对应的二进制文件,然后将其放到 PATH 路径下即可。
➜ tar -xvf kubectl-kruise-darwin-arm64.tar.gz
➜ sudo mv darwin-arm64/kubectl-kruise /usr/local/bin/然后就可以使用 kubectl-kruise 或者 kubectl kruise 命令了:
➜ kubectl-kruise --help
# or
➜ kubectl kruise --helpkubectl-kruise 插件安装完成后,我们就可以通过 kubectl-kruise rollout approve 命令来手动确认继续发布第二批次了:
➜ kubectl kruise rollout approve rollout/rollouts-demo -n default
rollout.rollouts.kruise.io/rollouts-demo approved确认后现在我们再去查看下现在工作负载的状态:
➜ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
workload-demo 10/10 5 10 45m
➜ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
workload-demo-6c7764b765 5 5 5 45m
workload-demo-6dd59d49b5 5 5 5 15m
➜ kubectl get rollout
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollouts-demo Progressing 2 StepPaused Rollout is in step(2/3), and you need manually confirm to enter the next step 18m可以看到现在工作负载已经有 5 个是新版本的了,Rollout 对象也已经进入了第 2 步,如果我们再次手动确认,那么就会进入第 3 步,然后就会将所有的工作负载全部更新为新版本。
继续执行确认操作:
➜ kubectl kruise rollout approve rollout/rollouts-demo -n default
rollout.rollouts.kruise.io/rollouts-demo approved可以看到现在工作负载已经全部更新为新版本了,Rollout 对象也显示金丝雀发布已经完成:
➜ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
workload-demo 10/10 10 10 47m
➜ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
workload-demo-6c7764b765 0 0 0 48m
workload-demo-6dd59d49b5 10 10 10 17m
➜ kubectl get rollout
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollouts-demo Healthy 3 Completed Rollout progressing has been completed 21m到这里我们的分批次发布就完成了。
上面我们使用 kubectl kruise rollout approve 命令来进行手动确认的,那么还有其他方法吗?目前,有两种方法,例如,如果你已完成第一批并要发送第二批:
这两种方法都有自己的优点和缺点:
kind: Rollout
spec:
strategy:
canary:
steps:
- replicas: 1
pause:
duration: 0
- ... ...➜ kubectl kruise rollout approve rollout/<your-rollout-name> -n <your-rollout-namespace>那么如果现在我们想要回滚操作怎么办呢?事实上,Kruise Rollout 不提供直接回滚的能力。Kruise Rollout 更喜欢用户可以直接回滚工作负载规范来回滚他们的应用程序。当用户需要从 version-2 回滚到 version-1 时,Kruise Rollout 会使用原生的滚动升级策略快速回滚,而不是遵循 multi-batch checkpoint 策略。
此外还有一些其他注意事项值得我们注意:
金丝雀发布策略允许用户在发布新版本时,将流量分配给新版本的一小部分,以便在发布新版本之前,可以对其进行测试。如果测试通过,则可以将流量分配给新版本的所有副本,否则可以回滚到旧版本。
目前金丝雀发布策略只支持 Deployment 工作负载。

金丝雀发布策略
比如现在我们有一个如下所示的 Deployment 工作负载:
# workload-canary-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoserver
labels:
app: echoserver
spec:
replicas: 5
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
containers:
- name: echoserver
image: registry.aliyuncs.com/google_containers/echoserver:1.10
ports:
- containerPort: 8080
env:
- name: VERSION # 表示当前是 v1 版本
value: v1
- name: NODE_NAME # 这里我们使用该环境变量来表示版本,这样后续只需要更改该环境变量的值即可
value: version1
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
# nginx ingress 配置
---
apiVersion: v1
kind: Service
metadata:
name: echoserver
labels:
app: echoserver
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: echoserver
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echoserver
spec:
ingressClassName: nginx
rules:
- host: echo.k8s.local
http:
paths:
- path: /apis/echo
pathType: Exact
backend:
service:
name: echoserver
port:
number: 80由于要我们这里要使用金丝雀发布策略,所以需要指定流量来源,这里我们使用 Ingress 来指定流量来源。在 Ingress 中,我们指定了 echo.k8s.local 作为域名,然后在 paths 中指定了 /apis/echo 作为路径。
直接应用上面的资源对象即可:
➜ kubectl apply -f workload-canary-demo.yaml
➜ kubectl get ingress echoserver
NAME CLASS HOSTS ADDRESS PORTS AGE
echoserver nginx echo.k8s.local 10.98.12.94 80 2m42s
➜ kubectl get svc echoserver
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echoserver ClusterIP 10.97.158.14 <none> 80/TCP 2m48s
➜ kubectl get pods -l app=echoserver
NAME READY STATUS RESTARTS AGE
echoserver-6995b4bc86-4dzvb 1/1 Running 0 2m54s
echoserver-6995b4bc86-9b4qg 1/1 Running 0 2m54s
echoserver-6995b4bc86-bl82m 1/1 Running 0 2m54s
echoserver-6995b4bc86-n27v7 1/1 Running 0 2m54s
echoserver-6995b4bc86-wgjwp 1/1 Running 0 2m54s部署后我们就可以通过 http://echo.k8s.local/apis/echo 来访问我们的服务了。

echo 服务
然后接下来我们就可以使用 Rollout 来进行金丝雀发布了,定义一个如下所示的 Rollout 对象:
# rollout-canary-demo.yaml
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-canary-demo
annotations:
rollouts.kruise.io/rolling-style: canary # 指定金丝雀发布策略
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: echoserver
strategy:
canary: # 金丝雀发布策略
steps: # 步骤
- weight: 5 # 导入5%的流量
pause: {} # 表示人工确认
replicas: 1 # 第一批发布的副本个数
- weight: 40 # 导入40%的流量,没有配置 replicas,也表示发布40%的副本数
pause: { duration: 30 } # 不需要人工确认,等待30s继续下一批
- weight: 60
pause: { duration: 30 }
- weight: 80
pause: { duration: 30 }
- weight: 100
pause: { duration: 10 }
trafficRoutings: # 流量路由
- service: echoserver
ingress:
classType: nginx
name: echoserver同样直接应用上面的资源对象即可:
➜ kubectl apply -f rollout-canary-demo.yaml
rollout.kruise.io/rollouts-canary-demo created
➜ kubectl get rollout rollouts-canary-demo
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollouts-canary-demo Healthy 5 Completed workload deployment is completed 2m53s目前第一次不会有任何变化,当我们进行下一次发布的时候才能看到效果,比如这里我们修改一下 workload-canary-demo.yaml 中的 NODE_NAME 环境变量,将其修改为 version2,然后再次应用,这样就会触发一次新的发布。
我们可以开一个新的终端来查看工作负载的版本变化:
➜ while true; do curl -s http://echo.k8s.local/apis/echo |grep node; sleep 1; done应用后我们再次查看工作负载的变化:
➜ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
echoserver 5/5 0 5 26m
echoserver-prxs8 1/1 1 1 10s
➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
echoserver-64ff85db9b-5fr82 1/1 Running 0 19m
echoserver-64ff85db9b-75wds 1/1 Running 0 19m
echoserver-64ff85db9b-trw69 1/1 Running 0 19m
echoserver-64ff85db9b-w7mc4 1/1 Running 0 19m
echoserver-64ff85db9b-wcrf4 1/1 Running 0 19m
echoserver-prxs8-5ccc576f44-x988t 1/1 Running 0 4s
➜ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
echoserver nginx echo.k8s.local 10.98.12.94 80 34m
echoserver-canary nginx echo.k8s.local 10.98.12.94 80 8m27s
➜ kubectl get ingress echoserver-canary -oyaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "5"
# ......
➜ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echoserver ClusterIP 10.97.158.14 <none> 80/TCP 34m
echoserver-canary ClusterIP 10.111.53.82 <none> 80/TCP 8m40s可以看到现在自动创建了一个新的 Deployment,其副本数为 1,这个 Deployment 就是我们的金丝雀 Deployment,同样为了引入流量进来,也创建了新的 Service 和 Ingress 对象。同样查看 Rollout 状态:
➜ kubectl get rollout rollouts-canary-demo
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollouts-canary-demo Progressing 1 StepPaused Rollout is in step(1/5), and you need manually confirm to enter the next step 9m26s可以看到现在 Rollout 的状态为 Progressing,并且处于第一步,也就是上面我们配置的第一布:
- weight: 5 # 导入5%的流量
pause: {} # 表示人工确认
replicas: 1 # 第一批发布的副本个数会导入 5% 的流量进入金丝雀 Deployment,并且只发布一个新版本的副本,并且需要人工确认,再新开的终端中也可以看到会出现 version2 的版本:

watch version
接下来我们需要手动确认,同样可以通过 kubectl rollout 命令来确认:
➜ kubectl kruise rollout approve rollout/rollouts-canary-demo -n default
rollout.rollouts.kruise.io/rollouts-canary-demo approved确认后就会进行第二步的发布:
- weight: 40 # 导入40%的流量,没有配置 replicas,也表示发布40%的副本数
pause: { duration: 30 } # 不需要人工确认,等待30s继续下一批这个时候会导入 40% 的流量进入金丝雀 Deployment,副本数也会增加到 40% 的副本数,这个时候不需要人工确认,等待 30s 后继续下一步:
➜ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
echoserver 5/5 0 5 56m
echoserver-prxs8 2/2 2 2 30m由于后续步骤不需要手动确认,所以慢慢地会发布完所有的副本:
➜ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
echoserver 5/5 5 5 59m
➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
echoserver-5ccc576f44-6cl72 1/1 Running 0 51s
echoserver-5ccc576f44-9z6sw 1/1 Running 0 51s
echoserver-5ccc576f44-g2gqj 1/1 Running 0 51s
echoserver-5ccc576f44-hrltf 1/1 Running 0 51s
echoserver-5ccc576f44-r2j2z 1/1 Running 0 50s
➜ kubectl get rollout rollouts-canary-demo
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollouts-canary-demo Healthy 5 Completed Rollout progressing has been completed 42m
发布完成
发布完成后,会自动删除金丝雀 Deployment 和 Pod,同时会将流量切换到新的 Deployment 上。
到这里,我们就完成了一个金丝雀发布的过程。
A/B 测试是一种常见的测试方法,它的原理是将用户分成几组,一组使用原有的版本,另一组使用新的版本,然后观察两组用户的行为,从而判断新版本是否更好。通常 A/B 测试的目的是为了验证新版本的功能是否可用,或者新版本是否能够带来更好的用户体验,需要结合具体的业务场景来进行。
目前 A/B Testing 策略可以在 CloneSet、StatefulSet、Advanced StatefulSet 和 Deployment 上工作。
此外 A/B Testing 需要结合金丝雀或多批次发布策略,如下图所示。

AB Test
下面我们举一个 A/B Testing 多批发布策略的例子:
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
annotations:
rollouts.kruise.io/rolling-style: partition
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: workload-demo
strategy:
canary:
steps:
- replicas: 1
matches: # 匹配规则
- headers: # HTTP Header 匹配规则
- key: user-agent # HTTP Header 名称
type: Exact # 匹配类型
value: pc # 匹配值
- replicas: 50%
- replicas: 100%
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo当应用该策略后:
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po