Order resources with sync waves
Apply resources and Releases in a fixed order, with health gates between the waves.
Sync waves set the order in which convoy applies resources. In this guide, you put the Service of
podinfo in a later wave than its Deployment. convoy applies the Service only after the Deployment
is healthy. Then you order two Releases on one cluster with spec.syncPolicy.waveStrategy. For
the full model, see Sync waves.
Before you start#
- convoy runs on your cluster.
- The
Clusterdev-local, theGitRepositorypodinfoand theHelmRegistrypodinfoexist in the namespacedefault. See Deploy from Git and Deploy a Helm chart. - The default
GlobalHealthRuleSetexists. See Add health rules to a Release. - The kubectl convoy plugin is on your
PATH.
Steps#
1. Put the resources in waves#
convoy reads three annotations on each rendered resource:
| Annotation | Value | Default |
|---|---|---|
convoy.kumodo.io/sync-wave | A signed integer | 0 |
convoy.kumodo.io/sync-strategy | waitForApplied, waitForHealthy or waitForHealthyWithTimeout | waitForApplied |
convoy.kumodo.io/sync-timeout | A Go duration | 30s |
Put the strategy on the resources of the wave that waits. That wave waits for the wave immediately before it. It does not wait for lower waves.
Do one of these two things:
If you control the source, write the annotations in the manifest:
apiVersion: v1 kind: Service metadata: name: podinfo annotations: convoy.kumodo.io/sync-wave: "1" convoy.kumodo.io/sync-strategy: waitForHealthyIf you do not control the source, set the annotations with a
syncWavemutation. The example in step 2 uses a mutation.
2. Apply the Release#
# A Release with two sync waves. The syncWave mutation puts the Service in
# wave 1 with waitForHealthy. The Deployment stays in wave 0. convoy applies
# the Service only after the Deployment is Healthy. The health gate needs
# spec.healthAssessment.
apiVersion: core.convoy.kumodo.io/v1alpha1
kind: Release
metadata:
name: podinfo-waves
namespace: default
mutations:
- type: syncWave
target:
group: ""
version: v1
kind: Service
waveStrategy:
wave: 1
strategy: waitForHealthy
spec:
clusterRef:
name: dev-local
source:
type: gitRepository
gitRepository:
name: podinfo
namespace: default
ref:
branch: master
content:
type: manifests
manifests:
paths:
- kustomize/deployment.yaml
- kustomize/service.yaml
healthAssessment:
globalRuleSetSelector:
matchLabels:
convoy.kumodo.io/default: "true"
deadline: 2m
syncPolicy:
automatic: true
prune:
orphaned: false
includeCRDs: false
includeNamespaces: false
interval: 1m
Save the example as
release-sync-waves.yaml.Make sure that
spec.healthAssessmentselects at least one rule set.Apply the file:
kubectl apply -f release-sync-waves.yaml
For an existing Release, for example podinfo-in-cluster, add the mutation with the plugin. That
Release must also have spec.healthAssessment. Write the mutation list to a file, for example
wave.yaml:
- type: syncWave
target:
group: ""
version: v1
kind: Service
waveStrategy:
wave: 1
strategy: waitForHealthyThen add the list to the Release:
kubectl convoy release mutations add podinfo-in-cluster -f wave.yaml3. Set a time limit (optional)#
- Set the strategy to
waitForHealthyWithTimeout. - Set the time limit in
convoy.kumodo.io/sync-timeout, or inwaveStrategy.timeoutof the mutation.
The time limit starts at status.waves[].startedAt of the previous wave. When the time passes
and the previous wave is not healthy, the wave fails. Without spec.failurePolicy, the
Applied reason is WaveFailed. See Roll back a Release for the rollback
options.
4. Order two Releases on one cluster#
spec.syncPolicy.waveStrategy sets the cluster wave of a Release. A Release waits for all
Releases with a lower wave on the same Cluster. Releases with the same wave do not wait for
each other.
# Two Releases on one Cluster, ordered with spec.syncPolicy.waveStrategy.
# podinfo-backend is in cluster wave 0. podinfo-frontend is in cluster wave 1
# with waitForHealthy: convoy applies it only when podinfo-backend has
# Healthy=True. podinfo-backend has a health assessment, so its Healthy
# condition reflects its workloads.
apiVersion: core.convoy.kumodo.io/v1alpha1
kind: Release
metadata:
name: podinfo-backend
namespace: default
spec:
clusterRef:
name: dev-local
source:
type: helmRegistry
helmRegistry:
name: podinfo
namespace: default
chart:
name: podinfo
version: "6.12.0"
content:
type: helm
helm:
releaseName: podinfo-backend
releaseNamespace: default
dependencyMode: vendored
healthAssessment:
globalRuleSetSelector:
matchLabels:
convoy.kumodo.io/default: "true"
deadline: 2m
syncPolicy:
automatic: true
prune:
orphaned: false
includeCRDs: false
includeNamespaces: false
interval: 1m
waveStrategy:
wave: 0
strategy: waitForApplied
---
apiVersion: core.convoy.kumodo.io/v1alpha1
kind: Release
metadata:
name: podinfo-frontend
namespace: default
spec:
clusterRef:
name: dev-local
source:
type: helmRegistry
helmRegistry:
name: podinfo
namespace: default
chart:
name: podinfo
version: "6.12.0"
content:
type: helm
helm:
releaseName: podinfo-frontend
releaseNamespace: default
dependencyMode: vendored
healthAssessment:
globalRuleSetSelector:
matchLabels:
convoy.kumodo.io/default: "true"
deadline: 2m
syncPolicy:
automatic: true
prune:
orphaned: false
includeCRDs: false
includeNamespaces: false
interval: 1m
waveStrategy:
wave: 1
strategy: waitForHealthy
Save the example as
release-cluster-waves.yaml.Give each predecessor Release a
spec.healthAssessment.Apply the file:
kubectl apply -f release-cluster-waves.yaml
With waitForApplied, each predecessor must have Applied=True. With waitForHealthy, each
predecessor must have Healthy=True.
Check the result#
Get the Releases:
kubectl get releasesRead the
APPLIEDandHEALTHYcolumns.Read the status of the Release with waves:
kubectl get release podinfo-waves -o yamlRead the
Appliedcondition andstatus.waves.
While wave 1 waits, Applied is False with reason WaitingForWaveHealth. The message names
the wave that is not healthy. status.waves has an entry for wave 0 only. When the Deployment
is Healthy, convoy applies wave 1. Then Applied is True, and status.waves has two entries.
Applied reason | Meaning |
|---|---|
WaitingForWaveHealth | A wave waits for the previous wave to be healthy. convoy does not prune. |
WaveFailed | The time limit of a wave passed. The previous wave is not healthy. |
WaitingForClusterWave | The Release waits for a Release with a lower cluster wave. The message names it. |
ClusterWaveFailed | The waveStrategy.timeout passed. A predecessor did not pass the bar. |
Read the
Appliedcondition ofpodinfo-frontend:kubectl get release podinfo-frontend -o yamlMake sure that the reason is
WaitingForClusterWaveuntilpodinfo-backendis healthy.
Clean up#
Delete the Releases:
kubectl delete -f release-sync-waves.yaml kubectl delete -f release-cluster-waves.yaml
convoy deletes the deployed resources of each Release. See Deletion.
Next steps#
- Sync waves: the gates, the time limits and
status.waves. - Add health rules to a Release: the health bar of a wave.
- Run lifecycle hooks: run Jobs before and after the waves.
- Change rendered objects with mutations: the other mutation types.
In the code
convoy v0.9.0
internal/render.applySyncWaveinternal/render/mutate.go:122internal/waves.Groupinternal/waves/waves.go:103internal/controller/release.(*Controller).waveHealthGateinternal/controller/release/controller.go:1593internal/controller/release.precedingWaveHealthyinternal/controller/release/controller.go:2063internal/controller/release.(*Controller).clusterWaveGateinternal/controller/release/controller.go:1968internal/waves.ClusterPredecessorsinternal/waves/cluster.go:68