Introduction

Imagine needing to install numerous applications on a Kubernetes cluster. You might automate the process using the Argo CD CLI in a CI/CD pipeline or even resort to manual installation. However, this approach can quickly become overwhelming as you would need to somehow take care of each application installation on its own. Additionally, some applications may require a specific installation order to avoid dependency conflicts.

Fortunately, the Argo CD App of Apps pattern is the right way to deal with these problems. In this blog post, we’ll explore what this pattern is, the benefits it brings, and how to implement it.

What is the Argo CD App of Apps Pattern?

The App of Apps pattern is a design approach in Argo CD where a single “parent” application manages multiple “child” applications. Each child application represents a specific component or service in your Kubernetes cluster, such as infrastructure, monitoring tools, or business applications.

The following diagram illustrates the relationship between the parent and child applications in Argo CD:

Argo CD App of Apps pattern

Key Benefits:

  • Simplified management: Manage a single parent application instead of handling each child application separately.
  • GitOps driven: Use Git repositories as the single source of truth for your application manifests.
  • Scalability: Easily adapts to an increasing number of applications you want to roll out.
  • Reusability: You can use this approach to bootstrap multiple Kubernetes clusters with the same applications.
  • Dependency coordination: Define dependencies between applications to ensure proper deployment order.

Prerequisites

Before diving into this tutorial, ensure you are familiar with the basic features and configuration of Argo CD.

To follow along, you will need:

  • A Kubernetes cluster with Argo CD installed.
  • A Git repository to implement the App of Apps pattern. You can use platforms like GitLab to host and manage your repository.

How to Implement it?

As we have already learned, the App of Apps pattern works by defining a parent application that references multiple child applications. In a Git repository, the folder structure for this pattern would look something like this:

├── Chart.yaml
├── templates
│   ├── app-1.yaml
│   ├── app-2.yaml
│   ├── app-3.yaml
│   └── app-n.yaml
└── values.yaml

This is essentially a Helm Chart for the parent application, containing all its Argo CD child applications within the templates directory. Each child application has its own manifest file:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-1
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    path: app-1
    repoURL: https://gitlab.com/repo/for/app-1/manifests
    targetRevision: HEAD
  destination:
    namespace: app-1
    server: https://kubernetes.default.svc
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

The repoURL should point to the specific repository hosting the application’s configuration files or Helm Chart. For example, if your application’s manifests are stored in a GitLab repository, the repoURL might look like https://gitlab.com/your-organization/your-repository.

The path defines the location within the repository where the application’s configuration files or the Chart.yaml file of your Helm Chart resides. For example, if your application’s configuration files are located in a folder named app-1, you would set the path to app-1. Alternatively, you can use the chart property to specify a Helm Chart from a private or public Helm Chart registry.

To make sure that all child apps and their corresponding resources are properly deleted when the parent app gets deleted, add the following finalizer to your child app definitions.

Note: Be cautious when using this finalizer, as it can lead to accidental cascading deletions of all child applications and their resources if the parent application is deleted unintentionally.

metadata:
  finalizers:
  - resources-finalizer.argocd.argoproj.io

To control the order of child app creation, you might want to set sync waves:

metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "2"

This controls the execution order of the apps to ensure that dependencies are respected. For example, you can assign lower sync wave numbers to applications that need to be deployed first, and higher numbers to those that depend on them. By default, all applications are assigned a sync wave of 0 if no annotation is specified.

Finally, you need to create and sync the parent application. This can be achieved using the Argo CD CLI, and this process can also be automated within a CI/CD pipeline:

argocd app create apps \
--dest-namespace argocd \
--dest-server https://kubernetes.default.svc \
--repo https://gitlab.com/repo/for/parent/app/helm/chart.git \
--revision main
--path apps
--sync-policy auto
--auto-prune
--upsert

This will also create the child applications, which you can now monitor directly in the Argo CD dashboard. The dashboard provides a visual representation of the parent-child relationships, making it easier to track the deployment status and troubleshoot any issues.

Conclusion

The Argo CD App of Apps pattern simplifies Kubernetes application rollouts by using a parent-child hierarchy. This approach is particularly useful for bootstrapping Kubernetes clusters with a predefined set of applications.

For further inspiration and practical examples, check out the official argocd-example-apps repository. It serves as an excellent starting point for designing your own App of Apps setup.

Have fun trying it out! 😃