convoy docs
Search

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#

Steps#

1. Put the resources in waves#

convoy reads three annotations on each rendered resource:

AnnotationValueDefault
convoy.kumodo.io/sync-waveA signed integer0
convoy.kumodo.io/sync-strategywaitForApplied, waitForHealthy or waitForHealthyWithTimeoutwaitForApplied
convoy.kumodo.io/sync-timeoutA Go duration30s

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:

    yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: podinfo
      annotations:
        convoy.kumodo.io/sync-wave: "1"
        convoy.kumodo.io/sync-strategy: waitForHealthy
  • If you do not control the source, set the annotations with a syncWave mutation. The example in step 2 uses a mutation.

2. Apply the Release#

guides/release-sync-waves.yaml
# 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
  1. Save the example as release-sync-waves.yaml.

  2. Make sure that spec.healthAssessment selects at least one rule set.

  3. Apply the file:

    sh
    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:

yaml
- type: syncWave
  target:
    group: ""
    version: v1
    kind: Service
  waveStrategy:
    wave: 1
    strategy: waitForHealthy

Then add the list to the Release:

sh
kubectl convoy release mutations add podinfo-in-cluster -f wave.yaml

3. Set a time limit (optional)#

  1. Set the strategy to waitForHealthyWithTimeout.
  2. Set the time limit in convoy.kumodo.io/sync-timeout, or in waveStrategy.timeout of 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.

guides/release-cluster-waves.yaml
# 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
  1. Save the example as release-cluster-waves.yaml.

  2. Give each predecessor Release a spec.healthAssessment.

  3. Apply the file:

    sh
    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#

  1. Get the Releases:

    sh
    kubectl get releases
  2. Read the APPLIED and HEALTHY columns.

  3. Read the status of the Release with waves:

    sh
    kubectl get release podinfo-waves -o yaml
  4. Read the Applied condition and status.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 reasonMeaning
WaitingForWaveHealthA wave waits for the previous wave to be healthy. convoy does not prune.
WaveFailedThe time limit of a wave passed. The previous wave is not healthy.
WaitingForClusterWaveThe Release waits for a Release with a lower cluster wave. The message names it.
ClusterWaveFailedThe waveStrategy.timeout passed. A predecessor did not pass the bar.
  1. Read the Applied condition of podinfo-frontend:

    sh
    kubectl get release podinfo-frontend -o yaml
  2. Make sure that the reason is WaitingForClusterWave until podinfo-backend is healthy.

Clean up#

  1. Delete the Releases:

    sh
    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#

In the code

convoy v0.9.0