The Go DevOps Way: A Step-by-Step Guide to Building, Deploying, and Managing Scalable and Reliable Go Applications with GitHub Actions and Helm

The Go DevOps Way: A Step-by-Step Guide to Building, Deploying, and Managing Scalable and Reliable Go Applications with GitHub Actions and Helm

Outline: End-to-End DevOps Project Explained

  1. Introduction
  2. Running the Application Locally
  3. Containerizing with Docker
  4. Creating Kubernetes Manifests
  5. Setting Up Kubernetes Cluster with EKS
  6. Configuring Ingress Controller and Load Balancer
  7. Helm Chart for Application
  8. Continuous Integration with GitHub Actions
  9. Continuous Deployment with ArgoCD
  10. Troubleshooting and Common Commands
  11. Conclusion
  12. FAQs



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

  • FROM: Sets the base image.
  • COPY: Copies files from the host machine to the Docker image.
  • RUN: Executes commands inside the Docker image.
  • EXPOSE: Exposes a port.
  • CMD: Specifies the command to run the application.

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        


Login and Create New ArgoCD App

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:

  • Get all resources: kubectl get all
  • Describe a pod: kubectl describe pod <podname>
  • View pod logs: kubectl logs <podname>

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

要查看或添加评论,请登录

社区洞察

其他会员也浏览了