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
- You have a Kubernetes cluster running
-
kubectlis configured to talk to your Kubernetes cluster - You have a basic understanding of GitOps
- You have a Git repository. I'll be using GitHub for this demo
- 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
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
Then we update the Helm repository list to ensure we have the latest chart information:
helm repo update
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
We can verify the installation with the following command, making sure that all pods are running:
kubectl -n argocd get pods
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
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
You can access the Argo CD UI on http://localhost:8080
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
-
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
- 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
- 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
- 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
- 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"
- 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
- 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
- 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"
- 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
- This manifest creates a service for the backend application's deployment that listens on port
80and redirects traffic to the deployment's pods on port5678
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
Argo CD will then:
- Create all Argo CD applications (
App of Apps,frontend, andbackend) - Create the Kubernetes namespaces for the frontend and backend applications
- Create the deployments for the frontend and backend applications
- Create the services for the frontend and backend applications
You should see a similar output after executing the previous command:
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
You should have outputs similar to these:
You could also verify this using the Argo CD UI.
Below is the page displaying the three Argo CD applications that were created:
Clicking on each of the applications should show you similar pages:
parent app
frontend app
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:
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)