In this article I'll walk you through the process of deploying a simple Spring Boot application to a Kubernetes cluster in AWS using GitHub Actions, and Argo CD.
Along the way, we'll also use a few additional tools and components, which we'll briefly cover — though they won't be the main focus of this article.
Why ArgoCD?
ArgoCD nowadays is the industry standard for the K8S deployment process.
Some key benefits:
Declarative GitOps approach
Git is the single source of truth. All deployment configurations are stored in Git, making rollbacks, audits, and version control easy.Automated Continuous Delivery
Argo CD automates the deployment of applications to Kubernetes once changes are pushed to Git.Visual UI & Observability
Offers a web UI to visualize:
a. Application status
b. Health of Kubernetes resources
c. Sync status (Git vs cluster)Access Control & Security
a. Role-based access control (RBAC)
b. Supports integrations with OIDC, SSO providers (e.g., Google, GitHub)
c. Can limit which users can deploy to which namespaces or clustersMulti-Cluster Support
a. Manages and deploys apps to multiple Kubernetes clusters from a single Argo CD instance
b. Good fit for hybrid or multi-cloud environmentsTooling Flexibility
Supports Helm, Kustomize, Jsonnet, and plain YAML.
Prerequisites
To demonstrate the real-world example we'll need a few things in place before we can jump to the CI/CD process itself.
These things are going be covered by these two repos:
So, the 3 things we need to have before we can go further are:
Kubernetes cluster which has ArgoCD onboard
This is the step where we create all the infrastructure needed for hosting our application - Network, Certificates, DNS entries, and Kubernetes cluster itself. I use Terraform to bootstrap the EKS Kubernetes cluster in AWS, and install ArgoCD into it.
The configuration that covers this part could be found hereKubernetes YAML configuration
This is the step where we define the K8S components of our application - deployment, service, configmap, ingress.
Since we will have two environments, I use Kustomize here. Kustomize is a Kubernetes-native configuration management tool that allows you to customize raw, template-free base YAML files using overlays, without modifying the original manifests. Overlay will have an environment-specific Spring Boot application properties file that our container application will consume.
The configuration that covers this part could be found hereThe application itself
For this demo I created a simple Spring Boot application that renders a simple html page with the environment name and the application version. The environment name is the thing that comes from the Spring Boot properties file.
The repo that covers this part could be found here
Ok, so that was a lot already. I intentionally don't dive too deep into the implementation of each step above since it would be overwhelming, and wouldn't allow us to focus on the main part of this article - the CI/CD part. But if you're curious - feel free to reach out, I'll be glad to speak on details.
CI part
As long as we speak about K8S we need to build the image that will be hosted there.
There are three main components needed to achieve that:
The Dockerfile
That's the thing that uses the multi-stage build approach where the Build stage does the Maven build and the Run stage launches the application.
You can find it hereECR repository
This image needs to be hosted somewhere. It could be DokerHub, your cloud provider repository, or something else. Because the K8S cluster in my case is placed in AWS, I use ECR service for it.GitHub Actions CI workflow
This is the part that's responsible for building the docker image from our Dockerfile, pushing it to ECR repository, and setting the updated image in the K8S YAML configuration.
Just as a side note - there are many options to automate CI process. Since the code for this project is being stored in GitHub, I decided to use GitHub Actions. You can use the one you're most comfortable with like Jenkins, or even Argo Workflows.
The code for the GitHub Actions workflow could be found here
CD part
Once the docker image is built and the K8S deployment YAML is updated using the GitHub Actions CI workflow from the application repository, ArgoCD comes into action.
We have an application (ArgoCD entity) in it that constantly monitors the changes in the pre-defined path of the IAC repository related to dev overlay and makes sure the actual cluster state is aligned with the configuration in GitHub. So, once the deployment object gets updated, ArgoCD automatically applies these changes, and no administrator action is needed for the dev environment.
Once the code is synced you can open dev-app.put-your-domain-here.com in your browser and see the application environment and version like this:
But do we want to see the same behavior for the prod? Probably, not. That's why use the second workflow placed in the IAC repo here:
That's the workflow that gets an image version as an input and raises the PR to the main branch of IAC repo with the updated image version for the prod overlay. Once the PR is raised, the administrator reviews and approves it. So, the thing that's needed to see these changes in production is to press the SYNC button in the ArgoCD UI.
Once the code is synced you can open prod-app.put-your-domain-here.com in your browser and see the application environment and version like this:
Conclusion
That’s it — we’ve fully automated the CI/CD pipeline for deploying the SpringBoot application to the Kubernetes cluster, using Terraform to spin up the infrastructure in AWS, GitHub Actions for continuous integration, and Argo CD for continuous delivery.
Now, every development build is deployed automatically without manual intervention, while production releases require a pull request review and merge.
Feel free to ask questions, share your experience and suggestions in the comments section below.
Cheers!
The video version of this article could be found here
Top comments (0)