Kruise Rollout is an open source progressive delivery framework from the OpenKruise community. It works alongside native Kubernetes workloads (Deployments and StatefulSets) and OpenKruise workloads (CloneSets and Advanced StatefulSets) to deliver canary releases, A/B testing, phased releases, and blue-green deployments that coordinate traffic shifting with instance scaling. Based on Prometheus metrics, Kruise Rollout can also automate batching and pausing during the release process. Kruise Rollout integrates with Helm, Platform as a Service (PaaS), and other deployment tools without requiring changes to your existing workflow.
This topic walks through two use cases:
-
Canary and A/B testing — route a portion of traffic to the new version using Nginx Ingress or MSE Ingress before promoting further
-
Phased release for microservice apps — roll out pods in batches without Ingress, for apps (such as Nacos-based services) where traffic shifting is handled by the microservice framework
The following figure shows the architecture for a phased release using Kruise Rollout.
How it works
Kruise Rollout intercepts workload updates and executes them in configurable steps. Each step specifies how many pods to update (replicas) and how long to pause before proceeding (pause). For Ingress-based deployments, each step also controls the traffic weight (weight) reaching the new version.
Configure a Rollout resource once and apply it to your cluster. For every subsequent deployment update, Kruise Rollout automatically intercepts the change and progresses it through the defined steps. No further changes to the Rollout resource are needed.
Prerequisites
Before you begin, ensure that you have:
-
An ACK managed cluster. For more information, see Create an ACK managed cluster.
-
Cluster version 1.19 or later for A/B testing or canary releases
-
Cluster version 1.16 or later for phased releases
-
-
kubectl-kruise installed. See kubectl-kruise.
Preparations
Step 1: Install the ack-kruise add-on
-
Log on to the ACK console. In the left navigation pane, choose Clusters.
-
On the Clusters page, click the name of the target cluster. In the left navigation pane, click Add-ons.
-
On the Add-ons page, click the Manage Applications tab. In the lower-right corner of the ack-kruise card, click Install.
-
In the dialog box, confirm the information and click OK.
The ack-kruise add-on version 1.8 or later supports the v1beta1 API. For more information, see API specifications.
Step 2: Deploy the sample application
The following steps deploy an echoserver service using a Deployment and expose it through an Ingress. This sample application is used in both use cases.
-
Create a file named
echoserver.yamlwith the following content. -
Apply the configuration.
kubectl apply -f echoserver.yaml
Use case 1: Canary release and A/B testing with Ingress
This use case shows how to configure Kruise Rollout for canary releases and A/B testing using Nginx Ingress or MSE Ingress. The trafficRoutings field in the Rollout resource connects the rollout to the Service and Ingress, enabling Kruise Rollout to manage traffic weights at each step. Each release is defined as a Rollout resource with three steps:
| Strategy | Step 1 | Step 2 | Step 3 |
|---|---|---|---|
| Canary | 20% traffic weight, 1 pod, manual pause | 50% weight, 50% pods, 60s auto-pause | 100% (full release) |
| A/B testing | Route User-Agent: Android traffic to new version, 1 pod, manual pause |
50% pods, 60s auto-pause | 100% pods |
Step 1: Install the Ingress controller and create an Ingress
Select your Ingress type and follow the corresponding instructions.
Nginx Ingress
-
Install the Nginx Ingress Controller.
-
New cluster: During cluster creation, select Nginx Ingress in the Ingress configuration section. For more information, see Create an ACK managed cluster.
-
Existing cluster: See Create and use an Nginx Ingress to expose services.
-
-
Create a file named
echoserver-ingress.yamlwith the following content.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: echoserver spec: ingressClassName: nginx rules: - http: paths: - backend: service: name: echoserver port: number: 80 path: /apis/echo pathType: Exact -
Apply the Ingress.
kubectl apply -f echoserver-ingress.yaml
MSE Ingress
-
Install the MSE Ingress Controller and create an MseIngressConfig and an IngressClass. For more information, see Access container services through an MSE Ingress.
-
Create a file named
echoserver-ingress.yamlwith the following content.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: echoserver spec: # You must set ingressClassName to mse. ingressClassName: mse rules: - http: paths: - backend: service: name: echoserver port: number: 80 path: /apis/echo pathType: Exact -
Apply the Ingress.
kubectl apply -f echoserver-ingress.yaml
Step 2: Verify access to the application
-
Retrieve the external IP address or hostname. Nginx Ingress:
export EXTERNAL_IP=$(kubectl get ingress echoserver -o jsonpath="{.status.loadBalancer.ingress[0].ip}")MSE Ingress:
export EXTERNAL_IP=$(kubectl get ingress echoserver -o jsonpath="{.status.loadBalancer.ingress[0].hostname}") -
Test access.
curl http://${EXTERNAL_IP}/apis/echoExpected output:
Hostname: echoserver-75d49c475c-ls2bs Pod Information: node name: version1 pod name: echoserver-75d49c475c-ls2bs pod namespace: default Server values: server_version=nginx: 1.13.3 - lua: 10008 ...
Step 3: Define the Rollout resource
Create a file named rollout.yaml using the strategy that matches your use case. The trafficRoutings field links the Rollout to the echoserver Service and Ingress so that Kruise Rollout can shift traffic at each step.
Canary
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: echoserver
strategy:
canary:
steps:
# Step 1: Route 20% of traffic to the new version (1 pod). Pause until manually approved.
- weight: 20
replicas: 1
pause: {}
# Step 2: Increase to 50% traffic and 50% pods. Auto-proceed after 60 seconds.
- weight: 50
replicas: 50%
pause: {duration: 60} # unit: seconds
# Step 3: Full release.
- weight: 100
replicas: 100%
pause: {duration: 60} # unit: seconds
trafficRoutings:
- service: echoserver
ingress:
name: echoserver
A/B testing
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: echoserver
strategy:
canary:
steps:
# Step 1: Route Android traffic to the new version (1 pod). Pause until manually approved.
- matches:
- headers:
- type: Exact
name: User-Agent
value: Android
pause: {}
replicas: 1
# Step 2: 50% of pods, still matching Android traffic. Auto-proceed after 60 seconds.
- matches:
- headers:
- type: Exact
name: User-Agent
value: Android
pause: {duration: 60} # unit: seconds
replicas: 50%
# Step 3: Full release.
- matches:
- headers:
- type: Exact
name: User-Agent
value: Android
pause: {duration: 60} # unit: seconds
replicas: 100%
trafficRoutings:
- service: echoserver
ingress:
name: echoserver
Apply the Rollout resource and verify it is healthy.
kubectl apply -f rollout.yaml
kubectl get rollout
Expected output:
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollouts-demo Healthy 3 Completed workload deployment is completed 7s
STATUS=Healthy confirms the Rollout resource is ready.
Step 4: Trigger the upgrade
Kruise Rollout activates automatically when the Deployment spec changes. Update the image version in echoserver.yaml to trigger a release.
# echoserver.yaml (relevant section)
spec:
containers:
- name: echoserver
image: openkruise-registry.cn-shanghai.cr.aliyuncs.com/openkruise/demo:1.10.3
env:
- name: NODE_NAME
value: version2 # Optional: helps identify the new version in verification output
Apply the updated Deployment. You can also use tools such as Helm and Vela to apply the Deployment configuration.
kubectl apply -f echoserver.yaml
Check the rollout status.
kubectl get rollouts rollouts-demo -n default
Expected output:
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 41m
The status fields show:
| Field | Value | Meaning |
|---|---|---|
STATUS |
Progressing |
Canary release is in progress |
CANARY_STEP |
1 |
Currently in step 1 of 3 |
CANARY_STATE |
StepPaused |
Step 1 is complete; waiting for manual approval |
Step 5: Verify traffic distribution and proceed
Canary
-
Access the service 10 times and observe the
node namein the output.for i in {1..10}; do curl -s http://${EXTERNAL_IP}/apis/echo | grep 'node name'; sleep 1; doneExpected output (approximately 8 requests to version1, 2 to version2):
node name: version1 node name: version1 node name: version2 node name: version1 node name: version2 node name: version1 node name: version1 node name: version1 node name: version1 node name: version1The 8:2 ratio matches the 20% weight configured in step 1.
-
Approve step 1 to proceed to step 2.
kubectl-kruise rollout approve rollouts/rollouts-demo -n default -
Monitor the rollout as it progresses through steps 2 and 3.
kubectl get rollouts rollouts-demo -n default -wThe rollout automatically advances through step 2 (50% weight, 60s pause) and step 3 (100%, 60s pause). The rollout is complete when
STATUS=HealthyandCANARY_STATE=Completed.
A/B testing
-
Send requests with and without the
User-Agent: Androidheader.curl -s http://${EXTERNAL_IP}/apis/echo | grep 'Pod Information:' -A 3 curl -sH "User-Agent: Android" http://${EXTERNAL_IP}/apis/echo | grep 'Pod Information:' -A 3Expected output:
Pod Information: node name: version1 pod name: echoserver-69598f9458-7c66v pod namespace: default Pod Information: node name: version2 pod name: echoserver-fvhzg-687b4b56-qbhc8 pod namespace: defaultThe request without the header reaches version1; the Android request reaches version2. The header-based routing rule is working.
-
Approve step 1 to proceed to step 2.
kubectl-kruise rollout approve rollouts/rollouts-demo -n default -
Monitor the rollout until it completes.
kubectl get rollouts rollouts-demo -n default -wThe rollout automatically advances through step 2 and step 3. The rollout is complete when
STATUS=HealthyandCANARY_STATE=Completed.
Roll back if the new version is abnormal
If the new version behaves unexpectedly at any step, restore the previous Deployment configuration and reapply. No changes to the Rollout resource are required.
# echoserver.yaml (rollback version)
spec:
containers:
- name: echoserver
image: openkruise-registry.cn-shanghai.cr.aliyuncs.com/openkruise/demo:1.10.2
env:
- name: NODE_NAME
value: version1kubectl apply -f echoserver.yaml
Use case 2: Phased release for microservice apps
Apps built on microservice frameworks such as Nacos handle traffic shifting internally and do not require Ingress or Service-level traffic routing. For these apps, use Kruise Rollout's partition-based phased release, which rolls out pods in batches without the trafficRoutings field.
Because traffic shifting is managed by the microservice framework itself, this use case does not demonstrate traffic distribution verification. It shows only how to progress through rollout batches.
Step 1: Define and deploy the Rollout resource
The following Rollout uses the partition rolling style and releases pods in three batches: 1 pod, then 50%, then 100%. The trafficRoutings field is omitted because the microservice framework manages traffic routing.
# Save as rollout.yaml
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: echoserver
strategy:
canary:
steps:
# Step 1: Update 1 pod. Pause until manually approved.
- replicas: 1
pause: {}
# Step 2: Update 50% of pods. Auto-proceed after 60 seconds.
- replicas: 50%
pause: {duration: 60} # unit: seconds
# Step 3: Update all pods.
- replicas: 100%
pause: {duration: 60} # unit: secondskubectl apply -f rollout.yaml
Step 2: Trigger the upgrade
Update the image version in echoserver.yaml.
# echoserver.yaml (relevant section)
spec:
containers:
- name: echoserver
image: openkruise-registry.cn-shanghai.cr.aliyuncs.com/openkruise/demo:1.10.3
env:
- name: NODE_NAME
value: version2 # Optional: helps identify the new versionkubectl apply -f echoserver.yaml
Step 3: Check rollout status
kubectl get rollouts rollouts-demo -n default
Expected output:
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 41m
| Field | Value | Meaning |
|---|---|---|
STATUS |
Progressing |
Release is in progress |
CANARY_STEP |
1 |
Currently in step 1 of 3 |
CANARY_STATE |
StepPaused |
Step 1 is complete; waiting for manual approval |
Step 4: Approve batches and monitor progress
Approve step 1 to move to step 2.
kubectl-kruise rollout approve rollouts/rollouts-demo -n default
Monitor the rollout as it progresses.
kubectl get rollouts rollouts-demo -n default -w
After you approve step 1, the rollout automatically advances through step 2 (50% pods, 60s pause) and step 3 (all pods, 60s pause). Key state transitions to watch for:
CANARY_STATE |
Meaning |
|---|---|
StepPaused |
Batch complete; either waiting for manual approval or timed auto-pause |
StepUpgrade |
Upgrading pods in this batch |
StepReady |
Batch upgrade complete |
Completed |
All steps finished |
The rollout is complete when STATUS=Healthy and CANARY_STATE=Completed.
Roll back if the new version is abnormal
If the new version behaves unexpectedly, restore the previous Deployment configuration and reapply. No changes to the Rollout resource are required.
# echoserver.yaml (rollback version)
spec:
containers:
- name: echoserver
image: openkruise-registry.cn-shanghai.cr.aliyuncs.com/openkruise/demo:1.10.2
env:
- name: NODE_NAME
value: version1kubectl apply -f echoserver.yaml
What's next
-
Learn about Kruise Rollout's full configuration options: API specifications
-
Explore the OpenKruise Rollout project: Kruise Rollout on GitHub