GitOps on AWS: ArgoCD + EKS + CodeCommit/CodePipeline

I am experienced Cloud Devops Engineer I blog about Solutions, Cloud and DevOps Projects that boost your portfolio and provide troubleshooting guides on Cloud and DevOps
In the rapidly evolving world of cloud-native development, GitOps has emerged as the gold standard for continuous delivery. It shifts the paradigm from manual deployments to a declarative system where your Git repository is the single source of truth for your infrastructure and application state.
But how do you implement this on AWS in a way that is secure, scalable, and automated?
In this comprehensive guide, we will walk through building a complete GitOps pipeline. We will combine the power of AWS Managed Services (EKS, CodePipeline, CodeCommit) with ArgoCD, the industry-leading GitOps controller for Kubernetes. By the end of this tutorial, you will have a fully automated workflow where a simple git push triggers a build, updates your manifests, and syncs your application to a Kubernetes cluster.
🛠️ The Tech Stack: Why These Tools?
Before we write a single line of code, let's look at the components of our solution and why they were chosen.
1. Amazon EKS (Elastic Kubernetes Service)
We need a robust container orchestration platform. EKS removes the heavy lifting of managing the Kubernetes control plane, allowing us to focus on running workloads. We are using Kubernetes v1.34 for this project.
2. AWS CodeCommit & CodePipeline
CodeCommit: A secure, private Git repository to host our code. It integrates natively with IAM for security.
CodePipeline & CodeBuild: A serverless CI solution. It handles the "heavy lifting" of building Docker images and—crucially—updating our Git repository with new image tags.
3. ArgoCD
The heart of our GitOps strategy. ArgoCD runs inside our cluster. Unlike traditional CD tools that push changes to the cluster (requiring external admin access), ArgoCD pulls changes from the Git repository. This improves security and ensures that if someone manually changes the cluster, ArgoCD detects the drift and fixes it.
🏗️ The Architecture: Push vs. Pull
We are implementing a hybrid "Push-based CI" and "Pull-based CD" workflow:
The Push (CI): A developer pushes code to CodeCommit. CodePipeline triggers CodeBuild, which builds the Docker image, pushes it to Amazon ECR, and then commits the new image tag back to the Git repository.
The Pull (CD): ArgoCD detects the change in the Git repository (the updated Helm chart) and automatically syncs the EKS cluster to match the new state.

The automated CI pipeline that bridges the gap between code and infrastructure.
✅ Prerequisites
To follow along, ensure you have:
An AWS Account with admin permissions.
Terraform installed (for provisioning infrastructure).
kubectl and AWS CLI configured locally.
Docker running on your machine.
🚀 Step 1: Provisioning the Infrastructure
We start by laying the foundation using Terraform. We need a VPC, an EKS cluster, and the necessary IAM roles for our pipeline.
Note: The full Terraform code is available in the infrastructure/ folder of the project repository.
Once the infrastructure is applied, we verify our EKS cluster is active.

Installing ArgoCD
With the cluster running, I install ArgoCD. This is the only time I manually interact with the cluster for setup.
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
📂 Step 2: The Monorepo Structure
A clean repository structure is crucial for GitOps. We are using a Monorepo pattern:
app/: Contains the source code (Python Flask) andDockerfile.gitops/: Contains the Kubernetes manifests (Helm Charts) and ArgoCD configuration.pipeline/: Contains thebuildspec.ymlfor CI.infrastructure/: Contains the Terraform code.

🔄 Step 3: The CI Pipeline (The "GitOps Glue")
This is the most interesting part of the setup. How do we tell ArgoCD that a new image is ready? We don't talk to ArgoCD directly. Instead, we update Git.
Our AWS CodeBuild project does three things:
Builds the Docker image.
Pushes the image to Amazon ECR with the Git commit hash as the tag (e.g.,
7161a34).Updates the Helm chart in the
gitops/folder with this new tag and pushes the change back to the repo.
The Buildspec Magic
Here is the snippet from pipeline/buildspec.yml that closes the loop:
post_build:
commands:
- echo Pushing the Docker image...
- docker push $REPOSITORY_URI:$IMAGE_TAG
- echo Updating Helm chart values...
- git clone -b main $REPO_URL temp_repo
- cd temp_repo
# The magic command: Update the tag in values.yaml
- sed -i "s|tag: .*|tag: \"$IMAGE_TAG\"|" gitops/charts/webapp/values.yaml
- git commit -m "Update image tag to $IMAGE_TAG"
- git push origin main
This automated commit is what triggers the next phase.


☸️ Step 4: The CD Controller (ArgoCD)
Now that the Git repository has been updated with the new image tag, ArgoCD takes over.
We configure an ArgoCD Application that watches our gitops/charts/webapp directory.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: gitops-webapp
namespace: argocd
spec:
source:
repoURL: 'ssh://git-codecommit.us-west-2.amazonaws.com/v1/repos/gitops-on-aws'
targetRevision: main
path: gitops/charts/webapp
destination:
server: 'https://kubernetes.default.svc'
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
The Sync Process
ArgoCD polls the repository.
It sees the
values.yamlfile has a new tag (tag: "7161a34").It compares this with the live cluster state.
It applies the change, causing Kubernetes to perform a rolling update to the new image.


🎯 Step 5: Verification & The "Loop"
To verify everything is working, we simply access the application via the Load Balancer URL provided by AWS.

And finally, we can look at our Git history. We see a beautiful audit trail: developers commit code, and the "CodeBuild" user commits the deployment updates.

🏁 Conclusion
By combining AWS CodePipeline for integration and ArgoCD for delivery, we have built a pipeline that is:
Declarative: The entire state of our system is defined in Git.
Automated: No manual deployments or
kubectlcommands required.Auditable: Every change is tracked in the Git history.
This architecture represents the modern standard for deploying applications on Kubernetes, leveraging the best of AWS managed services and open-source GitOps tooling.
👉 Check out the repo: https://github.com/ChisomJude/GitOps-on-AWS




