Skip to content

Go-PostgreSQL app containerization and deployment on Kubernetes

Notifications You must be signed in to change notification settings

ayushgml/my-book-app

Repository files navigation


My Book App

Go-PostgreSQL app containerization and deployment on Kubernetes

About The Project

This project is a Go backend API with PostgreSQL as the database. The app is containerized using Docker and deployed on Kubernetes. The app is deployed on a single node cluster using Civo cloud(you can use minikube if you want. I have shown both ways!). The app is exposed using the LoadBalancer service of my-app. Following tech is used in the project:

  • Go
  • PostgreSQL
  • Docker
  • Kubernetes
  • YAML

Prequisites:

  • Docker installed on the host machine
  • Minikube installed on the host machine(If you want to run on your local machine instead of cloud)
  • Some knowledge about YAML (you can learn that from here)
  • Some knowledge about Kubernetes (you can learn that from here)
  • A cloud Provider account such as AWS, Civo, Azure, Google cloud etc. (I am using Civo in this project). This is only if you want to deploy your cluster on cloud.

Project Structure

.
├── Dockerfile
├── README.md
├── api
│   └── book_handler.go
├── cmd
│   └── main.go
├── deployment.yaml
├── go.mod
├── go.sum
├── ingress.yaml
├── internal
│   ├── book
│   │   └── book.go
│   └── student
│       └── student.go
├── postgres-config.yaml
├── postgres-deployment.yaml
├── postgres-service.yaml
├── postgres-storage.yaml
├── service.yaml
└── storage
    └── book_repository.go

Architecture

architecture

The API request goes to ingress controller which then forwards the request to my-app service. The service then forwards the request to the my-app pod. The image for the pod is being pulled from Dockerhub. The pod then connects to the PostgreSQL database which is also running in a pod. The database is also running in a pod and the image is being pulled from Dockerhub. The database pod is connected to a persistent volume which is used to store the data. The persistent volume is connected to a persistent volume claim which is used to claim the storage from the persistent volume. The persistent volume claim is connected to the database pod. The database pod is connected to a service which is used to expose the database pod to the my-app pod.

Installation

  1. Clone the repo

    git clone https://github.com/ayushgml/my-book-app.git
    cd my-book-app
  2. Make sure minkube and docker and installed and running on the host machine

    minikube start
  3. Now run the following commands

     kubectl apply -f postgres-config.yaml
     kubectl apply -f postgres-storage.yaml
     kubectl apply -f postgres-deployment.yaml
     kubectl apply -f postgres-service.yaml
     kubectl apply -f deployment.yaml
     kubectl apply -f service.yaml
     kubectl apply -f ingress.yaml
    

    The state of the cluster should look like this(if you are deploying using minikube):

  4. Now if you encounter any errors then you can run the following command to check the logs of the pod

    kubectl logs <pod-name>
    

    Or you can describe the pod to check the status of the pod

    kubectl describe pod <pod-name>
    

Running on cloud

  1. Now I deployed it on Civo cloud(because I found it cheaper to deploy on that). So I had to create a firewall rule to allow traffic on port 8080(it may be on by default). You can do the same on your cloud provider. If you are using Minikube then you can stop here. I downloaded the kubeconfig file from Civo(you can download from your cloud provider cluster) and then ran the following command to connect to the cluster.

    kubectl config use-context civo-cluster
    
  2. Now you need to make a change from NodePort to LoadBalancer in the service.yaml file. Then run the following command Before:

    spec:
    selector:
    app: my-app
    ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
    type: NodePort         # <--- For minkube
    

    After:

    
    spec:
    selector:
    app: my-app
    ports: - protocol: TCP
    port: 8080
    targetPort: 8080
    type: LoadBalancer     # <--- For cloud providers
    
    

    Then run the following command

    
    kubectl apply -f service.yaml
    

    Reason for using NodePort in minkube is that there is no LoadBalancer integrated (unlike AWS or Google Cloud). With this default setup, you can only use NodePort or an Ingress Controller. When using cloud providers, you can use LoadBalancer.

  3. Now run kubectl get all to get the IP address of the LoadBalancer. Now you can send requests to the IP address of the LoadBalancer. Send the request to the external-ip address of the LoadBalancer on port 8080. You can use Postman/Thunderclient/cURL to send the requests.

    cloud provider screenshot

Cluster graph

The below graph is made with Monokle graph view of default namespace with depth=5 from Persistent Volume Claim.

Continuous Integration

I used github Actions to build and push the docker image to Dockerhub. The workflow is triggered when a push is made to the main branch. The workflow is defined in the .github/workflows folder. The workflow is defined in the docker-image.yml file. The file is shown below:

name: Docker Image CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Build the Docker image
      run: docker build . --file Dockerfile --tag ayushgml/my-book-app-image:latest

    - name: Log in to Docker Hub
      run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASS }}

    - name: Push the Docker image
      run: docker push ayushgml/my-book-app-image:latest

Make sure you add DOCKERHUB_USERNAME and DOCKERHUB_PASS in the secrets section of the repository settings. You can get the username and password from Dockerhub.

Contact

Ayush Gupta - @itsayush__ - [email protected]

Project link

About

Go-PostgreSQL app containerization and deployment on Kubernetes

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published