Dhananjay.blog

Recipes for Java, Golang on Kubernetes and more.

Menu
  • Home
  • About
Menu

Go MicroService in Gin using Helm On k8s

Posted on December 12, 2022

In this article we will develop a template micro service written in go using gin which can run on Kubernetes.

Go with gingonic on Kubernetes

Pre-Requisites:

Please make sure you have the following setup before proceeding :

  1. helm
  2. A Kubernetes flavor is accessible, it can either be a local setup via Minikube, Docker Desktop, or even a cloud-based setup using GKE or EKS. This article will mostly focus on using Docker Desktop to demonstrate, but the configuration and the setup should stay the same across all Kubernetes flavors. 
  3. IDE for ease of use, you can use any editor as long as golfing is supported. This tutorial uses GoLand IDE from Jet-brains
  4. kubectl CLI . 
  5. Go Latest Stable Version installed.

Create a Template Application using Gin and Golang

Create a folder microservice-template and run the following command under it

go get -u github.com/gin-gonic/gin

This will install gin onto your local project including setting up imports within go.mod file, once done it should look like this:

module template
go 1.19

require github.com/gin-gonic/gin v1.8.1

require (
	github.com/gin-contrib/sse v0.1.0 // indirect
	github.com/go-playground/locales v0.14.0 // indirect
	github.com/go-playground/universal-translator v0.18.0 // indirect
	github.com/go-playground/validator/v10 v10.11.1 // indirect
	github.com/goccy/go-json v0.9.11 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/leodido/go-urn v1.2.1 // indirect
	github.com/mattn/go-isatty v0.0.16 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
	github.com/ugorji/go/codec v1.2.7 // indirect
	golang.org/x/crypto v0.3.0 // indirect
	golang.org/x/net v0.2.0 // indirect
	golang.org/x/sys v0.2.0 // indirect
	golang.org/x/text v0.4.0 // indirect
	google.golang.org/protobuf v1.28.1 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
)

Next up, we can import it to our projects main.go file by importing gin for e.g. import "github.com/gin-gonic/gin"

Now create a file called main.go within the folder microservice-template with the following code:

package main
import (
	"github.com/gin-gonic/gin"
	"net/http"
)
func main() {
	r := gin.Default()
	r.GET("/health", healthCheck)
	r.GET("/test", sampleApi)
	r.Run("0.0.0.0:8080")
}
func sampleApi(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"test": "ok"})
}
func healthCheck(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"status": "ok"})
}

The above code imports the installed gin framework to your project and then creates two apis /health and /test using gin framework with separate handlers for each. The intent here is to demonstrate how to package this go program to run in k8s. In future posts I will try to add more advanced used cases of routing than the one above.

Now build and run the above program to ensure its working as intended, run the following command inside micro service-template folder

$ go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /health                   --> main.healthCheck (3 handlers)
[GIN-debug] GET    /test                     --> main.sampleApi (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on 0.0.0.0:8080

Now to test our apis we can just hit the endpoints using curl:

$ curl http://localhost:8080/health
{"status":"ok"}
$ curl http://localhost:8080/test
{"test":"ok"}

Create DockerFile for the Go program

Next step is to package our go application to a container image. Create a Dockerfile within the root directory of the application to package this program into a OCI compliant container image. This image we will use later in the helm chart to deploy to kubenertes. Here is the Dockerfile:

FROM golang:1.19-alpine
#Define Work Dir for all image files to be built
WORKDIR /app
#Install Necessary Modules
COPY go.mod ./
COPY go.sum ./
# This installs all go modules needed. 
RUN go mod download
# Copy Source Files to work dir
COPY *.go ./
# Creates an executable in the root folder
RUN go build -o /ms-template
EXPOSE 8080
CMD [ "/ms-template" ]

The above structure of dockerfile is explained in much more detail here.

Create Image and Push to Local Docker Registry

In this step we will create a docker image using the above Dockerfile and push to a Docker compliant registry. In this article we will be using Docker Desktop to demonstrate, but in practice it’s recommended to use something like docker hub, GCR etc.

Build the image using the following command within the directory where Dockerfile is, in this case its our root application directory.

$ docker build -t ms-template:0.1 .
[+] Building 47.1s (12/12) FINISHED
$ docker image ls ms-template
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
ms-template   latest    bf9d234a7885   41 seconds ago   530MB

The image is created successfully, next up we will create a helm chart which will use the image created above.

Create and Configure Helm Chart

We are just going to use the base generated helm chart for our application, as its pretty straightforward. Generate a base helm chart using the following command:

helm create ms-template

Next up we will make changes similar to this post, where we will configure this helm chart to add relevant details such as health check urls and image repository. The following files needs to be updated:

  • deployment.yaml : Add readiness and liveness check urls and update port numbers
  • values.yaml: modify Service type to LoadBalancer and add image name
  • chart.yaml: update the tag to reflect the image tag.

Deploy on Local Kubernetes

Almost done, now just navigate to the directly where the root folder of helm chart is and install the chart on your local Kubernetes cluster

$ helm install ms-template ms-template
NAME: ms-template
LAST DEPLOYED: Sun Dec 11 13:31:10 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get --namespace default svc -w ms-template'
  export SERVICE_IP=$(kubectl get svc --namespace default ms-template --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
  echo http://$SERVICE_IP:8080

After a few seconds the pods will start up and will be ready to receive traffic

$ kubectl get pods
NAME                           READY   STATUS    RESTARTS   AGE
ms-template-5bbc7c448c-j9nnv   1/1     Running   0          5s

$ kubectl get service ms-template
NAME          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          
ms-template   LoadBalancer   10.104.150.21   localhost     8080:32048/TCP 

$ curl http://localhost:8080/test
{"test":"ok"}
$ curl http://localhost:8080/health
{"status":"ok"}

Troubleshooting

Troubleshooting any failure or issues is similar to how you would do it for other Kubernetes workloads. Here are some tips on easy starting over

  1. If something goes wrong in helm and you want to start over just delete the chart by running helm delete ms-template
  2. YAML is very sensitive to indentation, so please ensure that the indentation is proper.
  3. if all else fails you can still download the code from the GitHub repo and try comparing it with your setup

The entire source code for this post is available here.

Further Reading

  • Go
  • Gin Gonic
  • Helm

Categories

  • GO
  • Home
  • Java
  • K8s and More
  • Programming
  • Software

Tags

Container Image Docker gingonic go helm jib kafka kubernetes microservices springboot spring cloud config tdd test driven development unit testing

Recent Posts

  • Unit Testing Checklist
  • ConfigMap Custom Watcher with SpringBoot
  • Go Service Configuration with k8s ConfigMaps
  • Go MicroService in Gin using Helm On k8s
  • Container Image Reducing Size with Jib

Archives

  • March 2025
  • January 2023
  • December 2022
  • September 2022
  • August 2022

Categories

  • GO
  • Home
  • Java
  • K8s and More
  • Programming
  • Software

About

  • Privacy
  • Terms of Service
  • About
  • Contact
@2024 Dhananajay on Tech