ArgoCD Sync Policies
Sync policies control when and how ArgoCD synchronizes applications. They determine whether syncs happen automatically or manually, what happens during sync, and when syncs are allowed or blocked.
Sync Policy Overview
A sync policy defines:
- When to sync - Automated or manual
- What to sync - Which resources and options
- How to sync - Sync strategy and hooks
- When syncs are allowed - Sync windows
Automated Sync
Automated sync automatically applies changes from Git to the cluster when differences are detected.
Basic Automated Sync
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app
namespace: argocd
spec:
syncPolicy:
automated:
prune: true # Delete resources removed from Git
selfHeal: true # Automatically sync on cluster drift
Automated Sync Options
- prune - Automatically delete resources that exist in cluster but not in Git
- selfHeal - Automatically sync when cluster state drifts from Git
- allowEmpty - Allow applications with no resources (default: false)
Example: Full Automated Sync
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app
namespace: argocd
spec:
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PruneLast=true
Manual Sync
Manual sync requires explicit user action to apply changes.
Manual Sync Configuration
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-app
namespace: argocd
spec:
syncPolicy:
# No automated section = manual sync
syncOptions:
- CreateNamespace=true
Triggering Manual Sync
# Sync application
argocd app sync production-app
# Sync with specific revision
argocd app sync production-app --revision v1.2.3
# Sync with prune
argocd app sync production-app --prune
# Sync with force (bypass hooks)
argocd app sync production-app --force
Sync Options
Sync options control how resources are synchronized.
Common Sync Options
- CreateNamespace=true - Create namespace if it doesn’t exist
- PruneLast=true - Prune resources after all other resources are synced
- PrunePropagationPolicy=foreground - Prune with foreground deletion
- RespectIgnoreDifferences=true - Respect ignore differences settings
- ApplyOutOfSyncOnly=true - Only sync out-of-sync resources
Example with Sync Options
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app
namespace: argocd
spec:
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- PruneLast=true
- PrunePropagationPolicy=foreground
- RespectIgnoreDifferences=true
Sync Strategies
Sync strategies define the order and method of applying resources.
Hook-Based Sync
Use hooks to run operations before, during, or after sync.
Sync Waves
Control the order of resource synchronization using annotations:
apiVersion: apps/v1
kind: Deployment
metadata:
name: database
annotations:
argocd.argoproj.io/sync-wave: "1" # Sync first
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
annotations:
argocd.argoproj.io/sync-wave: "2" # Sync after database
---
apiVersion: v1
kind: Service
metadata:
name: api
annotations:
argocd.argoproj.io/sync-wave: "3" # Sync last
Lower wave numbers sync first. Default wave is 0.
Sync Wave Example
Sync Hooks
Hooks are Kubernetes resources that run at specific points during sync.
Hook Types
- PreSync - Runs before sync
- Sync - Runs during sync (replaces normal sync)
- PostSync - Runs after sync
- SyncFail - Runs if sync fails
PreSync Hook Example
Run database migrations before deploying application:
apiVersion: batch/v1
kind: Job
metadata:
name: database-migration
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: myapp:migrate
command: ["/bin/sh", "-c", "python manage.py migrate"]
restartPolicy: Never
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
# No hook annotation = normal resource
PostSync Hook Example
Run smoke tests after deployment:
apiVersion: batch/v1
kind: Job
metadata:
name: smoke-tests
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: test
image: myapp:test
command: ["/bin/sh", "-c", "npm test"]
restartPolicy: Never
Hook Delete Policies
Control when hooks are deleted:
- HookSucceeded - Delete when hook succeeds
- HookFailed - Delete when hook fails
- BeforeHookCreation - Delete previous hook before creating new one
apiVersion: batch/v1
kind: Job
metadata:
name: pre-sync-job
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
# ...
Complete Hook Example
# PreSync: Backup database
apiVersion: batch/v1
kind: Job
metadata:
name: backup-db
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: backup
image: postgres:14
command: ["pg_dump", "-h", "db", "-U", "user", "mydb"]
restartPolicy: Never
---
# Normal resource: Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
# ...
---
# PostSync: Health check
apiVersion: batch/v1
kind: Job
metadata:
name: health-check
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: check
image: curlimages/curl
command: ["curl", "-f", "http://web-app/health"]
restartPolicy: Never
Sync Windows
Sync windows define when Applications can be synced. Useful for:
- Preventing deployments during business hours
- Maintenance windows
- Change freeze periods
Application-Level Sync Windows
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-app
namespace: argocd
spec:
syncPolicy:
syncWindows:
- kind: allow
schedule: '0 2 * * *' # 2 AM daily
duration: 1h
manualSync: true
- kind: deny
schedule: '* * * * *' # All other times
Project-Level Sync Windows
Define sync windows at the Project level:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: production
namespace: argocd
spec:
syncWindows:
- kind: allow
schedule: '0 2 * * 1-5' # Weekdays 2 AM
duration: 2h
applications:
- 'production-*'
manualSync: true
- kind: deny
schedule: '* * * * *' # All other times
applications:
- 'production-*'
Sync Window Schedule Format
Uses cron syntax: minute hour day month weekday
Examples:
0 2 * * *- Daily at 2 AM0 2 * * 1-5- Weekdays at 2 AM0 */4 * * *- Every 4 hours0 9-17 * * 1-5- Business hours on weekdays
Sync Window Properties
- kind -
allowordeny - schedule - Cron expression
- duration - How long the window lasts (e.g.,
1h,30m) - applications - Which applications (supports wildcards)
- namespaces - Which namespaces (supports wildcards)
- clusters - Which clusters (supports wildcards)
- manualSync - Allow manual sync during deny windows
Example: Business Hours Restriction
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: production
namespace: argocd
spec:
syncWindows:
# Allow syncs during maintenance window
- kind: allow
schedule: '0 2 * * 1-5' # Weekdays 2-4 AM
duration: 2h
applications:
- 'production-*'
manualSync: true
# Deny all other times
- kind: deny
schedule: '* * * * *'
applications:
- 'production-*'
manualSync: false # No manual syncs outside window
Sync Status and Conditions
Monitor sync status and conditions:
# Get sync status
argocd app get web-app
# View sync operation details
argocd app get web-app --show-operation
# Check sync history
argocd app history web-app
Sync Conditions
Applications have sync conditions:
- Synced - Application is in sync
- Healthy - All resources are healthy
- Progressing - Sync is in progress
- Degraded - Some resources are unhealthy
- Suspended - Sync is paused
Sync Conflicts
Handling Conflicts
When cluster state conflicts with Git:
# View differences
argocd app diff web-app
# Force sync (overwrites cluster changes)
argocd app sync web-app --force
# Use replace strategy
argocd app sync web-app --strategy replace
Ignore Differences
Ignore specific fields that change in cluster:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app
namespace: argocd
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas # Ignore replica count changes
- group: v1
kind: Service
jsonPointers:
- /spec/clusterIP # Ignore cluster IP changes
Best Practices
1. Use Automated Sync for Development
spec:
syncPolicy:
automated:
prune: true
selfHeal: true
2. Use Manual Sync for Production
spec:
syncPolicy:
# No automated section
syncOptions:
- CreateNamespace=true
3. Use Sync Windows for Production
spec:
syncPolicy:
syncWindows:
- kind: allow
schedule: '0 2 * * 1-5'
duration: 2h
manualSync: true
4. Use Hooks for Complex Deployments
- PreSync for migrations, backups
- PostSync for health checks, notifications
- Delete policies to clean up hooks
5. Use Sync Waves for Dependencies
Order resources by dependencies using sync waves.
6. Monitor Sync Status
Set up alerts for:
- Sync failures
- OutOfSync state
- Degraded applications
Troubleshooting
Sync Stuck
# Check sync status
argocd app get web-app
# View operation details
argocd app get web-app --show-operation
# Force sync
argocd app sync web-app --force
Hook Failures
# Check hook status
kubectl get jobs -n <NAMESPACE>
# View hook logs
kubectl logs job/<HOOK_NAME> -n <NAMESPACE>
# Retry sync
argocd app sync web-app
Sync Window Issues
# Check active sync windows
argocd app get web-app
# Override sync window (if manualSync enabled)
argocd app sync web-app --skip-sync-window
Summary
Sync policies control how ArgoCD synchronizes applications:
- Automated sync - Automatic synchronization from Git
- Manual sync - Requires explicit user action
- Sync options - Control sync behavior
- Sync hooks - Run operations at specific points
- Sync windows - Restrict when syncs can occur
- Sync waves - Control resource sync order
Configure sync policies based on your environment needs:
- Development: Automated sync with self-heal
- Production: Manual sync with sync windows
- Complex deployments: Use hooks and sync waves