Manage OrderFlow on EKS with Argo CD
Use Argo CD to reconcile Git-based OrderFlow deployments on Amazon EKS.
Introduction
30 Second Summary
A manual update can leave a live service out of step with the version everyone agreed to ship. Each direct change makes the live system harder to trust.
In this project, you will create a GitOps delivery loop for the existing OrderFlow environment on Amazon EKS. Argo CD reconciles secret-safe desired state from GitHub into Kubernetes.
What You'll Build
A replica change pushed to GitHub reaches the live cluster through Argo CD until Caddy shows two ready replicas.
By the end of this project, you'll have:
- Secret-safe desired state you can inspect in a public repository as a Kustomize overlay with no plaintext credentials.
- Git-driven releases that scale Caddy plus the Catalog API to two ready replicas through commits.
- Self-healing proof where a direct Caddy scale-down returns to Git's declared two replicas without another commit.
- Secret Mission: Enable automatic pruning with a harmless ConfigMap. Prove the deletion by removing its manifest from Git.
Are there any prerequisites?
The completed persistent-checkout workspace plus its live OrderFlow EKS environment are required for this project. A deleted orderflow-foundation cluster sits outside this project's rebuild scope.
Before We Start
This checkpoint locks in the delivery model: Git declares OrderFlow's Kubernetes state for Argo CD to reconcile into Amazon EKS. You are also committing to delete the paid orderflow-foundation environment after you complete the proof.
Verify EKS and Install Argo CD
A GitOps controller needs a reachable cluster before it can enforce the state stored in Git. Argo CD also needs the inherited OrderFlow resources to remain available.
The inherited Amazon EKS environment may be running or paused. This step confirms its state before installing the reconciliation layer.
In this step, get ready to:
- Restore access to the existing EKS cluster.
- Verify the inherited OrderFlow deployment.
- Install Argo CD v3.5.2.
Detect and restore the inherited EKS state
Your AWS CLI identity determines which account is searched for the cluster. Checking that identity first prevents you from investigating the wrong AWS account.
- Verify your AWS identity and list the EKS clusters in us-east-1 by running these commands:
aws sts get-caller-identity
aws eks list-clusters --region us-east-1
What do these checks prove?
- The first command shows the AWS account used by your current credentials.
- The second command lists the EKS clusters available to that account in us-east-1.
- Confirm the account details match the AWS account that contains OrderFlow.
- Choose the tab that matches the cluster list you received.
✔️ I See orderflow-foundation
The cluster still exists. The next check connects kubectl to it and reveals its current worker capacity.
- Update your kubeconfig and inspect the worker nodes by running these commands:
aws eks update-kubeconfig --region us-east-1 --name orderflow-foundation
kubectl get nodes
What happens here?
- The kubeconfig command sets orderflow-foundation as the current cluster context.
- The node check shows whether the managed worker capacity is ready for OrderFlow and Argo CD.
- Choose the tab that matches the node output.
✔️ I See One Ready Node
Your worker is active. The cluster has enough capacity for the inherited workloads and the Argo CD evaluation deployment.
ⓧ I Do Not See a Ready Node
The managed node group may be paused at zero workers. Restoring one worker can take several minutes while AWS provisions the instance.
- Restore one worker and watch for its Ready status by running these commands:
aws eks update-nodegroup-config --cluster-name orderflow-foundation --nodegroup-name orderflow-workers --scaling-config minSize=1,maxSize=2,desiredSize=1 --region us-east-1
aws eks wait nodegroup-active --cluster-name orderflow-foundation --nodegroup-name orderflow-workers --region us-east-1
kubectl get nodes --watch
How does the restore work?
- The first command sets the managed node group to one desired worker.
- The waiter pauses until AWS reports the node group as active.
- The final command streams node updates so you can see when the worker becomes Ready.
- Stop the node watch with Ctrl+C after one node reports Ready.
Worker still not becoming Ready?
Confirm that your AWS identity belongs to the account containing orderflow-foundation. Check that the node group command completed successfully before starting the watch.
Ask for help with the exact output you received: Help me diagnose why my EKS managed node is not becoming Ready.
ⓧ orderflow-foundation Is Missing
The cluster has been deleted. Rebuilding the EKS foundation and the complete OrderFlow deployment falls outside this project's scope.
- Stop this project before making any changes.
- Repeat the preceding EKS foundation project.
- Repeat the preceding OrderFlow deployment project.
Why must the cluster exist first?
This project adds GitOps management to an existing OrderFlow environment. Argo CD needs that environment before it can adopt and reconcile its resources.
Good checkpoint. Your current Kubernetes context now points to orderflow-foundation with one Ready worker.
Confirm the inherited application boundary
OrderFlow already has workloads and storage inside the cluster. Verifying that boundary prevents Argo CD from being installed against an incomplete application environment.
- Inspect the inherited OrderFlow resources by running this command:
kubectl -n orderflow get deployments,services,pods,pvc
What should this inventory contain?
You should see ten Deployments and nine Services. You should also see four PersistentVolumeClaims plus the Pods supporting the inherited application.
OrderFlow resources missing?
A missing namespace or incomplete workload list means the inherited deployment is unavailable. Repeat the preceding EKS deployment project before continuing.
Share only the resource names and statuses when asking for help: Help me understand which inherited OrderFlow resources are missing from my EKS cluster.
The application also depends on an out-of-band Secret. You only need to prove that the Secret exists.
- Confirm the inherited Secret exists without printing its contents by running this command:
kubectl -n orderflow get secret orderflow-secrets
Why keep this Secret out of Git?
The live Secret satisfies the application's credential dependency. The next project stage can copy the deployment configuration without committing credential values.
Secret not found?
Repeat the preceding OrderFlow deployment project if orderflow-secrets is absent. Do not recreate it from memory or print another Secret while troubleshooting.
Get help without sharing credential values: Help me verify why the orderflow-secrets Secret is missing without exposing its contents.
The inherited Kustomize overlay combines the Kubernetes manifests used by the EKS deployment. A successful render proves that its resource references still resolve.
- Return to the terminal in the persistent-checkout workspace.
- Render the inherited EKS overlay by running this command:
kubectl kustomize k8s/overlays/eks
What does this render prove?
The command builds the combined manifests without applying them. A complete YAML render confirms that the inherited overlay can still produce OrderFlow's desired resources.
Overlay not rendering?
Confirm that your terminal is in the persistent-checkout workspace. The relative path must lead to the inherited k8s/overlays/eks directory.
Ask for help with the render error only: Help me diagnose why the inherited EKS Kustomize overlay does not render.
Install the pinned Argo CD evaluation deployment
Argo CD runs inside the same EKS cluster that it manages. The pinned v3.5.2 manifest creates the controller and supporting services needed for reconciliation.
- Check whether the argocd namespace or any Argo CD workloads already exist by running these commands:
kubectl get namespace argocd
kubectl -n argocd get statefulsets,deployments,pods
Why check the current state?
The namespace check separates a fresh installation from an existing namespace. The workload list reveals whether an earlier Argo CD deployment is already present.
- Choose the tab that matches the results from both checks.
✔️ The argocd Namespace Is Missing
This is a fresh installation. The manifest can take several minutes to create the Argo CD controllers and services.
- Create the namespace and install Argo CD v3.5.2 by running these commands:
kubectl create namespace argocd
kubectl apply -n argocd --server-side --force-conflicts -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.5.2/manifests/install.yaml
What does the installation create?
- The first command creates the namespace that holds the Argo CD resources.
- The second command applies the pinned non-HA evaluation manifest.
- Server-side apply handles the large Argo CD resource definitions.
ⓧ The argocd Namespace Is Empty
The namespace already exists without Argo CD workloads. You can install the pinned deployment directly into it.
- Install Argo CD v3.5.2 in the existing namespace by running this command:
kubectl apply -n argocd --server-side --force-conflicts -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.5.2/manifests/install.yaml
What does this command do?
The command installs the pinned evaluation deployment into the existing namespace. Server-side apply creates the Argo CD resources declared by the manifest.
ⓧ Argo CD Resources Already Exist
Existing resources may come from an earlier installation attempt. Applying the pinned manifest aligns them with Argo CD v3.5.2.
- Reconcile the existing installation to the pinned manifest by running this command:
kubectl apply -n argocd --server-side --force-conflicts -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.5.2/manifests/install.yaml
Why use the pinned manifest again?
The manifest declares the selected Argo CD release. Server-side apply updates conflicting installation resources to match that declaration.
Argo CD now needs time to start its Deployments and application controller. The availability check allows up to 300s for the Deployments.
- Wait for the Argo CD Deployments and controller StatefulSet by running these commands:
kubectl wait --for=condition=Available deployment --all -n argocd --timeout=300s
kubectl rollout status statefulset/argocd-application-controller -n argocd --timeout=300s
What do the availability checks cover?
- The first command waits for every Argo CD Deployment to become available.
- The second command waits for the application controller StatefulSet to finish its rollout.
Argo CD not becoming available?
Confirm that the worker still reports Ready. A paused or unavailable worker prevents the Argo CD Pods from being scheduled.
Ask for help with the workload statuses you can safely share: Help me diagnose why my Argo CD Deployments or application controller are not becoming available.
Before you run the final check, do you expect both namespaces to show available workloads?
- Verify Argo CD and OrderFlow together by running these commands:
kubectl -n argocd get statefulsets,deployments,pods
kubectl -n orderflow get deployments,pods,pvc
What should you see?
You should see the argocd-application-controller StatefulSet plus the Argo CD Deployments and Pods. Their availability confirms that the installation is running.
You should also see all ten OrderFlow Deployments plus their Pods and four PersistentVolumeClaims. This confirms that installing Argo CD did not disrupt the inherited application.
That is the foundation secured. Argo CD is running beside a healthy OrderFlow deployment and is ready to receive a Git-backed Application.
Your cluster and reconciliation controller are ready. Next, you will prepare a secret-safe desired state for Git.
Publish Secret-Safe Desired State
Your Amazon EKS cluster is healthy. Argo CD is ready to reconcile workloads.
Git can become the source of truth only after the inherited plaintext training credentials are removed. You need a configuration-only copy that is safe to publish.
This step also proves that a Git commit cannot change the live cluster by itself.
In this step, get ready to:
- Create a configuration-only copy of the inherited Kubernetes manifests without the plaintext Secret.
- Add a Kustomize overlay that declares two Caddy replicas.
- Publish the desired state to a public GitHub repository before testing its effect on the live cluster.
Create a secret-safe repository copy
The inherited manifest combines storage resources with a plaintext training Secret. Your public repository needs the storage definitions while the live Secret stays outside Git.
You will use the Linux file manager for the copy. You will edit the copied manifests in Visual Studio Code.
- Use the Linux file manager to create the `orderflow-gitops` folder inside your home folder.
- Copy the existing `k8s` directory from the `persistent-checkout` workspace into `~/orderflow-gitops`.
- Open the copied folder in Visual Studio Code by running this command:
code ~/orderflow-gitops
What does this command do?
The `code` command opens `~/orderflow-gitops` as its own Visual Studio Code workspace. This keeps every edit inside the configuration-only copy.
- Confirm the Visual Studio Code Explorer shows the copied `k8s` directory.
Copied folder missing?
Check that `orderflow-gitops` sits directly inside your home folder. Confirm that the copied `k8s` directory is inside it.
Ask for help if the workspace opened in the wrong location: Help me check where my orderflow-gitops folder was created on Linux.
- Select the `k8s` directory in the Visual Studio Code Explorer.
- Create a file named `00-platform.yaml` inside `k8s`.
- Add the Namespace plus the first two storage claims by pasting this code:
apiVersion: v1
kind: Namespace
metadata:
name: orderflow
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: order-data
namespace: orderflow
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: inventory-data
namespace: orderflow
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
What does this code do?
- The Namespace keeps OrderFlow resources inside the `orderflow` boundary.
- The `order-data` claim reserves storage for order data.
- The `inventory-data` claim reserves storage for inventory data.
- Each claim requests `1Gi` with the `ReadWriteOnce` access mode.
- Save `k8s/00-platform.yaml`.
- Confirm the file shows the `orderflow` Namespace plus the `order-data` and `inventory-data` claims.
YAML structure looks uneven?
Check that each nested YAML level uses two spaces. Confirm that each `---` separator starts at the beginning of its line.
Ask for help with the first manifest section: Help me check the YAML structure in 00-platform.yaml.
- Place the cursor after the `inventory-data` storage request in `k8s/00-platform.yaml`.
- Add the remaining storage claims by pasting this code:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: catalog-data
namespace: orderflow
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rabbitmq-data
namespace: orderflow
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
What does this code do?
- The `catalog-data` claim preserves Catalog data.
- The `rabbitmq-data` claim preserves RabbitMQ data.
- Both claims stay in the `orderflow` Namespace.
- Save `k8s/00-platform.yaml`.
- Confirm the file now contains four PersistentVolumeClaims.
Missing a storage claim?
Confirm the file contains `order-data`, `inventory-data`, `catalog-data`, and `rabbitmq-data`. Check that every claim has its own YAML document separator.
Ask for help comparing the four claims: Help me find the missing claim in 00-platform.yaml.
- Select `k8s/kustomization.yaml` in the Visual Studio Code Explorer.
- Replace its contents with this Secret-free resource list:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- 00-platform.yaml
- 10-catalog.yaml
- 20-ordering.yaml
- 30-app-config.yaml
- 40-gateway.yaml
What does this code do?
This Kustomization replaces the sensitive foundation manifest with `00-platform.yaml`. The inherited workload manifests remain part of the desired state.
- Save `k8s/kustomization.yaml`.
- Delete the copied `k8s/00-foundation.yaml` file in the Visual Studio Code Explorer.
- Search the copied `k8s` directory for `kind: Secret` using Visual Studio Code's workspace search.
- Search the copied `k8s` directory for `stringData:` using Visual Studio Code's workspace search.
- Confirm both searches return no results.
Why remove the Secret manifest?
The existing `orderflow-secrets` Secret remains live in the cluster as an out-of-band prerequisite. Removing its manifest prevents the plaintext training credentials from entering the public repository.
Search still finds Secret content?
Open each search result to identify the copied file that still contains the sensitive fields. Remove that copied Secret definition before continuing.
Ask for help reviewing the search results without sharing any credential values: Help me remove Secret definitions from my copied k8s directory.
Add a GitOps overlay
A Kustomize overlay can change one part of the inherited EKS configuration without duplicating every workload manifest. This overlay declares two Caddy replicas as the next desired state.
- Create the `k8s/overlays/gitops` directory in the Visual Studio Code Explorer.
- Create `caddy-replicas.yaml` inside `k8s/overlays/gitops`.
- Declare the Caddy replica target by pasting this code:
apiVersion: apps/v1
kind: Deployment
metadata:
name: caddy
namespace: orderflow
spec:
replicas: 2
What does this code do?
This patch identifies the `caddy` Deployment in the `orderflow` Namespace. Its desired replica count is set to `2`.
- Save `k8s/overlays/gitops/caddy-replicas.yaml`.
- Confirm the patch names `caddy` and declares `replicas: 2`.
Patch not matching Caddy?
Confirm the Deployment name is exactly `caddy`. Confirm the Namespace is exactly `orderflow`.
Ask for help checking the patch identity: Help me check why my Caddy replica patch is not matching the Deployment.
- Create `kustomization.yaml` inside `k8s/overlays/gitops`.
- Connect the overlay to the inherited EKS configuration by pasting this code:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../eks
patches:
- path: caddy-replicas.yaml
What does this code do?
- The `resources` entry starts with the inherited EKS overlay.
- The `patches` entry applies the Caddy replica declaration during rendering.
- Save `k8s/overlays/gitops/kustomization.yaml`.
- Open a terminal for the `orderflow-gitops` Visual Studio Code workspace.
Before you render the overlay, which Caddy replica count do you expect to find?
- Render the GitOps overlay without applying it by running this command:
kubectl kustomize ~/orderflow-gitops/k8s/overlays/gitops
What does this command do?
The command builds the complete manifest from the GitOps overlay without changing the cluster. It combines the inherited EKS resources with the Caddy patch.
The rendered output contains the Caddy Deployment with `replicas: 2`. It contains no `kind: Secret` manifest.
- Find the rendered Caddy Deployment in the terminal output.
- Confirm its specification contains `replicas: 2`.
- Confirm the rendered output contains no Secret resource.
Overlay fails to render?
Check that `k8s/overlays/gitops/kustomization.yaml` points to `../eks`. Confirm that `caddy-replicas.yaml` sits beside it.
Ask for help with the overlay paths: Help me debug my GitOps Kustomize overlay paths.
Use these tabs to compare every new file with the completed secret-safe desired state.
✔️ Awesome, I've got everything!
Great. Save every file before publishing the repository.
ⓧ I'd like to double check the full code
apiVersion: v1
kind: Namespace
metadata:
name: orderflow
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: order-data
namespace: orderflow
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: inventory-data
namespace: orderflow
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: catalog-data
namespace: orderflow
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rabbitmq-data
namespace: orderflow
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- 00-platform.yaml
- 10-catalog.yaml
- 20-ordering.yaml
- 30-app-config.yaml
- 40-gateway.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: caddy
namespace: orderflow
spec:
replicas: 2
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../eks
patches:
- path: caddy-replicas.yaml
Publish the repository and test the gap
Git needs a commit identity before it can record the desired state. The public repository must also stay empty until your local files are ready to push.
- Check the configured Git commit name and email by running these commands:
git config --global user.name
git config --global user.email
What do these commands check?
The first command prints the name attached to future commits. The second command prints the email attached to those commits.
Choose the tab that matches what the terminal returned.
✔️ Both values appear
Your Git commit identity is ready. Continue to the GitHub repository setup.
ⓧ One or both values are empty
Git needs a value for each empty identity field before it can create the commit.
- Choose the command that matches each empty value.
- Replace `YOUR_NAME` or `YOUR_EMAIL` with your own commit identity.
- Set each missing value by running the relevant line below:
git config --global user.name "YOUR_NAME"
git config --global user.email "YOUR_EMAIL"
What do these commands change?
These commands save your chosen commit name and email in Git's global configuration. Future commits use that identity.
- Recheck both configured values by running:
git config --global user.name
git config --global user.email
What should you see?
The terminal now prints a name followed by an email address. Both values need visible output before you continue.
Identity still empty?
Confirm that you replaced the uppercase placeholder in the command you ran. Check that the value remains inside quotation marks.
Ask for help with the Git configuration: Help me configure my Git commit identity on Linux.
- Go to GitHub in your browser.
- Select **New repository**.
- Enter `orderflow-gitops` as the repository name.
- Set the repository visibility to **Public**.
- Leave the README option unselected.
- Leave the `.gitignore` option unselected.
- Leave the license option unselected.
- Select **Create repository**.
Why keep the repository empty?
An empty remote avoids an unrelated initial commit. Your local secret-safe desired state becomes the repository's first history.
- Return to the terminal for the `orderflow-gitops` Visual Studio Code workspace.
- Initialize the repository and create its first commit by running these commands:
git init -b main
git add .
git commit -m "Create secret-safe OrderFlow desired state"
What do these commands do?
- `git init -b main` initializes the repository with `main` as its first branch.
- `git add .` stages the secret-safe files.
- The commit records those staged files as OrderFlow's desired state.
- Confirm the terminal prints a commit summary for the new files.
Commit not created?
Confirm the terminal belongs to the `orderflow-gitops` workspace. Check that both Git identity values were configured.
Ask for help with the first commit: Help me diagnose why my first orderflow-gitops commit was not created.
- Copy the Quick Setup URL that matches the Git authentication already configured on your Linux device.
- Replace `REMOTE-URL` in the command below with the copied URL.
- Add the remote and display its configuration by running:
git remote add origin REMOTE-URL
git remote -v
What do these commands do?
The first command names the GitHub repository `origin`. The second command displays the saved fetch and push destinations.
- Confirm the remote output shows the copied repository URL for both fetch and push.
Remote URL looks wrong?
Compare the displayed remote with the Quick Setup URL from the `orderflow-gitops` repository. Confirm that no placeholder text remains.
Ask for help checking the remote safely: Help me verify my Git remote URL without sharing authentication credentials.
How HTTPS authentication works
An HTTPS push can request credentials. GitHub accepts a personal access token in place of the account password.
- Use a personal access token if an HTTPS push requests a password.
- Publish the `main` branch by running this command:
git push -u origin main
What does this command do?
The command uploads the local `main` branch to `origin`. It also records the remote branch as the default destination for future pushes.
- Return to the `orderflow-gitops` repository page in GitHub.
- Refresh the repository page.
- Confirm the `k8s` directory and its secret-safe files are visible on the `main` branch.
Push did not reach GitHub?
Confirm that `origin` points to the new empty repository. Use a personal access token if HTTPS authentication rejects an account password.
Ask for help without sharing the token: Help me troubleshoot my GitHub push safely.
The repository now stores a desired Caddy count of two. The next check reveals whether publishing that commit changed the live cluster.
Before you check, do you think the Git commit changed the live replica count?
- Check the live Caddy Deployment by running this command:
kubectl -n orderflow get deployment caddy
What does this command check?
The command reads the live `caddy` Deployment from the `orderflow` Namespace. Its desired count shows what the cluster currently enforces.
The live desired count remains one. Your Git repository declares two replicas.
That mismatch is intentional. Git stores the desired state, but no reconciliation link is enforcing it yet.
Strong work. Your secret-safe desired state is published without changing the unmanaged cluster. Next, you will connect Argo CD to the repository and close that reconciliation gap.
Connect Argo CD to Git
Your secret-safe repository now stores OrderFlow's desired state in Git. The live cluster still has one Caddy replica because no controller connects that desired state to the cluster.
An Argo CD Application creates that connection through a public HTTPS read. It reconciles the repository's Kustomize overlay into the existing Kubernetes environment.
In this step, get ready to:
- Declare an Argo CD Application that points to your public repository.
- Apply the Application to start automated synchronization.
- Prove that reconciliation scales Caddy from one replica to two.
Declare the Argo CD Application
The Application manifest tells Argo CD where to find the desired state. It also defines the cluster destination plus the automation rules that keep the live resources aligned with Git.
- Return to the public orderflow-gitops repository page on GitHub.
- Select Code above the repository files.
- Select HTTPS in the clone options.
- Copy the public HTTPS clone URL.
- Record the copied value here: your public GitHub HTTPS clone URL.
- Switch back to Visual Studio Code from earlier.
- Use the Explorer sidebar to create argocd/orderflow-application.yaml inside ~/orderflow-gitops.
- Populate argocd/orderflow-application.yaml by pasting this manifest:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: orderflow
namespace: argocd
spec:
project: default
source:
repoURL: your-public-github-https-clone-url
targetRevision: main
path: k8s/overlays/gitops
destination:
server: https://kubernetes.default.svc
namespace: orderflow
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
allowEmpty: false
What does this manifest control?
- The source section selects the public repository's main branch.
- The path field points Argo CD to k8s/overlays/gitops.
- The destination section targets the same cluster plus the orderflow namespace.
- The selfHeal setting lets Argo CD correct live changes that conflict with Git.
- The prune setting stays false so this step cannot automatically delete tracked resources.
- The allowEmpty setting stays false to preserve protection against an empty target state.
The editor now shows the complete Application declaration with one repository placeholder ready for your URL.
- Replace your-public-github-https-clone-url with your public GitHub HTTPS clone URL.
- Save argocd/orderflow-application.yaml.
The Explorer sidebar should now list orderflow-application.yaml inside the new argocd folder.
Manifest not looking right?
Check that each nested YAML section uses spaces consistently. Confirm that argocd sits directly inside ~/orderflow-gitops.
Make sure the repository URL starts with the public HTTPS form copied from GitHub. An SSH URL requires repository credentials that this Application does not configure.
Help me compare my Application manifest with the required structure.
✔️ Awesome, I've got everything!
Your Application manifest is saved. Keep your own public HTTPS clone URL in the repoURL field.
ⓧ I'd like to double check the full code
Compare your file with this complete template. The repository placeholder marks where your copied public HTTPS clone URL belongs.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: orderflow
namespace: argocd
spec:
project: default
source:
repoURL: your-public-github-https-clone-url
targetRevision: main
path: k8s/overlays/gitops
destination:
server: https://kubernetes.default.svc
namespace: orderflow
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
allowEmpty: false
What should match?
The source path must remain k8s/overlays/gitops. The destination must remain the in-cluster Kubernetes API plus the orderflow namespace.
Your saved file should contain your copied URL where this template shows your-public-github-https-clone-url.
The Application declaration belongs in Git too. This keeps the delivery controller's configuration beside the desired state it manages.
- Return to the terminal in ~/orderflow-gitops from earlier.
- Publish the Application declaration by running these commands:
git add argocd/orderflow-application.yaml
git commit -m "Declare the OrderFlow Argo CD application"
git push origin main
What do these commands record?
- The first command stages the Application manifest.
- The second command records the declaration in the local repository history.
- The third command publishes that commit to the public main branch.
You should see Git confirm the new commit before it finishes pushing the branch.
- Return to the GitHub repository page.
- Select the argocd folder.
- Select orderflow-application.yaml to confirm the manifest is visible on the main branch.
Push did not reach GitHub?
Confirm the terminal is inside ~/orderflow-gitops. Check that the repository remote still points to your public orderflow-gitops repository.
If an HTTPS push requests a password, use the GitHub authentication method already configured on your Linux device. GitHub account passwords do not authenticate Git pushes.
Help me diagnose why my Application commit did not reach GitHub.
Connect Argo CD to Git
The commit records the controller configuration in Git. Applying the manifest creates the Application resource that starts reconciliation.
- Return to the terminal in ~/orderflow-gitops.
- Create the Application resource by running this command:
kubectl apply -f argocd/orderflow-application.yaml
What does this command do?
This sends the declarative Application manifest to the Kubernetes API. Argo CD can now read the public repository plus compare its rendered resources with the live orderflow namespace.
You should see kubectl confirm that the orderflow Application was created or configured.
A short wait here is normal because repository polling can take up to three minutes before Argo CD detects the desired state.
- Watch the Application synchronize by running this command:
kubectl get application orderflow -n argocd -w
What does the watch show?
The watch keeps the current Application state visible while Argo CD reads the repository. Keep it running until synchronization succeeds.
- Stop the watch with Ctrl+C after synchronization succeeds.
- Inspect the completed synchronization record by running this command:
kubectl get application orderflow -n argocd -o yaml
Where is the sync result?
The status.operationState.phase field records the completed synchronization result. A successful run reports Succeeded.
You should see Succeeded under status.operationState.phase.
Repository connection failing?
Recheck that repoURL contains the public HTTPS clone URL. An SSH URL cannot use the anonymous public read path configured in this project.
Confirm that the URL belongs to the public orderflow-gitops repository. Confirm that the main branch contains k8s/overlays/gitops.
Help me troubleshoot the Argo CD repository connection.
Prove the First Reconciliation
The Application reports that synchronization completed. The live Caddy Deployment now provides the visible proof that Argo CD enforced Git's desired state.
Before you run these checks, do you expect Caddy to stay at one replica or move to the two replicas declared in Git?
- Verify the new desired state plus the completed rollout by running these commands:
kubectl wait --for=jsonpath='{.spec.replicas}'=2 deployment/caddy -n orderflow --timeout=300s
kubectl rollout status deployment/caddy -n orderflow --timeout=180s
kubectl get application orderflow -n argocd
kubectl -n orderflow get deployment caddy
What do these checks prove?
- The replica wait cannot succeed while the Deployment still declares one replica.
- The rollout check waits for the new Caddy replica set to become available.
- The Application check confirms that Argo CD has finished reconciling the repository.
- The final Deployment check exposes the desired plus available Caddy replica counts.
You should see a successful synchronized Application. Caddy should show two desired replicas plus two available replicas.
That closes the reconciliation gap. Git now declares the state while Argo CD enforces it without giving GitHub direct cluster access.
Caddy still showing one replica?
Confirm that the Application completed synchronization before checking the Deployment. Recheck that spec.source.path points to k8s/overlays/gitops.
Confirm that the public repository's main branch still contains caddy-replicas.yaml with replicas: 2.
Help me find why Argo CD has not scaled Caddy to two replicas.
Your first Git-driven reconciliation is complete. Next, you will release a Catalog scaling change through the same delivery loop.
Release the Catalog Change
Argo CD has already turned the Caddy replica change in Git into a live Kubernetes rollout. Your first reconciliation loop is working.
A second commit proves this delivery path is repeatable. The Catalog release travels from Git to Argo CD to Kubernetes without giving GitHub cluster credentials.
In this step, get ready to:
- Declare two replicas for the Catalog Deployment.
- Publish the Catalog change through Git.
- Verify the Catalog rollout through Argo CD.
Declare the Catalog replica count
Kustomize can apply a small patch without duplicating the full Catalog Deployment. This patch makes two Catalog replicas part of the desired state.
- In the Visual Studio Code Explorer for ~/orderflow-gitops, select k8s/overlays/gitops.
- Create catalog-replicas.yaml inside that folder.
- Declare two Catalog replicas by pasting this configuration into catalog-replicas.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-service
namespace: orderflow
spec:
replicas: 2
What does this patch do?
- The metadata.name value targets the existing catalog-service Deployment.
- The metadata.namespace value keeps the patch inside orderflow.
- The spec.replicas value declares two Catalog Pods.
- Save catalog-replicas.yaml.
- In k8s/overlays/gitops/kustomization.yaml, find this patch list:
patches:
- path: caddy-replicas.yaml
What are you locating?
This list currently tells Kustomize to apply only the Caddy replica patch. The Catalog patch needs its own entry in the same list.
- Add catalog-replicas.yaml below the existing Caddy entry so the patch list looks like this:
patches:
- path: caddy-replicas.yaml
- path: catalog-replicas.yaml
What changed?
The overlay now applies both replica patches during every render. Caddy stays at two replicas while Catalog gains its own two-replica declaration.
- Save k8s/overlays/gitops/kustomization.yaml.
- Return to the terminal in ~/orderflow-gitops.
- Render the updated GitOps overlay by running this command:
kubectl kustomize k8s/overlays/gitops
What does this command prove?
The command renders the complete overlay locally without changing the cluster. A successful render proves that both patch files match their target Deployments.
In the rendered YAML, you will find the Caddy Deployment with replicas: 2. You will also find the Catalog Deployment with replicas: 2.
Overlay not rendering?
Check that catalog-replicas.yaml sits inside k8s/overlays/gitops. Confirm that its filename matches the new patch entry exactly.
Compare the indentation under patches with the reference below. YAML spacing controls which values belong to that list.
Help me debug the Catalog Kustomize patch.
✔️ Awesome, I've got everything!
Great. Double-check that both files are saved before you publish the release.
ⓧ I'd like to double check the full code
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-service
namespace: orderflow
spec:
replicas: 2
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../eks
patches:
- path: caddy-replicas.yaml
- path: catalog-replicas.yaml
Publish the Catalog release
The local render proves that the desired state is valid. Publishing it to main gives Argo CD a new revision to reconcile.
- Publish the Catalog release from the terminal in ~/orderflow-gitops by running these commands:
git add k8s/overlays/gitops
git commit -m "Scale Catalog through GitOps"
git push origin main
What do these commands do?
- The first command stages both the new patch file and the updated overlay configuration.
- The second command records the desired-state change in Git history.
- The third command publishes the commit to the public repository watched by Argo CD.
You will see Git create the Scale Catalog through GitOps commit. The push output confirms that main received the new revision.
Push not completing?
Confirm that the terminal is still inside ~/orderflow-gitops. Check that your GitHub authentication from earlier is still available.
Help me troubleshoot this Git push.
Wait for the new desired state
An old successful rollout can look healthy before the new Git revision arrives. The replica wait checks the declared field first so the rollout check applies to the Catalog release you just pushed.
This check can take up to three minutes while Argo CD polls the repository. A quiet wait during that interval is normal.
Before you run the check, predict whether Catalog stays at one replica or reaches the two replicas declared in Git.
- Wait for the new Catalog replica count before checking rollout health by running these commands:
kubectl wait --for=jsonpath='{.spec.replicas}'=2 deployment/catalog-service -n orderflow --timeout=300s
kubectl rollout status deployment/catalog-service -n orderflow --timeout=180s
kubectl get application orderflow -n argocd
kubectl -n orderflow get deployment caddy catalog-service
How does this verify the release?
- The first command waits until the live Catalog Deployment declares two replicas.
- The second command confirms that the latest Catalog rollout completes.
- The third command shows the current synchronization state of the orderflow Application.
- The fourth command compares the live Caddy and Catalog Deployments.
You will see the Application synchronized. Caddy and Catalog each show two desired replicas plus two available replicas.
That closes the second delivery loop. Your new Git commit now controls the live Catalog replica count without giving GitHub access to the cluster.
Catalog still showing one replica?
Confirm that the push completed before the wait began. Check that catalog-replicas.yaml appears under the patches list in the repository's main branch.
If the Application is not synchronized, inspect its reported status for a repository or manifest problem. Keep the patch names identical to the saved files.
Help me find why Argo CD has not scaled Catalog.
The Git-driven release path is now repeatable. Next, you will test whether Argo CD can reverse a direct change that conflicts with Git.
Test Argo CD Self-Healing
Your latest Git release brought both target Deployments to two replicas.
Now you will test Argo CD's self-healing against a direct cluster change. The controller should restore Git's declared state without a new commit.
In this step, get ready to:
- Confirm Caddy's declared two-replica baseline.
- Create controlled live drift inside a kubectl watch.
- Verify that self-healing restores Caddy without a Git commit.
Establish the declared baseline
Self-healing needs a clear desired state to compare with the live cluster. The Kustomize overlay is the Git-backed baseline for this test.
- Return to the terminal in ~/orderflow-gitops.
- Render the GitOps overlay by running this command:
kubectl kustomize k8s/overlays/gitops
What does this render prove?
The rendered Caddy Deployment contains replicas: 2. This proves the repository still declares two Caddy replicas.
- Check the current live Caddy Deployment by running this command:
kubectl -n orderflow get deployment caddy
What does the live check prove?
Caddy currently reports two desired replicas with two available replicas. The declared state matches the live state before you introduce drift.
Baseline not showing two replicas?
- Return to ~/orderflow-gitops if the render cannot find the overlay.
- Check that caddy-replicas.yaml still contains replicas: 2 if the rendered value differs.
Help me diagnose why the GitOps overlay or live Caddy Deployment does not show two replicas.
Watch self-healing repair live drift
Drift appears when the live cluster differs from Git's declared state. A watch makes the brief mismatch visible before Argo CD repairs it.
- Start a live Caddy watch in your current terminal by running this command:
kubectl -n orderflow get deployment caddy --watch
What does the watch do?
The --watch flag keeps the terminal connected to Deployment updates. The terminal stays occupied while replica changes stream into the output.
- Open a second terminal panel in Visual Studio Code.
Before you run the next command, predict whether Caddy will remain at one replica or return to Git's value.
- Create live drift from the second terminal by running this command:
kubectl scale deployment/caddy --replicas=1 -n orderflow
What does this command change?
The scale request changes the live Caddy Deployment to one replica. The Git repository still declares two replicas.
- Return to the first terminal.
- Focus on the replica counts in the running watch.
You should see the replica counts fall toward one before returning to two. That brief reversal is Argo CD correcting the live drift from Git.
- Stop the watch by pressing Ctrl+C.
Why did Caddy return?
Argo CD detected that the live Deployment no longer matched Git. The selfHeal: true setting triggered reconciliation without another commit.
Missed the replica change?
- Repeat the scale command from the second terminal while the watch is already running.
- Check that selfHeal: true remains in argocd/orderflow-application.yaml if Caddy stays at one replica.
Help me diagnose why Argo CD did not restore Caddy to the two replicas declared in Git.
Confirm reconciliation completed
The watch captures the repair as it happens. Explicit waits now prove that the restored Deployment is stable.
Before you verify the repair, predict whether the replica wait will finish successfully.
- Wait for Caddy's declared replica count to return to two by running this command:
kubectl wait --for=jsonpath='{.spec.replicas}'=2 deployment/caddy -n orderflow --timeout=300s
What does this wait prove?
The command completes only when spec.replicas equals 2. A successful exit proves the live desired count matches Git again.
- Confirm the restored Caddy rollout is healthy by running this command:
kubectl rollout status deployment/caddy -n orderflow --timeout=180s
What does the rollout check prove?
The rollout check waits for the restored Caddy Pods to become available. This confirms that self-healing recovered a healthy Deployment.
- Display the final Caddy replica state by running this command:
kubectl -n orderflow get deployment caddy
What should you see?
Caddy shows two desired replicas with two available replicas. The temporary one-replica drift is gone.
- Confirm the OrderFlow Application is synchronized by running this command:
kubectl get application orderflow -n argocd
What does the Application status prove?
The OrderFlow Application reports a synchronized state after repairing Caddy. You made no Git commit to trigger this reconciliation.
Final checks still waiting?
- Allow up to three minutes for normal repository reconciliation before repeating the checks.
- Inspect the OrderFlow Application status if the replica wait reaches its timeout.
Help me investigate why the final Argo CD self-healing checks are still waiting.
That is the proof complete. Argo CD now protects OrderFlow's Git-declared Caddy state from direct cluster changes.
Secret mission
Prove Automatic Pruning Safely
Create a harmless tracked ConfigMap. Enable controlled pruning, then prove Argo CD removes the resource after Git stops declaring it.
Clean Up Your Resources
Clean Up Your Resources
Choose whether to keep the Amazon EKS environment running, pause its worker, or delete the cluster using your selected teardown path. Argo CD already pruned the temporary gitops-proof ConfigMap, but AWS charges continue until cleanup finishes.
Cost warning
The Amazon EKS control plane costs $0.10 per cluster-hour. Your one-hour session is estimated to cost approximately $0.20 to $0.50.
The Linux t3.large worker on Amazon EC2 costs $0.0835 per hour. Its public IPv4 address costs $0.005 per hour.
Amazon EBS storage can add charges. Amazon ECR storage can add charges.
Data transfer can add charges. T3 Unlimited CPU credits may add charges.
Resources you used:
- The orderflow-foundation Amazon EKS cluster.
- The orderflow-workers managed node group.
- The Linux t3.large worker and its public IPv4 address.
- The Amazon EBS volumes supporting the four OrderFlow PersistentVolumeClaims.
- The Amazon ECR repositories inherited from the previous project.
- Argo CD v3.5.2 in the argocd namespace.
- The orderflow Application and Kubernetes workloads.
The public orderflow-gitops GitHub repository remains your source of truth. Your selected teardown path keeps it for the next CI project.
Keep everything running
No action is needed. Choose this if you want Argo CD to continue reconciling OrderFlow from Git.
- Keep the orderflow-foundation cluster active.
- Keep the orderflow-workers node group at one desired worker.
- Keep the synchronized orderflow Application in the argocd namespace.
- Keep the public orderflow-gitops repository as the desired-state source.
AWS charges continue while the control plane, worker, storage, and public IPv4 address remain active.
Pause - I'll come back to this later
Pause the worker to stop its Amazon EC2 instance charge while preserving the EKS control plane. Retained storage and other AWS resources can remain billable.
- Scale the orderflow-workers node group to zero by running this command:
aws eks update-nodegroup-config --cluster-name orderflow-foundation --nodegroup-name orderflow-workers --scaling-config minSize=0,maxSize=2,desiredSize=0 --region us-east-1
This requests zero workers while keeping the orderflow-foundation control plane available.
The waiter checks every 30 seconds, so pauses in the terminal are expected.
- Wait for the node group update to finish by running this command:
aws eks wait nodegroup-active --cluster-name orderflow-foundation --nodegroup-name orderflow-workers --region us-east-1
The command finishes after AWS reports the managed node group as active with its new scaling configuration.
- Confirm that the cluster has no workers by running this command:
kubectl get nodes
You should see no worker nodes after the scale-in finishes.
Still seeing a worker?
The scale-in may still be finishing. Wait for the node-group update to complete before checking the nodes again.
If the worker remains, help me diagnose why the EKS node group did not scale to zero.
The EKS control plane remains active after the pause. Amazon EBS volumes and Amazon ECR storage also remain billable.
Delete - I don't want to use this again
Delete the paid EKS environment using the teardown path you selected before starting. This is permanent, so the storage checks protect you from leaving EBS volumes behind.
Each OrderFlow claim points to an EBS volume through its CSI handle. You need those volume IDs to confirm storage cleanup after deleting the namespace.
- List the cluster's PersistentVolumes by running this command:
kubectl get pv -o yaml
Why record the volume handles?
Each OrderFlow PersistentVolume contains a spec.csi.volumeHandle that identifies its Amazon EBS volume. Recording those IDs lets you verify that AWS removed the storage before the cluster disappears.
- Record each spec.csi.volumeHandle whose spec.claimRef.namespace is orderflow: your OrderFlow EBS volume IDs.
The Argo CD Application can keep reconciling resources while it exists. Remove that reconciliation link before deleting the workloads.
- Return to ~/orderflow-gitops in your terminal.
- Delete the orderflow Application by running this command:
kubectl delete -f argocd/orderflow-application.yaml
What does this remove?
This removes the Argo CD Application declaration from the cluster. Argo CD stops reconciling OrderFlow from the Git repository.
Application deletion failed?
Confirm that your terminal is in ~/orderflow-gitops so the manifest path resolves. Confirm that kubectl still points to orderflow-foundation.
If deletion still fails, help me troubleshoot deleting the Argo CD Application.
Deleting the orderflow namespace removes its workloads, Services, Secret, and PersistentVolumeClaims. The wait keeps the command active until Kubernetes finishes the namespace deletion.
- Delete the workload namespace by running this command:
kubectl delete namespace orderflow --wait=true --timeout=300s
What happens to the claims?
Deleting the namespace deletes the four OrderFlow PersistentVolumeClaims. Their storage cleanup must finish before you remove the EKS cluster.
Namespace deletion still running?
Allow the deletion to finish before continuing. A remaining workload or storage finalizer can keep the namespace in a terminating state.
If the timeout expires, help me inspect why the orderflow namespace is still terminating.
- Check for remaining project volumes by running this command:
kubectl get pv
Continue only after you no longer see a project PersistentVolume.
- Check each recorded EBS volume by replacing VOLUME-ID with one recorded value and running this command:
aws ec2 describe-volumes --volume-ids VOLUME-ID --region us-east-1
What should I confirm?
Repeat this check for every recorded volume ID. Continue only after AWS no longer returns each volume.
Still seeing an EBS volume?
The CSI cleanup may still be running. Keep the cluster in place until the volume is gone.
If a volume remains, help me investigate an OrderFlow EBS volume that was not deleted.
The cluster deletion removes the EKS control plane and managed worker infrastructure. Start it only after every project volume check is clear.
- Return to the directory containing cluster.yaml in your persistent-checkout workspace.
- Delete the EKS cluster by running this command:
eksctl delete cluster -f cluster.yaml --disable-nodegroup-eviction --wait
What does this command do?
The command uses the existing cluster.yaml configuration to delete the cluster. The --wait flag keeps the command running so deletion errors are reported.
Cluster deletion can take several minutes. A quiet terminal during this period does not mean the process has stopped.
Cluster deletion did not finish?
Confirm that cluster.yaml is in the current directory. Confirm that the namespace and EBS checks completed before retrying.
If deletion remains blocked, help me diagnose the eksctl cluster teardown.
- Confirm that the cluster is absent by running this command:
aws eks list-clusters --region us-east-1
You should no longer see orderflow-foundation in the cluster list. That confirms the paid EKS environment is removed.
Amazon ECR repositories are separate from the EKS cluster. You can retain them for the next CI project or remove each repository for complete AWS cleanup.
- Delete each unneeded ECR repository by replacing REPOSITORY-NAME with its name and running this command:
aws ecr delete-repository --repository-name REPOSITORY-NAME --force --region us-east-1
What does force delete?
The --force flag deletes a non-empty repository and its images. Use this command only for repositories you do not need for the next project.
Repository deletion failed?
Confirm that REPOSITORY-NAME matches the repository name in us-east-1.
If the repository remains, help me troubleshoot the Amazon ECR deletion.
- Keep the public orderflow-gitops GitHub repository for the next CI project.
Your selected teardown is complete once orderflow-foundation is absent. The Git repository remains as a record of the desired state you built.
Nice Work!
Nice Work!
Outstanding work! OrderFlow now runs through a GitOps delivery loop where Argo CD keeps Amazon EKS aligned with your public configuration repository in Git.
You've learned how to:
- Published a secret-safe Kustomize configuration repository without committing the inherited plaintext credentials.
- Created Git-driven releases that scaled Caddy and Catalog through automated synchronization.
- Proved self-healing by scaling Caddy down to one replica. Argo CD restored the two replicas declared in Git without another commit.
- Secret Mission: Enabled controlled pruning with the harmless gitops-proof ConfigMap. Proved Argo CD removed it after its deletion from Git.
Ready to quiz yourself?