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:
- Apply CRD manifests to the target cluster
- Wait for
Establishedcondition using the health check customization - Apply dependent Custom Resources once the API is available
- 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:
manifests/crds/application-crd.yaml– Core Application API schema with OpenAPI validationmanifests/crds/appproject-crd.yaml– AppProject RBAC and scope definitionsmanifests/crds/applicationset-crd.yaml– ApplicationSet generator specificationsgitops-engine/pkg/sync/sync_context.go– Dynamic client initialization for CRD watchinggitops-engine/pkg/sync/sync_tasks.go– Task ordering logic ensuring CRDs apply before dependentsresource_customizations/apiextensions.k8s.io/CustomResourceDefinition/– Health check expressions for CRD statushack/gen-crd-spec/main.go– Code generator extracting CRD definitions from Go structsui/src/app/applications/components/resources.ts– Frontend resource type mapping and health display
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 CRDstatus.conditionsto ensure definitions reachEstablishedstate - ApplicationSets can generate Applications containing CRDs, enabling automated provisioning of operator-backed services
- The code generator at
hack/gen-crd-spec/main.goensures 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →