How to Deploy a Go Web App on AWS EKS Using CI/CD with GitHub Actions and More


Introduction
In this blog post, Iโll walk you through the process of deploying a Go web application on an Amazon EKS cluster using Docker, Helm, and ArgoCD. We'll also set up a CI/CD pipeline with GitHub Actions to automate the deployment process.
This project was inspired by Abhishek Veermalla, whose tutorial helped me navigate through these technologies. ๐
GitHub repository (VishuPatel-27).
Prerequisites
Before we dive into the steps, make sure you have the following tools installed:
Go (1.22 or later)
Docker
Kubernetes (kubectl)
AWS CLI
eksctl (for EKS cluster management)
Helm
ArgoCD
GitHub Actions (for CI/CD automation)
Step-by-Step Implementation
Step 1: Clone the Go Web Application
First, we clone the Go web application from the GitHub repository:
git clone https://github.com/iam-veeramalla/go-web-app.git
cd go-web-app
Step 2: Containerizing the Application
Next, we create a multi-stage Dockerfile to build and package our Go web app efficiently.
Hereโs a Dockerfile:
# we are using golang image to build our application
FROM golang:1.22 AS builder
# Set the Current Working Directory inside the container
WORKDIR /app
# Copy go mod
COPY . .
# Download all dependencies. Dependencies will be cached if the go.mod is not changed
RUN go mod download
# Build the Go app
RUN go build -o main .
# Start a new stage from scratch
FROM gcr.io/distroless/base
# Copy the Pre-built binary file from the previous stage
COPY --from=builder /app/main .
# Copy the static files
COPY --from=builder /app/static /static
# expose the port on which the application will run
EXPOSE 8080
# Command to run the executable
CMD ["./main"]
Step 3: Run the Docker Image Locally
To verify our Docker image, we build and run it locally:
docker build -t go-webapp:v1.0 .
docker run -p 8080:8080 go-webapp:v1.0
Check if the app is accessible at http://localhost:8080/courses
.
Step 4: Push the Docker Image to Docker Hub
Once verified, push the image to Docker Hub:
docker tag go-webapp:v1.0 <your-dockerhub-username>/go-webapp:v1
docker push <your-dockerhub-username>/go-webapp:v1
Step 5: Create Kubernetes Manifests
We create three K8s manifest files:
deployment.yaml: Defines how the app is deployed.
service.yaml: Exposes the app internally.
ingress.yaml: Handles external traffic routing.
Apply the manifests later when the cluster is ready.
Step 6: Create an EKS Cluster
We use eksctl to set up an EKS cluster with a single t2.medium instance:
eksctl create cluster --name go-webapp-cluster \
--region us-east-1 \
--nodegroup-name go-webapp-ng \
--node-type t2.medium \
--nodes 1
Step 7: Install the Nginx Controller and Configure DNS
To manage incoming traffic, we install the Nginx Ingress Controller:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml
Then, configure the local DNS record for the app.
How to Add a Custom DNS Record to Your Hosts File
In this guide, I'll show you how to map the domain go-webapp.local
to the IP address of nginx controller by editing your host file. This is especially useful for local development and testing environments. Follow the step-by-step instructions below for both Windows and Ubuntu.
This Nginx controller on the EKS cluster is basically a network load balancer. You can find this IP address by using the command kubectl get all -o wide -n ingress-nginx
or kubectl get ingress
. After that, take that IP address and run this command nslookup <ip-address>
on your terminal, and you will get the IP address of the Nginx controller.
For Windows
Open Notepad as Administrator:
Click the Start menu, search for
Notepad
, right-click the app, and choose Run as administrator.Accept the UAC prompt if it appears.
Open the Hosts File:
In Notepad, go to File > Open.
Navigate to:
C:\Windows\System32\drivers\etc\
Change the file type to All Files (.) at the bottom right, then select the file named
hosts
and click Open.
Add Your DNS Record:
Scroll to the bottom of the file and add the following line:
<ip-address> go-webapp.local
Ensure a space or tab between the IP address and the domain.
Save the File:
- Click File > Save and then close Notepad.
Flush the DNS Cache (Optional but Recommended):
Open Command Prompt as Administrator (search for
cmd
, right-click, and select Run as administrator).Run the following command:
ipconfig /flushdns
Press Enter to ensure your system uses the updated DNS settings immediately.
For Ubuntu
Open the Terminal:
- Press
Ctrl+Alt+T
to launch the Terminal.
- Press
Edit the Hosts File:
Use your favourite text editor. For example, with
nano
, type:sudo nano /etc/hosts
Enter your password if prompted.
Insert the DNS Record:
Scroll down to the bottom of the file and add:
<ip-address> go-webapp.local
Ensure at least one space or tab between the IP address and the domain.
Save and Exit:
- If using
nano
, pressCtrl+O
to save (confirm with Enter) and thenCtrl+X
to exit.
- If using
Flush the DNS Cache (If Needed):
While Ubuntu usually applies changes to the hosts file immediately, if youโre using a DNS cache (like
systemd-resolved
), restart it with:sudo systemctl restart systemd-resolved
Alternatively, a reboot will also apply the changes.
Verification
To ensure everything is set up correctly, open a terminal (or Command Prompt on Windows) and run:
ping go-webapp.local
Step 8: Deploy the Application on EKS Using K8s Manifests
Now, we deploy our application using the created Kubernetes manifests. This step is completely optional. If you want to verify the deployment, then you can definitely go with this step.
kubectl apply -f k8s/manifests/
Verify the deployment:
kubectl get pods -n default
Step 9: Deploy Using Helm Charts
To simplify deployment, we create a Helm chart and deploy it (make sure you remove the previous deployment that you deployed using the k8โs manifests):
helm install go-webapp-stack -n go-webapp-ns . -f values.yaml --create-namespace
Verification:
Go to your favourite browser and access the application on go-webapp.local/courses
.
Step 10: Set Up CI/CD Pipeline with GitHub Actions
We define a GitHub Actions workflow (.github/workflows/ci.yaml
) to automate builds, tests, and deployments.
# CI using the gihub actions
# name of the workflow
name: CI - GitHub Actions
# when the workflow should be triggered
on:
push:
branches:
- main
# paths to ignore
paths-ignore:
- README.md
- helm/**
# jobs that will be executed
jobs:
# job name
build:
# runs on ubuntu-latest
runs-on: ubuntu-latest
# steps to be executed
steps:
# checkout the repository
- name: Checkout repository
uses: actions/checkout@v4
# setup go
- name: Setup Go
uses: actions/setup-go@v2
with: # arguments for the action
go-version: 1.22
# build the application
- name: Build
run: go build -o go-webapp .
# run the tests
- name: Unit tests
# run the tests in all possible directories
# ./... means all possible directories
run: go test ./...
# static code analysis
code-quality:
# defined the runner for the job
runs-on: ubuntu-latest
# steps to be executed
steps:
# checkout the repository
- name: Checkout repository
uses: actions/checkout@v4
# static code analysis
- name: static code analysis
uses: golangci/golangci-lint-action@v6
with:
version: latest
# build and push the docker image
docker:
# defined the runner for the job
runs-on: ubuntu-latest
# need build job to complete before this job starts
needs: build
# steps to be executed
steps:
# checkout the repository
- name: Checkout repository
uses: actions/checkout@v4
# login to docker hub
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
# docker hub username and password
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# we are using public docker registry
# that is why we don't need to login to the docker registry
# build the docker image
- name: Build Docker image
run: docker build -t go-webapp:${{ github.run_id }} .
# tag the docker image
- name: Tag Docker image
# tag the image with the github sha
# e.g. <docker-hub-username>/go-webapp:<github.run_id>
run: docker tag go-webapp:${{ github.run_id }} ${{ secrets.DOCKER_USERNAME }}/go-webapp:${{ github.run_id }}
# push the docker image
- name: Push Docker image
run: docker push ${{ secrets.DOCKER_USERNAME }}/go-webapp:${{ github.run_id }}
update-helm-chart:
# defined the runner for the job
runs-on: ubuntu-latest
# need build job to complete before this job starts
needs: docker
# steps
steps:
# checkout the repository
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.TOKEN }}
# update the helm chart
- name: Update Helm chart
# sed [OPTIONS] 'SCRIPT' [INPUTFILE...]
# -i: edit files in place
#replace the tag in the values.yaml file
run: |
sed -i 's/tag: .*/tag: "${{ github.run_id }}"/' helm/go-webapp-helm/values.yaml
# push the changes to the repository
- name: Push changes
run: |
git config --global user.email ${{ secrets.EMAIL }}
git config --global user.name "${{ secrets.NAME }}"
git add helm/go-webapp-helm/values.yaml
git commit -m "Update helm chart"
git push
Push this file to the repo to trigger the pipeline.
Step 11: Install and Configure ArgoCD
ArgoCD ensures that our EKS deployments stay in sync with GitHub. Install ArgoCD:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Step 12: Verify ArgoCD Auto-Deployment
Now, edit values.yaml
file in the repo and commit the changes. ArgoCD will automatically detect and deploy the changes.
Check the deployment status:
kubectl get applications -n argocd
Conclusion
Following these steps, we successfully deployed a Go web application on AWS EKS using Docker, Kubernetes, Helm, and ArgoCD. ๐
Key Takeaways:
CI/CD automation ensures seamless deployments.
Helm charts simplify application deployment.
ArgoCD enables GitOps, making deployments predictable and manageable.
Thanks again to Abhishek Veermalla, Sir, for his amazing content that helped me build this project! ๐
๐ฌ Have questions or feedback? Drop them in the comments! ๐
#GoLang #Kubernetes #AWS #EKS #Docker #CI/CD #Helm #ArgoCD #GitOps #DevOps #CloudComputing
Subscribe to my newsletter
Read articles from Vishukumar Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Vishukumar Patel
Vishukumar Patel
Hi there! Iโm a DevOps enthusiast, certified in AWS, and passionate about crafting innovative cloud solutions. From designing scalable CI/CD pipelines to deploying microservices on cloud platforms, Iโve immersed myself in transforming ideas into impactful technologies.