Argo CD Hooks: The Basics and a Quick Tutorial

What Are Argo CD Resource Hooks?

Argo CD resource hooks control the application lifecycle within Kubernetes environments. They enable users to execute custom logic at predefined points during the application’s lifecycle, such as before the application starts or after it finishes. This flexibility is important for automatically executing tasks, such as schema migration, validation checks, and notifications, when certain conditions are met.

These hooks are implemented as Kubernetes resources themselves, following annotations to determine their execution timing. By using annotations like argocd.argoproj.io/hook, developers can specify the type of hook, such as pre-sync, post-sync, or sync-failure, dictating when the resource should be executed.

Argo CD Resource Hooks Use Cases

Argo CD resource hooks offer flexibility by allowing users to execute custom scripts at various stages of the application’s lifecycle. This can be particularly useful in scenarios that require going beyond the default behavior provided by Kubernetes:

  1. Database schema migration before deployment (PreSync hook): Performing a database schema migration before deploying a new version of an application. By using a PreSync hook, developers can ensure that the database is in the correct state before any new application code is deployed, reducing the risk of incompatibilities and errors.
  2. Complex deployment strategies (Sync hook): For deployments that require more sophistication than Kubernetes’ standard rolling update strategy, Sync hooks can be used to orchestrate complex deployment processes. This might involve coordinating multiple services, managing dependencies, or implementing a blue-green deployment strategy.
  3. Post-deployment checks (PostSync hook): After an application is deployed, it’s often necessary to run integration tests or health checks to verify that everything is working as expected. A PostSync hook allows these checks to be automated, ensuring that issues are caught early in the process.
  4. Handling deployment failures (SyncFail hook): In the event of a deployment failure, it’s critical to perform clean-up or run finalizer logic to maintain system integrity. SyncFail hooks can be used to automate these actions, preventing incomplete or failed deployments from leaving the system in an inconsistent state.
  5. Post-deletion clean-up (PostDelete hook): When an application is deleted, there may be resources or data that need to be cleaned up. A PostDelete hook can be used to automate this clean-up process. This is particularly useful in environments where resources are not automatically garbage collected after the application is deleted.

Using Argo CD Resource Hooks

Technically, hooks in Argo CD are simply Kubernetes resources annotated with argocd.argoproj.io/hook, specifying when and how these resources should be executed during the application’s lifecycle.

Defining Hooks in Kubernetes Manifests

Hooks are defined within Kubernetes manifests and are stored in the source repository along with the other Argo CD application resources. Each hook is annotated to indicate its role, such as PreSync, Sync, or PostSync. For example, a PreSync hook could be a Kubernetes Job that runs a database migration script before the application is deployed:

apiVersion: batch/v1
kind: Job
metadata:
  generateName: schema-migrate-
  annotations:
    argocd.argoproj.io/hook: PreSync

This job will execute before the actual application manifests are applied, ensuring that the database is ready for the new application code.

Types of Hooks and Their Execution

Argo CD supports various types of hooks, each serving a different purpose in the deployment process:

  • PreSync: Executes before the application manifests are applied.
  • Sync: Executes simultaneously with the application manifests.
  • PostSync: Executes after the application manifests have been applied and the application is in a healthy state.
  • SyncFail: Executes if the sync operation fails, allowing for cleanup or rollback operations.
  • PostDelete: Executes after all application resources are deleted, useful for cleanup tasks after application removal.

Managing Hook Lifecycles

Argo CD also provides mechanisms to manage the lifecycle of hooks themselves, such as automatically deleting them once they have been executed. This is done using the argocd.argoproj.io/hook-delete-policy annotation:

apiVersion: batch/v1
kind: Job
metadata:
  generateName: integration-test-
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded

In this example, the Job defined by the PostSync hook will be automatically deleted after it has successfully completed, keeping the Kubernetes cluster clean and avoiding resource leakage.

Dan Garfield
VP of Open Source, Octopus Deploy
Dan is a seasoned leader in the tech industry with a strong focus on open source initiatives. Currently serving as VP of Open Source at Octopus Deploy, contributing as an Argo maintainer, co-creator of Open GitOps, and leveraging extensive experience as a co-founder of Codefresh, now part of Octopus Deploy.

TIPS FROM THE EXPERT

In my experience, here are tips that can help you better utilize Argo CD resource hooks:

  1. Implement hook ordering with sync waves: Use argocd.argoproj.io/sync-wave to manage the execution order of both hooks and regular application resources. Sync waves allow you to control complex deployment flows, ensuring that critical hooks (like PreSync database migrations) run before dependent application resources.
  2. Use custom health checks for faster feedback loops: Define custom health checks using the health.lua script in your application manifests. By specifying conditions that are more granular than the default health checks, you can detect application readiness issues earlier (e.g., checking specific API endpoints or database status).
  3. Version hooks independently from the main application: Store hooks in a separate Helm chart or directory from the main application manifests. This allows you to version and update hook logic independently, making it easier to iterate on complex tasks like migrations or custom cleanup without impacting the main application deployment process.
  4. Control resource cleanup with lifecycle hooks: Use PostDelete hooks not only for cleanup but also to archive application state or logs before deleting resources. This approach ensures that you capture critical information before cleaning up, aiding in audits and troubleshooting.
  5. Use hooks to enforce compliance: Implement PostSync hooks that run compliance checks (such as security scans or configuration audits) after deployment. Automatically enforcing these checks helps maintain standards across all environments and reduces manual auditing efforts.

Tutorial: Using A Hook To Send A Notification

Argo CD allows you to run custom logic at various stages of an application’s lifecycle using resource hooks. In this tutorial, we’ll walk through an example where a PostSync hook sends a notification to a Slack channel after a successful deployment. Additionally, a SyncFail hook sends an alert in case of a failed deployment. 

This example is based on code shared in the Argo CD documentation.

1. Sending a Slack Message on Successful Sync

The following Kubernetes manifest defines a Job that sends a message to a Slack channel when an Argo CD sync completes successfully. The Job is annotated as a PostSync hook, meaning it runs after the application has been deployed and is in a healthy state.

apiVersion: batch/v1
kind: Job
metadata:
  generateName: app-slack-notification-
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
      - name: slack-notification
        image: curlimages/curl
        command:
          - "curl"
          - "-X"
          - "POST"
          - "--data-urlencode"
          - "payload={\"channel\": \"#somechannel\", \"username\": \"hello\", \"text\": \"App Sync succeeded\", \"icon_emoji\": \":ghost:\"}"
          - "https://hooks.slack.com/services/..."
      restartPolicy: Never
  backoffLimit: 2

A few important points in the code:

Annotations:

  • argocd.argoproj.io/hook: PostSync: Marks this Job as a PostSync hook, meaning it will run after the application is successfully deployed.
  • argocd.argoproj.io/hook-delete-policy: HookSucceeded: Automatically deletes the Job after it runs successfully, preventing resource clutter.

Containers:

  • The Job uses the curlimages/curl container to make an HTTP POST request to the Slack API.
  • The payload specifies the Slack channel (#somechannel), username (hello), message text (App Sync succeeded), and an icon emoji (:ghost:) that will be used in the notification.

Slack Webhook URL

Replace the placeholder https://hooks.slack.com/services/... with your actual Slack Incoming Webhook URL to ensure the message gets delivered.

Backoff Policy:

backoffLimit: 2: Limits the number of retry attempts for the Job if it fails.

2. Sending a Slack Message on Sync Failure

In case a deployment fails, it’s crucial to notify the relevant team members. The following Job defines a SyncFail hook that triggers a Slack message when an Argo CD sync fails.

apiVersion: batch/v1
kind: Job
metadata:
  generateName: app-slack-notification-fail-
  annotations:
    argocd.argoproj.io/hook: SyncFail
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
      - name: slack-notification
        image: curlimages/curl
        command: 
          - "curl"
          - "-X"
          - "POST"
          - "--data-urlencode"
          - "payload={\"channel\": \"#somechannel\", \"username\": \"hello\", \"text\": \"App Sync failed\", \"icon_emoji\": \":ghost:\"}"
          - "https://hooks.slack.com/services/..."
      restartPolicy: Never
  backoffLimit: 2

A few important points in the code:

Annotations

argocd.argoproj.io/hook: SyncFail: This annotation triggers the Job if the sync operation fails, allowing for immediate notification of deployment issues.

Payload:

The message text is modified to notify that the application sync failed (“App Sync failed“), but the rest of the setup is similar to the PostSync hook.

Automatic Cleanup:

Similar to the PostSync hook, this Job is also automatically deleted after it completes successfully using the HookSucceeded policy.

Key Takeaways

  • PostSync Hook: Triggers a Job to send a Slack notification when the application is successfully deployed.
  • SyncFail Hook: Sends an alert to the Slack channel if the deployment fails.
  • Hook Lifecycles: The argocd.argoproj.io/hook-delete-policy ensures that the Jobs are deleted after they succeed, preventing unnecessary clutter in the Kubernetes cluster.

By using Argo CD resource hooks, you can easily integrate notifications into your deployment pipeline, ensuring that your team stays informed about deployment success or failure in real time.

Codefresh: A Modern, Argo-Based CI/CD Platform

The Codefresh platform, powered by Argo, combines the best of the open-source with an enterprise-grade runtime allowing you to fully tap the power of Argo Workflows, Events, CD, and Rollouts. It provides teams with a unified GitOps experience to build, test, deploy, and scale their applications.

You can use Codefresh for your platform engineering initiative either as a developer portal or as the machinery that takes care of everything that happens in the developer portal. Your choice depends on how far your organization has adopted Kubernetes and micro-services

Codefresh is a next generation CI/CD platform designed for cloud-native applications, offering dynamic builds, progressive delivery, and much more.