Crossplane resources are just Kubernetes Custom Resources (CRs), and Argo CD is designed to manage Kubernetes CRs. So, managing Crossplane resources with Argo CD is as straightforward as managing any other Kubernetes application.
Let’s see it in action.
Imagine you have a Crossplane CompositeResourceDefinition (XRD) that defines a Composite resource called RDSInstance. You want to provision an RDSInstance that represents a PostgreSQL database.
First, your Crossplane installation needs to be configured to talk to your cloud provider (e.g., AWS). This involves creating a ProviderConfig resource.
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-credentials
key: credentials
Next, you define the CompositeResourceDefinition (XRD) for your RDSInstance. This tells Crossplane what a RDSInstance is.
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: rdsinstances.rds.example.com
spec:
group: rds.example.com
names:
kind: RDSInstance
plural: rdsinstances
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
instanceClass:
type: string
required:
- storageGB
- instanceClass
required:
- parameters
Now, you create a CompositeResource (XRs) of type RDSInstance. This is the actual request for a PostgreSQL database.
apiVersion: rds.example.com/v1alpha1
kind: RDSInstance
metadata:
name: my-postgres-db
spec:
parameters:
storageGB: 20
instanceClass: db.t3.micro
This RDSInstance object is a Kubernetes Custom Resource. Argo CD can track a Git repository containing these YAML manifests.
Here’s a typical Argo CD Application manifest that would point to a Git repository containing the Crossplane CRs (like ProviderConfig, XRD, and the RDSInstance XR):
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: crossplane-resources
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/your-gitops-repo.git
path: crossplane/rds-db
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: crossplane-system # Or wherever your Crossplane CRs should live
syncPolicy:
automated:
prune: true
selfHeal: true
When Argo CD syncs this application, it will apply the ProviderConfig, XRD, and RDSInstance manifests to your Kubernetes cluster. Crossplane, watching for these resources, will then act upon the RDSInstance request. It will consult its CompositeResource definitions and the underlying Managed Resources (like AWS RDS instances) to provision the actual cloud infrastructure.
The magic is that Argo CD doesn’t need to know anything about Crossplane’s internal workings. It just sees a RDSInstance as another CustomResourceDefinition and CustomResource to manage. When you update the RDSInstance YAML in Git (e.g., change storageGB to 30), Argo CD detects the change, syncs it to the cluster, and Crossplane reacts by updating the underlying AWS RDS instance.
The mental model is simple: Git is your source of truth. Argo CD enforces that truth on your cluster. Crossplane translates your abstract, declarative cloud resource definitions into concrete cloud infrastructure.
What most people don’t realize is how deeply integrated Crossplane’s Managed Resources become with the Kubernetes API. When Crossplane provisions an AWS RDS instance, it creates a RDSInstance Managed Resource (e.g., class.aws.upbound.io/RDSInstance.v1alpha1) in your cluster. This is a distinct Kubernetes object that mirrors the state of the actual cloud resource. Argo CD then tracks both your abstract rds.example.com/RDSInstance XR and the concrete class.aws.upbound.io/RDSInstance MR. This two-level abstraction is key to Crossplane’s power.
The next step is to explore how to use Crossplane’s Composition to define the actual cloud provider resources that fulfill your composite resources.