How to enable ArgoCD sync waves between apps in Kubernetes

This article provides insights on configuring the sync waves function in ArgoCD for optimal performance in an App of Apps framework.

Series - ArgoCD Insights

Here you will learn how to configure the sync waves feature in ArgoCD to work in an App of Apps pattern. If you have tried the app of apps pattern, you might have noticed that placing the sync-wave annotation does not work between individual applications, just between manifests in a singular application. This is because the health assessment of applications has been removed in version 1.8 of ArgoCD.

In short, the sync wave annotation, when added to ArgoCD applications, informs the engine that there is an order of synchronization. For example, if you wanted to generate a certificate by using cert-manager in Kubernetes for your own application, without the sync waves, the both deployments will run at once, and the synchronization will fail because your application can’t find the Certificate resource. This can be solved by adding the sync-wave annotation to both applications.

The priority is calculated from the smallest to the highest number. If you add this to the cert-manager application metadata:

1
2
annotations:
  argocd.argoproj.io/sync-wave: "-2"

you will have to add the following to your own application:

1
2
annotations:
  argocd.argoproj.io/sync-wave: "-1"

This should work, but as mentioned above, the disabled health assessment of applications is directly tied to the sync waves. When the cert-manager app is not healthy yet, your application has to wait for the health assessment to pass. ArgoCD supports adding custom Lua scripts to the main configuration, and this is what we will use to enable the health assessment.

The first method is using the kubectl edit command to add/remove live manifest configuration. Run the following (replace the editor with your own):

1
2
EDITOR=vim
kubectl edit configmap argocd-cm -n argocd

After that, add the following Lua custom script in data to enable the health assessment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
data:
  resource.customizations.health.argoproj.io_Application: |
        hs = {}
        hs.status = "Progressing"
        hs.message = ""
        if obj.status ~= nil then
          if obj.status.health ~= nil then
            hs.status = obj.status.health.status
            if obj.status.health.message ~= nil then
              hs.message = obj.status.health.message
            end
          end
        end
        return hs        

Save the file, and you are done.

The second method is if you installed, or plan on installing ArgoCD with the official helm chart. Create the custom-values.yaml file and add the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
configs:
  cm:
    resource.customizations.health.argoproj.io_Application: |
      hs = {}
      hs.status = "Progressing"
      hs.message = ""
      if obj.status ~= nil then
        if obj.status.health ~= nil then
          hs.status = obj.status.health.status
          if obj.status.health.message ~= nil then
            hs.message = obj.status.health.message
          end
        end
      end
      return hs      

Now, if you are installing ArgoCD from scratch, run the following:

1
2
3
4
kubectl create namespace argocd
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd -n argocd argo/argo-cd -f custom-values.yaml

This will install ArgoCD in the argocd namespace and the argocd-cm configmap will be edited from the start. If you already have ArgoCD installed with Helm in your Kubernetes cluster, run the following after the creation of the custom-values.yaml file:

1
helm upgrade argocd -n argocd argo/argo-cd -f custom-values.yaml

And that is it. Your sync wave annotations should work now in an App of Apps pattern.