Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

Application

  • Application CRD is an ArgoCD construct that contains a logical collection of kubernetes resources.
  • the Application is the smallest unit of work in ArgoCD and is where Argo interfaces with kubernetes in order to deploy objects
  • the most significant parts of the Application resource are the spec.source and spec.destination
    spec:
        destination:
          namespace: snake
          server: https://kubernetes.default.svc
        source:
          helm:
            valueFiles:
            - values.yaml
          path: helm-charts/snake
          repoURL: https://github.com/rnemeth90/homelab.git
          targetRevision: HEAD
    
  • ArgoCD also supports a sources (plural) field where you can specify multiple sources

Sync Policy

spec:
  syncPolicy:
    syncOptions:
    - Validate=true
    - CreateNamespace=true
    - Replace=false ##... etc
    - ApplyOutOfSyncOnly=true # only update resources in the app that have changed
    automated:
      prune: true
      selfHeal: true
      allowEmpty: false
  • Sync policy options can be applied to individual resources, not just the entire Application
    • You just need to add an annotation to the resource with the sync policy

      metadata:
        annotations:
          argocd.argoproj.io/sync-options: Validate=false
      
      
    • the options available via the sync policy annotations are:

      • Validate
      • PruneLast
      • Replace
      • ServerSideApply

Sync Order and Hooks

  • https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/

  • ArgoCD has the ability to setup different sync phases by allowing the user to utilize hooks.

  • Imagine you have a directory full of kubernetes manifest files. If you run kubectl apply, k8s will try to create everything at once. This may be bad. Maybe you have a deployment that is dependent on a database or cache running in a statefulset. Maybe the deployment has health probes, and those probes reach out to the statefulset at some point in their execution path. What happens? The application pods will continually restart until the until statefulset comes up.

  • Sync Hooks allow you to create an ArgoCD deployment playbook. You can define how your resources are created, updated, and deleted.

  • Stages of a Sync Hook

    1. Presync - Database migrations, backups, etc. Anything you want to run BEFORE the main sync
    2. Sync - The main sync process. ArgoCD waits here until resources are healthy for a configurable amount of time.
    3. PostSync - Runs after the sync succeeds and all resources are healthy
    4. SyncFail - Runs only if a syncoperation has failed. Normally used for alerting or garbage collection.
    5. PostDelete - Used for any cleanup tasks after all other resources have been deleted
  • every stage of a sync hook relies on the success of the previous stage (with the exception of the SyncFail phase)

  • Sync hooks are defined within your existing kubernetes manifests. You just add a single annotation:

      metadata:
        annotations:
          argocd.argoproj.io/hook: PreSync
    
  • You also need to define a cleanup policy for the sync hook:

      metadata:
        annotations:
          argocd.argoproj.io/hook: PreSync
          argocd.argoproj.io/hook-delete-policy: HookSucceeded
    
    • There are several policies you can use. HookFailed will only delete the resources if the hook fails.

Sync Waves

  • Sync waves are used to define an order of operations to your kubernetes deployed.
  • Sync waves are defined in the annotations section of your manifests.
  • Sync waves work best when proper health checks are created for the application
  • Lower number go first
  • “0” is the default value
  • You can even combine sync hooks and waves. This example would run in the 3rd wave of the PreSync hook:
      metadata:
        annotations:
          argocd.argoproj.io/hook: PreSync
          argocd.argoproj.io/sync-wave: 3
    

Example Application (the important bits are source and destination)

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  creationTimestamp: "2026-08-17T20:21:14Z"
  finalizers:
  - resources-finalizer.argocd.argoproj.io
  generation: 21183
  name: snake
  namespace: argocd
  ownerReferences:
  - apiVersion: argoproj.io/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: ApplicationSet
    name: helm-charts
    uid: fb81928e-bce5-4efc-be70-380e17069785
  resourceVersion: "328662005"
  uid: 1eb74018-b72e-4492-95b5-e4f18e921a06
spec:
  destination:
    namespace: snake
    server: https://kubernetes.default.svc
  ignoreDifferences:
  - group: apps
    jqPathExpressions:
    - .spec.template.spec.hostUsers
    kind: Deployment
    name: headlamp
    namespace: headlamp
  project: default
  source:
    helm:
      valueFiles:
      - values.yaml
    path: helm-charts/snake
    repoURL: https://github.com/rnemeth90/homelab.git
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    retry:
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m
      limit: 5
    syncOptions:
    - CreateNamespace=true

Application Health

  • ArgoCD continuously monitors Application’s. An Application can be in one of the following health states:

  • Health statuses:

    • Healthy - the resource is healthy
    • Progressing - the resource is attempting to become healthy by syncing
    • Degraded - the resource has failed or otherwise become unhealthy
    • Missing - the resource is not installed in the cluster
    • Suspended - the resource is suspended or ‘paused’
    • Unknown - WTF?
  • You can also create custom health checks by editing the argocd-cm config map. You can use Lua to specify the custom health check:


---
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
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

Behavior of ArgCD Applications when Source is a helm chart

  • When argo deploys a helm chart, the helm chart itself is not actually deployed to the cluster. Meaning, you cannot connect to the cluster and expect to see the chart listed in the output of helm ls. Argo prefers to manage the YAML of all applications. So before deploying the helm chart, it runs helm template against the chart to generate the Kubernetes manifests, and then deploys those manifests.

Deleting Applications

  • When you delete an Application in Argo, you will find that the resources running in Kubernetes are not deleted. Argo takes the stance (like PersistentVolumes) that certain resources should be cleaned up manually to prevent data loss. If you choose, you can tell Argo to automatically delete the resources when the associated Application is deleted by adding a finalizers field to the Application:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  creationTimestamp: "2026-08-17T20:21:14Z"
  finalizers:
  - resources-finalizer.argocd.argoproj.io
  generation: 21183
  name: snake
  namespace: argocd
  ownerReferences:
  - apiVersion: argoproj.io/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: ApplicationSet
    name: helm-charts
    uid: fb81928e-bce5-4efc-be70-380e17069785
  resourceVersion: "328662005"
  uid: 1eb74018-b72e-4492-95b5-e4f18e921a06
spec:
  destination:
    namespace: snake
    server: https://kubernetes.default.svc
  source:
    helm:
      valueFiles:
      - values.yaml
    path: helm-charts/snake
    repoURL: https://github.com/rnemeth90/homelab.git
    targetRevision: HEAD
  finalizers:
  - resources-finalizer.argocd.argoproj.io/background #OR Foreground (see the next line below)
  - resources-finalizer.argocd.argoproj.io/foreground

App Project

  • With an ArgoCD Project, administrators can:
    • Manage RBAC on a per-project basis
    • restrict the sources of content (github, helm, etc.)
    • Restrict where ArgoCD apps can be deployed to
    • Restrict which kubernetes objects can be deployed
  • ArgoCD includes a project named default, which allows deployment of any resource to any cluster by anyone. You cannot delete the default project, but you can lock it down.
  • An ArgoCD Application can only ever belong to one project