Roll back a Release
Return a Release to an earlier render with a pin, or let convoy roll back a failed rollout automatically.
This guide shows two ways to return a Release to an earlier render. In part 1, you select a render from the history and pin the Release to it. In part 2, convoy detects a rollout that does not become healthy before a deadline, and applies the last healthy render. The two ways read the renders from the render store. For the full behavior, see Pin and history and Progressive rollout.
Before you start#
- Configure a render store. Set the same
--render-store-urlonconvoy-controller-managerand onconvoy-observer. See Render store backends. - Do not use
mem://. The observer cannot read the renders of the controller-manager from it. - Make sure that the
GitRepositorypodinfoand theClusterdev-localexist. See Deploy from Git. - Make sure that a
GlobalHealthRuleSetwith the labelconvoy.kumodo.io/default: "true"exists. See Add health rules to a Release. - Save each example under the file name in its title bar. The commands use these file names.
Without a render store, history returns 503 Service Unavailable. A pin to an earlier render
fails, and an automatic rollback cannot occur.
Steps#
Part 1: Roll back manually with a pin#
1. Deploy the first render#
The Release has spec.healthAssessment and spec.failurePolicy. Part 2 uses these fields.
apiVersion: core.convoy.kumodo.io/v1alpha1
kind: Release
metadata:
name: podinfo-rollback
namespace: default
spec:
clusterRef:
name: dev-local
source:
type: gitRepository
gitRepository:
name: podinfo
namespace: default
ref:
branch: master
content:
type: helm
helm:
path: charts/podinfo
releaseName: podinfo-rollback
values:
- type: inline
inline:
image:
tag: 6.14.0
replicaCount: 1
syncPolicy:
automatic: true
interval: 1m
healthAssessment:
globalRuleSetSelector:
matchLabels:
convoy.kumodo.io/default: "true"
deadline: 2m
failurePolicy:
rollback: OnReleaseFailure
Apply the Release.
kubectl apply -f guides/release-podinfo-rollback.yamlMonitor the Release until
STATEisSucceeded.kubectl get releases podinfo-rollback -w
2. Deploy a second render#
This version sets replicaCount: 2. The render changes, so it gets a new renderRef.
apiVersion: core.convoy.kumodo.io/v1alpha1
kind: Release
metadata:
name: podinfo-rollback
namespace: default
spec:
clusterRef:
name: dev-local
source:
type: gitRepository
gitRepository:
name: podinfo
namespace: default
ref:
branch: master
content:
type: helm
helm:
path: charts/podinfo
releaseName: podinfo-rollback
values:
- type: inline
inline:
image:
tag: 6.14.0
replicaCount: 2
syncPolicy:
automatic: true
interval: 1m
healthAssessment:
globalRuleSetSelector:
matchLabels:
convoy.kumodo.io/default: "true"
deadline: 2m
failurePolicy:
rollback: OnReleaseFailure
Apply the second version.
kubectl apply -f guides/release-podinfo-rollback-v2.yamlMonitor the Release until
STATEisSucceededagain.
3. Find the render in the history#
Show the history.
kubectl convoy release history podinfo-rollbackFind the two entries. Each line has the time of the first apply, the
renderRefand the source summary. The newest entry is first.Copy the
renderRefof the second line. This is the first render.
4. Examine the change#
Compare the first render with the live objects.
kubectl convoy release diff podinfo-rollback --render sha256:…Find the
Deployment. The output showsspec.replicaswith the live value2and the stored value1.
The output shows what the rollback changes. For the full result, add -o json.
5. Pin the first render#
Pin the Release to the first render.
kubectl convoy release pin podinfo-rollback --render-ref sha256:…Read the pin status.
kubectl get releases podinfo-rollback -o jsonpath='{.status.pin.intent}'Examine the value. It is
rollbackuntil convoy applies the pinned render. Then it isfreeze.
The pin starts a reconcile immediately. convoy reads the pinned render from the store and applies it with the usual apply: dry run, hooks, sync waves and prune. While the pin is set, convoy does not run the rollout state machine. A change to the source does not change the cluster.
If the pinned render is not in the store, Applied is False with reason Pinned. convoy
applies nothing.
6. Clear the pin#
Clear the pin.
kubectl convoy release unpin podinfo-rollbackMake sure that convoy applies the current render again.
spec.replicasof theDeploymentchanges to2.
Part 2: Let convoy roll back a failed rollout#
7. Examine the failure policy#
The Release from part 1 has these fields:
spec:
healthAssessment:
deadline: 2m
failurePolicy:
rollback: OnReleaseFailuredeadlineis the maximum time for a new render to become healthy. The time starts atstatus.rollout.startedAt.rollback: OnReleaseFailureapplies the last healthy render when the deadline passes.- A
rollbackvalue other thanNeverrequiresspec.healthAssessment.deadline. The API rejects a Release without it.
8. Deploy a render that fails#
This version uses an image tag that does not exist. The new pods cannot start.
apiVersion: core.convoy.kumodo.io/v1alpha1
kind: Release
metadata:
name: podinfo-rollback
namespace: default
spec:
clusterRef:
name: dev-local
source:
type: gitRepository
gitRepository:
name: podinfo
namespace: default
ref:
branch: master
content:
type: helm
helm:
path: charts/podinfo
releaseName: podinfo-rollback
values:
- type: inline
inline:
image:
tag: 0.0.0-does-not-exist
replicaCount: 2
syncPolicy:
automatic: true
interval: 1m
healthAssessment:
globalRuleSetSelector:
matchLabels:
convoy.kumodo.io/default: "true"
deadline: 2m
failurePolicy:
rollback: OnReleaseFailure
Apply the broken version.
kubectl apply -f guides/release-podinfo-rollback-broken.yamlMonitor the Release.
kubectl get releases podinfo-rollback -wExamine the
STATEcolumn. It isProgressinguntil the deadline passes. Then it isRolledBack.
The rollback applies the last healthy render. This apply is smaller than a usual apply:
- It applies all objects in one step. It does not use sync waves.
- It does not run the dry run or the lifecycle hooks.
- It does not add a history entry.
9. Start the rollout again#
A RolledBack rollout stays until a new rollout starts. Do the checks of “Check the result”
before this step. Then select one of two options:
- The cause is in the manifest: correct the manifest and apply it. A new render starts a new rollout.
- The cause is outside the render, for example a missing image: correct the cause, then send a forced sync.
To send a forced sync, do these steps:
Send a forced sync.
kubectl convoy release sync podinfo-rollback --forceMake sure that
STATEchanges toProgressing.
A forced sync skips the pre-apply dry run. It starts a new rollout from Failed or RolledBack.
If the cause is still there, the rollout fails again at the deadline.
Check the result#
Read the rollout status.
kubectl get releases podinfo-rollback -o jsonpath='{.status.rollout}'After the rollback, make sure that
stateisRolledBack.messagenames the render that convoy applied.Compare this render with
status.lastHealthy.renderRef. The two values must be the same.Make sure that the
RolloutSucceededcondition isFalse.kubectl describe releases podinfo-rollbackMake sure that
AppliedisTruewith reasonRolledBack.Make sure that the pods of the
Deploymentuse the image tag6.14.0.
RolloutSucceeded · written by convoy-controller-manager (field manager convoy-release)
| Reason | Status | Meaning |
|---|---|---|
Progressing | Unknown | convoy waits for the resources of the render to become healthy. |
Succeeded | True | All resources of the render became healthy. |
Failed | False | The resources did not become healthy before the deadline, and convoy did not roll back. |
RolledBack | False | The resources did not become healthy before the deadline, and convoy applied the last healthy render. |
Clean up#
Delete the Release.
kubectl delete releases podinfo-rollback
convoy deletes the keys of the Release in the render store before it clears the finalizer.
Next steps#
- Read Pin and history for the retention of renders.
- Read Progressive rollout for the rollout states.
- Roll back on a sync wave timeout with
OnWaveFailure. See Sync waves. - Write the health rules that decide the rollout. See Health rules.
In the code
convoy v0.9.0
internal/cli/release.runPininternal/cli/release/command.go:262internal/controller/release.(*Controller).resolvePinnedRenderinternal/controller/release/controller.go:986internal/controller/release.pinStatusinternal/controller/release/controller.go:1713internal/controller/release.(*Controller).planRolloutinternal/controller/release/controller.go:1511internal/controller/release.rollbackEligibleinternal/controller/release/controller.go:1568internal/controller/release.(*Controller).applyLastHealthyinternal/controller/release/controller.go:1644