DEV Community

Cover image for Argo CD "App of Apps" on EKS

Argo CD "App of Apps" on EKS

In our previous article we saw how to set up an Istio service mesh and monitor it using Kiali. Now we'll configure and use Argo CD on our EKS cluster with the "App of Apps" GitOps pattern, and automatically deploy sample frontend (nginx) and backend (http-echo) applications.

The "App of Apps" pattern is essential when you're bootstrapping clusters with many components, whether they're add-ons (like Istio and Kiali) or application workloads.

Prerequisites

  1. You have a Kubernetes cluster running
  2. kubectl is configured to talk to your Kubernetes cluster
  3. You have a basic understanding of GitOps
  4. You have a Git repository. I'll be using GitHub for this demo
  5. You have a basic understanding of Helm

Step 1 - Installing Argo CD

Before installing Argo CD in our cluster, we'll first create an "argocd" namespace for better isolation and management of Argo CD components (pods, deployments, services, etc).

kubectl create namespace argocd
Enter fullscreen mode Exit fullscreen mode

There are primarily two options for installing Argo CD in a Kubernetes cluster: kubectl or helm.
For our demo, we'll install Argo CD using helm.

We'll start by adding the Argo CD Helm chart repository:

helm repo add argo https://argoproj.github.io/argo-helm
Enter fullscreen mode Exit fullscreen mode

Then we update the Helm repository list to ensure we have the latest chart information:

helm repo update
Enter fullscreen mode Exit fullscreen mode

And finally, we install the Argo CD Helm chart with the command below. This will install all necessary Argo CD components into the argocd namespace (that we just created). You can customize the installation by using a values.yaml file with the --values flag.

helm install argocd argo/argo-cd --namespace argocd
Enter fullscreen mode Exit fullscreen mode

We can verify the installation with the following command, making sure that all pods are running:

kubectl -n argocd get pods
Enter fullscreen mode Exit fullscreen mode

With Argo CD now installed, the simplest way to access the UI is via port forwarding (depending on your EKS cluster's network).
So, we'll port-forward the argocd-server service, making it available on http://localhost:8080:

kubectl -n argocd port-forward svc/argocd-server 8080:443
Enter fullscreen mode Exit fullscreen mode

We should now retrieve the initial admin password (the default username is admin). The initial password is auto-generated and stored as a Kubernetes secret:

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
Enter fullscreen mode Exit fullscreen mode

You can access the Argo CD UI on http://localhost:8080

Argo CD UI

Step 2 - Prepare Git Repository

Your GitOps repository should look like this:

gitops-eks/
├── apps/
│   ├── frontend-app.yaml
│   └── backend-app.yaml
│
├── app-of-apps/
│   └── parent-app.yaml
│
├── frontend/
│   ├── namespace.yaml
│   ├── deployment.yaml
│   └── service.yaml
│
└── backend/
    ├── namespace.yaml
    ├── deployment.yaml
    └── service.yaml
Enter fullscreen mode Exit fullscreen mode
  • app-of-apps/ -> App of Apps
  • apps/ -> Argo CD applications
  • frontend/ -> Kubernetes manifests for frontend application
  • backend/ -> Kubernetes manifests for backend application

Content of Manifests

app-of-apps/parent-app.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: platform-apps
  namespace: argocd
spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_ORG/gitops-eks.git
    targetRevision: HEAD
    path: apps

  destination:
    server: https://kubernetes.default.svc
    namespace: argocd

  syncPolicy:
    automated:
      prune: true
      selfHeal: true
Enter fullscreen mode Exit fullscreen mode
  • This parent Argo CD application (App of Apps) reads all manifests in the apps directory (as indicated by the line path: apps)
  • It then creates the child Argo CD applications (frontend and backend in this case)
  • Then it automatically syncs drift (as indicated by the syncPolicy)

apps/frontend-app.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: frontend
  namespace: argocd
spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_ORG/gitops-eks.git
    targetRevision: HEAD
    path: frontend

  destination:
    server: https://kubernetes.default.svc
    namespace: frontend

  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
Enter fullscreen mode Exit fullscreen mode
  • This frontend Argo CD application deploys the frontend application using the Kubernetes manifests in the frontend directory (as indicated by the line path: frontend)
  • It also automatically creates this application's namespace if it doesn't exist already

apps/backend-app.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: backend
  namespace: argocd
spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_ORG/gitops-eks.git
    targetRevision: HEAD
    path: backend

  destination:
    server: https://kubernetes.default.svc
    namespace: frontend

  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
Enter fullscreen mode Exit fullscreen mode
  • This frontend Argo CD application deploys the backend application using the Kubernetes manifests in the backend directory (as indicated by the line path: backend)
  • It also automatically creates this application's namespace if it doesn't exist already

frontend/namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: frontend
Enter fullscreen mode Exit fullscreen mode
  • This manifest creates the namespace for the frontend application

frontend/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
Enter fullscreen mode Exit fullscreen mode
  • This manifest creates an Nginx deployment for the frontend application that listens on port 80

frontend/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  type: ClusterIP
  selector:
    app: frontend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
Enter fullscreen mode Exit fullscreen mode
  • This manifest creates a service for the frontend application's deployment that listens on port 80

backend/namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: backend
Enter fullscreen mode Exit fullscreen mode
  • This manifest creates the namespace for the backend application

backend/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: api
        image: hashicorp/http-echo
        args:
        - "-text=Hello from backend"
        - "-listen=:5678"
        ports:
        - containerPort: 5678
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
Enter fullscreen mode Exit fullscreen mode
  • This manifest creates an http-echo deployment for the backend application that listens on port 5678

backend/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  type: ClusterIP
  selector:
    app: backend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5678
Enter fullscreen mode Exit fullscreen mode
  • This manifest creates a service for the backend application's deployment that listens on port 80 and redirects traffic to the deployment's pods on port 5678

Step 3 - Bootstrap the App of Apps

With the Git repository configured and the manifest files pushed to it, we can now apply the parent YAML once:

kubectl apply -f app-of-apps/parent-app.yaml
Enter fullscreen mode Exit fullscreen mode

Argo CD will then:

  1. Create all Argo CD applications (App of Apps, frontend, and backend)
  2. Create the Kubernetes namespaces for the frontend and backend applications
  3. Create the deployments for the frontend and backend applications
  4. Create the services for the frontend and backend applications

You should see a similar output after executing the previous command:

Argo CD applications created

From your terminal, enter the following commands to verify that the applications were successfully deployed:

kubectl -n argocd get applications
kubectl -n frontend get service,deployment
kubeclt -n backend get service,deployment
Enter fullscreen mode Exit fullscreen mode

You should have outputs similar to these:

Argo CD apps - command line

You could also verify this using the Argo CD UI.
Below is the page displaying the three Argo CD applications that were created:

Argo CD apps - UI

Clicking on each of the applications should show you similar pages:

parent app

Argo CD parent app

frontend app

Argo CD frontend app

backend app

Argo CD backend app

Step 4 - GitOps in Action

To see the power of GitOps, we will update the backend deployment manifest so it now has 3 replicas instead of the initial 2.
After making this change and pushing it to the Git repository, we should see our backend application update automatically (you may need to refresh your apps in the UI).

As you can see from the image below, the backend application no longer has 2 replicas, but now has 3:

Argo CD updated backend app

Conclusion

By implementing Argo CD on your EKS clusters with the App of Apps pattern, you move from imperative cluster management to a true GitOps operating model, thereby leading to faster, reproducible deliveries, with auditable changes.

Top comments (0)