Skip to main content

ArgoCD Sync Waves

Sync waves control the order of resource deployment in ArgoCD. Lower wave numbers deploy first, ensuring dependencies are ready before dependent resources start.

Wave Assignment

WaveResourcesPurpose
-2NamespaceCreate the namespace first
-1ServiceAccount, Role, RoleBinding, credential-generator Job, image-versions ConfigMapRBAC setup and secret generation
0PostgreSQL init, S3 credentials syncDatabase and storage provisioning
1Deployments, Services (backend, frontend, worker)Application workloads
2IngressRoute, Certificate, CronJob, RabbitMQ resourcesExternal access and scheduled tasks
3RedisCache (deployed after workloads to save resources)

How It Works

ArgoCD processes resources in wave order:

Wave -2: Create namespace


Wave -1: Create RBAC, run credential-generator Job
│ (creates pg, rabbitmq, redis, app-key secrets)

Wave 0: S3 credentials sync Job
│ (waits for CephObjectStoreUser, copies to namespace)

Wave 1: Deploy backend, frontend, worker
│ (all secrets exist at this point)

Wave 2: Create IngressRoutes, TLS certs, CronJobs


Wave 3: Deploy Redis

Credential Generator

The credential-generator is a Kubernetes Job that runs at sync-wave -1:

annotations:
argocd.argoproj.io/sync-wave: "-1"
argocd.argoproj.io/hook: Sync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation

It creates these secrets (only if they don't exist):

SecretHow
{app}-pg-credentialsConnects to PostgreSQL superuser, creates DB + user via psql
{app}-rabbitmq-credentialsGenerates random password, creates import secret in rabbitmq-system
{app}-app-secretsGenerates Laravel APP_KEY via openssl rand
{app}-redis-credentialsGenerates random password for Redis

The Job is idempotent — it checks each secret individually and only creates missing ones.

S3 Credentials Sync

A separate Job at sync-wave 0 handles S3 credentials:

annotations:
argocd.argoproj.io/sync-wave: "0"
argocd.argoproj.io/hook: Sync

It waits for the CephObjectStoreUser to be provisioned by Rook-Ceph, then copies the access key and secret key to the application namespace.

Hook Policies

AnnotationValueMeaning
argocd.argoproj.io/hookSyncRun during every sync
argocd.argoproj.io/hook-delete-policyBeforeHookCreationDelete previous Job before creating new one

This ensures the credential-generator runs on every sync but doesn't accumulate old Jobs.

Troubleshooting

Pods stuck in CreateContainerConfigError

Cause: A required Secret doesn't exist yet (credential-generator or S3 sync failed).

Fix:

  1. Check credential-generator Job logs: kubectl logs job/vecton-admin-credential-generator -n vecton-admin
  2. Check if all secrets exist: kubectl get secrets -n vecton-admin
  3. If a secret is missing, delete the Job and re-sync: ArgoCD will recreate it

Sync wave ordering issues

If resources deploy out of order:

  • Verify argocd.argoproj.io/sync-wave annotation is set correctly
  • Remember: ArgoCD processes waves sequentially — wave 1 won't start until wave 0 is healthy
  • Hooks (Jobs) in a wave must complete before the next wave starts