The Go DevOps Way: A Step-by-Step Guide to Building, Deploying, and Managing Scalable and Reliable Go Applications with GitHub Actions and Helm
Kundan Antyakula
DevSecOps | AWS Certified (2x) | GitHub Certified (1x) | Kubernetes & Containerization | CI/CD & Infrastructure Automation | Driving Secure & Scalable DevOps Solutions
Outline: End-to-End DevOps Project Explained
Introduction
In today's fast-paced software development landscape, DevOps has emerged as a critical practice for streamlining the development, deployment, and management of applications. This article walks you through an end-to-end DevOps project, breaking down complex concepts into manageable steps. Whether you're a beginner or an experienced developer, this guide aims to make advanced DevOps techniques accessible and understandable.
Running the Application Locally
Before diving into the complexities of containerization and orchestration, let's start by running the application locally.
Building the Application Locally
To build the application, use the Go build command:
go build -o kunbin .
The -o flag specifies the output binary name as kunbin.
Executing Go Binary
Run the built binary with:
./kunbin
Accessing the Application on a Web Browser
Open your web browser and navigate to:
https://localhost:8080/courses
This URL allows you to access the locally running application.
Containerizing with Docker
Next, we'll containerize our application using Docker. This process involves writing a Dockerfile, which contains instructions for building the Docker image.
Writing a Dockerfile
Here's an example Dockerfile for our Go application:
FROM golang:1.22.5 as base
WORKDIR /app
COPY go.mod .
RUN go mod download
COPY . .
RUN go build -o kunbin .
FROM gcr.io/distroless/base
COPY --from=base /app/kunbin .
COPY --from=base /app/static ./static
EXPOSE 8080
CMD ["./kunbin"]
This Dockerfile uses a multi-stage build to optimize the image size and security. The first stage builds the application, and the second stage uses a minimal distroless image.
Building and Running the Docker Image
Build the Docker image with:
docker build -t kundanty/go-web-app:v1 .
Run the Docker container:
docker run -p 8080:8080 -it kundanty/go-web-app:v1
Understanding Dockerfile Instructions
Creating Kubernetes Manifests
To deploy our containerized application, we'll create Kubernetes manifests, including deployment, service, and ingress resources.
Deployment Manifest (deployment.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-web-app
labels:
app: go-web-app
spec:
replicas: 1
selector:
matchLabels:
app: go-web-app
template:
metadata:
labels:
app: go-web-app
spec:
containers:
- name: go-web-app
image: kundanty/go-web-app:v1
ports:
- containerPort: 8080
Service Manifest (service.yaml)
apiVersion: v1
kind: Service
metadata:
name: go-web-app
spec:
type: ClusterIP
selector:
app: go-web-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
Ingress Manifest (ingress.yaml)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: go-web-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: go-web-app.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: go-web-app
port:
number: 80
Setting Up Kubernetes Cluster with EKS
To manage our Kubernetes cluster, we'll use Amazon EKS.
Creating EKS Cluster Using eksctl
Create a cluster with:
eksctl create cluster --name demo-cluster --region us-east-1 --nodes 1 --node-type t3.small --managed
领英推荐
Applying Kubernetes Manifests
Deploy the manifests to the cluster:
kubectl apply -f k8s/manifests/deployment.yaml
kubectl apply -f k8s/manifests/service.yaml
kubectl apply -f k8s/manifests/ingress.yaml
Configuring Ingress Controller and Load Balancer
To route external traffic to our services, we'll configure an Ingress controller.
Installing NGINX Ingress Controller
Install NGINX Ingress Controller with:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.1/deploy/static/provider/aws/deploy.yaml
Exposing the Service through Ingress
Once the Ingress controller is set up, you can expose your services through DNS mapping.
Helm Chart for Application
Helm simplifies managing Kubernetes applications by using charts, which are packages of pre-configured Kubernetes resources.
Creating and Configuring Helm Chart
Create a Helm chart:
helm create go-web-app-chart
Using Values.yaml for Environment Configuration
Customize the values.yaml file for different environments.
replicaCount: 1
image:
repository: kundanty/go-web-app
pullPolicy: IfNotPresent
tag: "v1"
ingress:
enabled: false
className: ""
annotations: {}
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
Continuous Integration with GitHub Actions
Automate your build, test, and deployment processes with GitHub Actions.
Setting Up CI Workflow
Create a workflow file .github/workflows/ci.yaml:
name: CI/CD
on:
push:
branches:
- main
paths-ignore:
- 'helm/**'
- 'k8s/**'
- 'README.md'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Go 1.22
uses: actions/setup-go@v2
with:
go-version: 1.22
- name: Build
run: go build -o go-web-app
- name: Test
run: go test ./...
code-quality:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.56.2
push:
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push action
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/go-web-app:${{github.run_id}}
update-newtag-in-helm-chart:
runs-on: ubuntu-latest
needs: push
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.TOKEN }}
- name: Update tag in Helm chart
run: |
sed -i 's/tag: .*/tag: "${{github.run_id}}"/' helm/go-web-app-chart/values.yaml
- name: Commit and push changes
run: |
git config --global user.email "[email protected]"
git config --global user.name "Your Name"
git add helm/go-web-app-chart/values.yaml
git commit -m "Update tag in Helm chart"
git push
Continuous Deployment with ArgoCD
ArgoCD automates the deployment of your applications.
To optimize costs, we initially set up a single node for our ArgoCD deployment. However, to increase the capacity of our nodes and allow ArgoCD pods to run as intended, we need to update the EKS compute minimum capacity to 2, desired capacity to 3, and maximum capacity to 4. This change will enable us to scale our nodes and ensure that our ArgoCD deployment can run smoothly and efficiently.
Installing and Configuring ArgoCD
Install ArgoCD:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Setting Up Automatic Deployment
Access ArgoCD UI and configure your application to automatically deploy updates.
Troubleshooting and Common Commands
Here are some essential kubectl commands and tips for troubleshooting:
Conclusion
In this article, we've covered the entire lifecycle of a DevOps project, from running a local application to containerizing it, deploying it on Kubernetes, and setting up CI/CD pipelines. Implementing these practices ensures a smooth and efficient development process, allowing for rapid iteration and deployment.
FAQs
What is the importance of multi-stage Docker builds? Multi-stage Docker builds reduce the final image size and improve security by only including necessary files and dependencies in the final image.
How does an Ingress controller enhance Kubernetes deployment? Ingress controllers manage external access to the services in a Kubernetes cluster, routing traffic to the appropriate services based on rules defined in Ingress resources.
What is the role of Helm in managing Kubernetes applications? Helm simplifies the management of Kubernetes applications by using charts, which package multiple Kubernetes resources and configurations into a single, reusable unit.
How do GitHub Actions integrate with ArgoCD? GitHub Actions automate the CI pipeline, building and testing code, creating Docker images, and updating Helm charts, while ArgoCD automates the CD pipeline, deploying the latest Helm charts to the Kubernetes cluster.
What are common issues faced during Kubernetes deployment? Common issues include misconfigured manifests, resource limits, and permissions errors. Effective troubleshooting often involves inspecting logs, resource descriptions, and events using kubectl commands.
Check out the Code: For a deeper dive into the code, please visit GitHub repository at https://github.com/KundanAntyakula/go-web-app-devops.git