Argo CD Application CRDs Explained | GitOps Deployments Made Clear
This lecture establishes the foundational mechanics of Kubernetes Custom Resource Definitions (CRDs) and controllers before diving deep into the Argo CD Application CRD. By understanding how Kubernetes is extended, we can demystify how Argo CD acts as a declarative GitOps engine, bridging the gap between Git repositories and active cluster states.
1. The Foundation: Understanding Kubernetes Resource Definitions
When you bootstrap a new Kubernetes cluster, a wide array of built-in resource definitions are available by default. These definitions are schemas created by the Kubernetes community that dictate the exact structure, fields, and validation rules a resource must adhere to.
To view the default resource definitions in your cluster, run:
kubectl api-resources
The Relationship Between Resource Definitions and Resources
- Resource Definition: The blueprint or schema. It defines what fields are allowed, which are mandatory, and how the data must be structured (e.g., the schema for a
Deploymentor aService). - Resource: A user-created instance of a resource definition. It declares the desired state of a specific component in your cluster. If your YAML manifest violates the schema (e.g., incorrect indentation or missing mandatory fields), the Kubernetes API server rejects it.
2. Extending Kubernetes: Custom Resource Definitions (CRDs)
Kubernetes is highly modular and extensible. If the built-in resources (like Pods, Deployments, and ConfigMaps) do not satisfy your operational requirements, you can extend the Kubernetes API by defining your own Custom Resource Definitions (CRDs).
- CRD (Custom Resource Definition): A configuration file that tells the Kubernetes API server, "Here is a new type of resource called 'X', and here is the schema it must validate against."
- Custom Resource (CR): An instance created using that CRD. Once the CRD is registered, you can run
kubectl apply -fon a manifest of your customkind, and Kubernetes will store it inetcdjust like a native resource.
Note: CRDs can be written by you, a third-party vendor, or open-source projects (like Argo CD, Prometheus, or Istio) to introduce custom capabilities to the cluster.
3. The Brain of the Resource: Controllers and Reconciliation Loops
Simply storing a resource definition in etcd is not enough to make things happen. Many resources require a "brain" to act on the declared state. This brain is called a Controller.
A controller runs an infinite reconciliation loop (or control loop) that continuously executes three steps:
Do All Resources Have Controllers?
Not every Kubernetes resource requires a controller. Resources that represent static configuration or metadata generally do not have dedicated controllers, whereas resources that manage active workloads do.
The Operator Pattern
When you pair a Custom Resource Definition (CRD) with a Custom Controller, you get the Operator Pattern. The controller acts as an automated operator, watching your custom resources and executing complex operational tasks to match the desired state. Argo CD is built entirely on this pattern.
4. Argo CD as an Operator
When you install Argo CD into your cluster (e.g., via Helm or manifests), it registers several CRDs. You can inspect these CRDs by running:
kubectl get crd | grep argo
This command outputs the custom schemas registered by Argo CD:
applications.argoproj.io 2023-10-24T12:00:00Z
appprojects.argoproj.io 2023-10-24T12:00:00Z
applicationsets.argoproj.io 2023-10-24T12:00:00Z
Argo CD runs an Application Controller pod in its control plane. This controller continuously monitors resources of kind Application and reconciles the state of your target Kubernetes cluster with the manifests stored in your Git repository.
5. What is an Argo CD "Application"?
It is crucial to distinguish between your actual running application (e.g., a web portal, a database, or a microservice) and the Argo CD Application Resource.
Mental Hook: The Argo CD
Applicationresource is not your workload. It is the glue or bridge that connects a specific Git repository (source) to a specific Kubernetes cluster and namespace (destination).
Mapping in Microservices vs. Monoliths
- Microservices Best Practice: Each microservice should reside in its own Git repository. Consequently, one Argo CD Application maps to one independently deployable unit (one repository).
- Monoliths / Mono-repos: If multiple services or tiers reside in a single repository, you can define multiple Argo CD
Applicationresources, each pointing to a different subdirectory (path) within that same repository.
6. Anatomy of the Application CRD Manifest
Below is the declarative YAML manifest for an Argo CD Application resource. This resource tells Argo CD where to pull manifests from and where to deploy them.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps.git
targetRevision: HEAD
path: guestbook
destination:
server: https://kubernetes.default.svc
namespace: guestbook
Field Breakdown
apiVersion&kind: Specifies that this resource uses the custom Argo CD schema (argoproj.io/v1alpha1) and is of typeApplication.metadata.namespace: Must be set to the namespace where Argo CD is installed (typicallyargocd). The management resource itself must live in Argo CD's namespace, even if the target workload is deployed elsewhere.spec.project: Groups applications. By default, thedefaultproject is used.spec.source:repoURL: The Git repository containing your Kubernetes manifests.targetRevision: The branch, tag, or commit SHA to track.HEADpoints to the latest commit in the repository's default branch (e.g.,masterormain).path: The directory inside the repository where the Kubernetes manifests are located.
spec.destination:server: The target Kubernetes API server.https://kubernetes.default.svcrefers to the local cluster where Argo CD is running.namespace: The target namespace where the actual application workloads (Pods, Services, Deployments) will be deployed.
7. Hands-On Walkthrough: Deploying a Guestbook Application
Step 1: Verify Argo CD Control Plane Pods
Ensure your Argo CD installation is healthy and running:
kubectl get pods -n argocd
Step 2: Establish Port-Forwarding to the Argo CD UI
If you do not have an Ingress configured, port-forward the Argo CD API server to access the UI locally:
kubectl port-forward svc/argocd-server -n argocd 8080:443
Now, open your browser and navigate to http://localhost:8080 (or https://localhost:8080 depending on your TLS configuration).
Step 3: Create the Application Manifest
Create a file named sample-app.yaml on your local machine:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps.git
targetRevision: HEAD
path: guestbook
destination:
server: https://kubernetes.default.svc
namespace: guestbook
Step 4: Apply the Application Manifest
Apply the custom resource to your cluster:
kubectl apply -f sample-app.yaml
Verify that the application resource was successfully created:
kubectl get app -n argocd
Expected Output:
NAME SYNC STATUS HEALTH STATUS
guestbook OutOfSync Missing
8. Understanding Argo CD Statuses: Sync vs. Health
When you inspect your application in the Argo CD UI or CLI, you will notice two distinct status indicators: Sync Status and Health Status.
Crucial Distinction: An application can be Synced but Degraded. If you commit a broken manifest with an invalid container image to Git, Argo CD will successfully apply it (Sync Status:
Synced), but the Pods will fail to start (Health Status:Degraded).
9. Real-World Debugging: Resolving the Missing Namespace Error
After applying the sample-app.yaml, clicking Sync in the Argo CD UI results in a sync failure:
SharedResourceHistory: namespaces "guestbook" not found
Why Did This Fail?
Argo CD does not automatically create target namespaces by default unless explicitly configured to do so in the sync policy. The destination namespace guestbook specified in our manifest does not exist in the cluster.
The Fix
Manually create the namespace in your cluster:
kubectl create ns guestbook
Return to the Argo CD UI and click Sync again. The reconciliation loop will succeed, and you will see green status indicators across all resources.
Platform-Agnostic Manifests
Notice that the deployment and service manifests in the upstream Git repository do not have a hardcoded namespace field.
By omitting the namespace from your Git manifests and defining it inside the Argo CD Application spec instead, you make your manifests platform-agnostic. This allows you to deploy the exact same Git directory to dev, staging, or prod namespaces simply by changing the destination namespace in the respective Argo CD Application manifests.
10. Verifying the Deployment and Accessing the Application
Step 1: Verify the Workload Pods
Check if the guestbook application pods are running in the guestbook namespace:
kubectl get pods -n guestbook
Expected Output:
NAME READY STATUS RESTARTS AGE
guestbook-ui-5d9d979664-xxxxx 1/1 Running 0 2m
Step 2: Verify the Service
Check the service created for the guestbook application:
kubectl get svc -n guestbook
Expected Output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
guestbook-ui ClusterIP 10.96.120.45 <none> 80/TCP 2m
Step 3: Port-Forward to Access the Guestbook App
To view the running guestbook application in your browser, port-forward the service to local port 8081 (since port 8080 is occupied by the Argo CD UI):
kubectl port-forward svc/guestbook-ui -n guestbook 8081:80
Open your browser and navigate to http://localhost:8081 to view the running Guestbook UI.
Summary and Key Takeaways
- CRDs Extend Kubernetes: Custom Resource Definitions allow developers and tools to define custom APIs that behave exactly like native Kubernetes resources.
- Controllers Drive State: Controllers run continuous reconciliation loops that observe the current cluster state, compare it to the desired state, and act to resolve any drift.
- Argo CD is an Operator: It uses custom CRDs (like
Application) and an active controller to automate GitOps deployments. - The Application CRD is a Bridge: It maps a source Git repository and path to a destination Kubernetes cluster and namespace.
- One App Per Deployable Unit: In a microservices architecture, configure one Argo CD Application per microservice repository to maintain clean boundaries.
- Sync vs. Health: Sync status measures configuration alignment with Git; Health status measures workload runtime operational status.
- Namespace Lifecycle: Argo CD does not create target namespaces by default; they must exist beforehand or be managed via explicit sync policies.
- Platform-Agnostic Manifests: Keeping namespace declarations out of your raw application YAMLs allows you to reuse the same manifests across multiple environments.