Argo CD Custom Resource Definitions (CRDs): A Complete Technical Guide

Argo CD uses five primary Custom Resource Definitions—applications, appprojects, applicationsets, argocdconfigs, and argocdnotifications—to declaratively manage GitOps workflows through Kubernetes-native APIs.

Argo CD custom resource definitions (CRDs) extend the Kubernetes control plane to support GitOps operations, allowing you to define applications, projects, and configuration generators as native resources. The argoproj/argo-cd repository ships these CRDs as YAML manifests that install into your cluster, enabling the application controller to watch and reconcile these objects alongside standard Kubernetes workloads. Understanding how these CRDs function internally—from the API definitions in manifests/crds/ to the synchronization logic in the gitops-engine—is essential for troubleshooting sync failures and designing complex deployment pipelines.

Core Argo CD CRDs and Their Purpose

Argo CD exposes its domain-specific objects through the Kubernetes API server using CRDs defined in the manifests/crds/ directory. These definitions map Go structs to OpenAPI v3 schemas, enabling validation and storage by etcd.

Application CRD (applications.argoproj.io)

The Application CRD represents the fundamental GitOps unit. Defined in manifests/crds/application-crd.yaml, this resource specifies source repositories, target clusters, deployment paths, and sync policies. The application controller watches these resources to trigger deployments when Git state diverges from cluster state.

AppProject CRD (appprojects.argoproj.io)

AppProjects group applications and enforce boundaries for RBAC, allowed source repositories, destination clusters, and sync windows. The definition resides in manifests/crds/appproject-crd.yaml, implementing multi-tenancy controls that restrict where applications can deploy and what resources they can manage.

ApplicationSet CRD (applicationsets.argoproj.io)

The ApplicationSet controller uses the CRD defined in manifests/crds/applicationset-crd.yaml to generate multiple Application objects from templates. It supports generators for Git directories, cluster lists, SCM providers, and pull requests, enabling automated Application provisioning for microservices architectures.

Configuration and Notification CRDs

ArgoCDConfigs (argocdconfigs.argoproj.io) store server configuration including Dex, OIDC, and RBAC policies in manifests/crds/argocdconfig-crd.yaml. ArgoCDNotifications (argocdnotifications.argoproj.io) manage notification subscriptions and triggers, defined in resource_customizations/notifications.argoproj.io/NotificationCRD.yaml.

How Argo CD Watches and Syncs CRDs

The Argo CD control plane uses dynamic clients and informers to monitor CRD state changes and orchestrate synchronization order.

Dynamic Client Registration

The server component creates dynamic Kubernetes clients for each CRD using extensionsclientset.ApiextensionsV1().CustomResourceDefinitions(). In gitops-engine/pkg/sync/sync_context.go around line 1290, the controller fetches CRD definitions:

crd, err := sc.extensionsclientset.ApiextensionsV1().
        CustomResourceDefinitions().
        Get(ctx, name, metav1.GetOptions{})

These informers feed resource events into the application controller's reconciliation loop.

Task Ordering for CRD Dependencies

When an Application includes CRDs in its manifest set, Argo CD must apply them before dependent custom resources. The task ordering logic in gitops-engine/pkg/sync/sync_tasks.go (around line 41) classifies resources by kind, ensuring CRDs precede their instances in the synchronization wave. This prevents "resource not found" errors when applying Custom Resources whose definitions haven't reached the Established state.

Application Controller Reconciliation

The application controller (controller/sync.go) treats Application resources as reconciliation targets. It pulls the declared Git source, renders manifests (including nested CRDs), and applies them to destination clusters using server-side apply or strategic merge patching depending on the resource type.

CRD Lifecycle Management in Argo CD

Managing CRDs through Argo CD requires understanding the complete lifecycle from installation to deletion.

Installation and Versioning

Argo CD installs CRDs through Helm charts or plain manifests in manifests/install*.yaml. Once installed, the controller monitors CRD health via status.conditions such as Established and NamesAccepted. Health check definitions reside in resource_customizations/apiextensions.k8s.io/CustomResourceDefinition/, providing custom health assessment logic for the CRD resource type itself.

Synchronization Ordering

When syncing Applications containing CRDs, Argo CD performs the following sequence:

  1. Apply CRD manifests to the target cluster
  2. Wait for Established condition using the health check customization
  3. Apply dependent Custom Resources once the API is available
  4. Verify resource health before marking sync successful

This ordering prevents race conditions where operators or controllers attempt to watch resources before their definitions exist.

Deletion and Cascade Behavior

Deleting an Application that owns CRDs triggers cascade deletion only when metadata.ownerReferences links the CRD to the Application. The controller respects Kubernetes propagationPolicy settings to avoid orphaned resources. Set prune: false in sync policies to preserve CRDs when deleting parent Applications.

Practical Examples

Deploying Applications with Embedded CRDs

When packaging operators with Argo CD, include the CRD in your Application source. The controller detects the CRD kind and applies it before operator deployments:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx-operator
spec:
  project: default
  source:
    repoURL: https://github.com/example/nginx-operator
    path: helm
    helm:
      valueFiles:
      - values.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: nginx-operator
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

The Helm chart's templates/crd.yaml deploys first, waits for Established status, then proceeds with the operator Deployment and Custom Resource instances.

Generating CRD-based Applications with ApplicationSet

For multi-tenant environments where each tenant requires its own CRD definition, use ApplicationSet generators:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: multi-tenant
spec:
  generators:
    - git:
        repoURL: https://github.com/example/multi-tenant-repo
        directories:
          - path: tenant-*
  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/multi-tenant-repo
        targetRevision: HEAD
        path: '{{path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{path.basename}}'

Each generated Application may contain tenant-specific CRDs. Argo CD ensures these definitions reconcile before creating tenant Custom Resources.

Monitoring CRD Health in the UI

The Argo CD UI renders CRD status using custom health checks defined in ui/src/app/applications/components/resources.ts (around line 44). The mapping logic interprets status.conditions to display "Established," "Progressing," or "Degraded" badges, providing visual feedback on CRD readiness before dependent resources deploy.

Key Source Files and Implementation Details

Understanding these specific files in the argoproj/argo-cd repository clarifies how CRDs integrate with the GitOps engine:

Summary

  • Argo CD CRDs (applications, appprojects, applicationsets, argocdconfigs, argocdnotifications) extend Kubernetes to support GitOps-native workflows
  • The gitops-engine orders synchronization tasks to apply CRDs before dependent resources, preventing race conditions
  • Health checks in resource_customizations/ monitor CRD status.conditions to ensure definitions reach Established state
  • ApplicationSets can generate Applications containing CRDs, enabling automated provisioning of operator-backed services
  • The code generator at hack/gen-crd-spec/main.go ensures CRD schemas remain synchronized with Go struct definitions

Frequently Asked Questions

What CRDs does Argo CD install by default?

Argo CD installs four core CRDs: applications.argoproj.io for GitOps application definitions, appprojects.argoproj.io for project scoping and RBAC, applicationsets.argoproj.io for application templating, and argocdconfigs.argoproj.io for server configuration. An optional fifth CRD, argocdnotifications.argoproj.io, supports notification configuration. These reside in manifests/crds/ and establish the API group argoproj.io.

How does Argo CD handle CRD dependencies during synchronization?

Argo CD uses task ordering logic in gitops-engine/pkg/sync/sync_tasks.go to classify CRDs as prerequisite resources. The sync context applies CRD manifests first, waits for the Established condition using health checks defined in resource_customizations/apiextensions.k8s.io/CustomResourceDefinition/, then proceeds with Custom Resource instances. This ordering prevents "resource not found" errors during automated syncs.

Can Argo CD manage CRDs for other operators?

Yes. Argo CD can deploy and manage CRDs defined in external repositories or Helm charts. When an Application references a manifest containing a CRD, the controller treats it like any other resource but applies special ordering logic. You can disable automated pruning for CRDs to prevent accidental deletion of operator definitions while allowing Application updates.

How are Argo CD's own CRDs generated from source code?

The repository includes hack/gen-crd-spec/main.go, a code generation utility that extracts OpenAPI v3 schemas from Go struct tags and comments. This ensures the YAML definitions in manifests/crds/ remain synchronized with the underlying Go types used by the application controller, reducing schema drift between API versions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →