Argo CD sync hooks let you run arbitrary commands before or after a sync operation, giving you fine-grained control over your deployment lifecycle.
Let’s see this in action. Imagine we have a simple application deployment that needs to perform a database migration before the new application version is rolled out, and then clean up old resources afterward.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-org/my-app-source.git
targetRevision: HEAD
path: kustomize/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: my-app-prod
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
hooks:
- automated:
prune: true
name: pre-sync-migration
resourceHook:
container:
image: my-database-migration-tool:latest
command: ["/app/run-migrations.sh"]
- automated:
prune: true
name: post-sync-cleanup
resourceHook:
container:
image: my-cleanup-tool:latest
command: ["/app/cleanup-old-resources.sh"]
In this Application manifest, we’ve defined two hooks: pre-sync-migration and post-sync-cleanup.
The pre-sync-migration hook uses a custom container image my-database-migration-tool:latest and executes the script /app/run-migrations.sh. This script is responsible for applying any necessary database schema changes before Argo CD proceeds with deploying the new application version.
The post-sync-cleanup hook is similar, but it runs after the sync is complete. It uses my-cleanup-tool:latest to execute /app/cleanup-old-resources.sh, which might remove old Kubernetes resources that are no longer needed, or perform other post-deployment tasks.
How it works internally:
When Argo CD initiates a sync for my-app, it first checks for any pre-sync hooks. If found, it spins up a temporary pod defined by the resourceHook specification. This pod runs the specified command. Argo CD waits for this pod to complete successfully. If the hook pod fails, the sync operation is aborted. Once the pre-sync hook succeeds, Argo CD proceeds to apply the manifests from your Git repository. After the manifests are applied and the sync is marked as successful, Argo CD then checks for post-sync hooks. These are executed in the same manner: a temporary pod is created, and Argo CD waits for its successful completion.
The resourceHook type is the most common and flexible. It allows you to define a standard Kubernetes Pod object directly within the hook. Argo CD will create and manage this pod for you. You can specify container, volumes, env, and other pod-level configurations. The command or args within the container definition are what actually get executed.
You can also use exec hooks, which are simpler and execute commands directly within the Argo CD controller pod. This is less common for application-specific tasks but can be useful for interacting with the Argo CD API or performing cluster-level operations. However, resourceHook is generally preferred for its isolation and ability to use custom tooling.
The automated: { prune: true } setting on the hook means that the hook resource (the temporary pod) will be cleaned up by Argo CD after it has completed its execution, regardless of success or failure. This prevents orphaned pods from accumulating in your cluster.
The syncOptions like CreateNamespace=true are applied after any pre-sync hooks have successfully completed, and before the main application manifests are applied. This ensures that if your pre-sync hook requires a specific namespace to exist, you can configure it to be created.
One aspect that often trips people up is how Argo CD determines success or failure. For resourceHooks, Argo CD considers the hook successful if the pod exits with a status code of 0. Any non-zero exit code will cause the sync to fail. For exec hooks, the command’s exit code directly determines success. This is why your hook scripts must be robust and correctly signal completion.
The next logical step after mastering sync hooks is understanding how to manage complex inter-application dependencies using Argo CD’s ApplicationSet feature.