Deploying a Golang Application to Google Kubernetes Engine

Introduction

In this article, I will guide you through deploying a Golang Application to Google Kubernetes Engine (GKE). Previously, I wrote an article about deploying a NodeJS Application to GKE, which you can refer to for some basic information before continuing.

Steps to Follow

The process is quite similar to deploying a NodeJS Application and includes the following steps:
  1. Create a Golang Application
  2. Build a Docker image
  3. Push the Docker image
  4. Deploy the Docker image to GKE
You will notice that when working with Kubernetes, the main difference is in the step where you build the Docker image. Depending on the application you need to deploy, there are different ways to build the Docker image. However, the common point is that once you build the Docker image, you have completed almost half of the process. This is because the subsequent steps involving Kubernetes are entirely the same.

Detailed Process

1. Create a Golang Application

In this step, you can either use an existing Golang project or create a new one. If you want to use the project I'm using in this article, follow these steps:

Create main module

go mod init main


Next, create a file named `main.go` with the following content:

package main

import (
"net/http"
"time"
"github.com/gin-gonic/gin"
)

func main() {
var (
PORT = ":8080"
TITLE = "Golang Application"
)
r := gin.Default()

r.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"title": TITLE,
"time": time.Now(),
})
})
r.Run(PORT)
}


Next, let's install the packages:

go get

Packages will be saved in the `go.mod` and `go.sum` files.


You can check if the application executes successfully as follows:

go run main.go


2. Build Docker Image  

Create a Dockerfile with the following content:

# build stage
FROM golang:alpine as builder
WORKDIR /builder

# use docker layer cache
COPY go.mod go.sum /builder/

# download dependency
RUN go mod download

COPY . .
RUN go build -o /builder/main main.go

# execute stage
FROM gcr.io/distroless/static
WORKDIR /app
COPY --from=builder /builder/main main

# execute binary file
CMD ["/app/main"]

The Dockerfile content is divided into 2 stages:

  1. Build Stage: This stage is for downloading packages and building the project into a binary file.
  2. Execute Stage: This stage is for creating an environment to execute the binary file. Since the `golang:alpine` Docker image supports the Golang CLI for project operations but has a large volume size, it's better to use `gcr.io/distroless/static` to minimize the Docker image size after building.


Next, create a `.dockerignore` file to ignore any files that should not be copied during the Docker image build process.

To build the image, execute the following command:

docker build . -t golang-app

3. Push Docker Image

To push your Docker image to Google Cloud Artifact Registry, check out this article I mentioned earlier. Alternatively, you can also push it to Docker Hub.

4. Deploy Docker Image to GKE

Now, let's create a cluster with the following command:

# gcloud container clusters create {cluster name} \
# --project {project id} \
# --zone {zone id} \
# --machine-type {machine type}

# ex:
gcloud container clusters create k8s-cluster \
--project project-id \
--zone asia-southeast1-a \
--machine-type e2-micro

Replace the placeholders for the cluster name, project ID, zone, and machine type as needed.

As mentioned earlier, when deploying projects to Kubernetes, the main difference lies in how you build the Docker image, which varies by project type. Once you have the Docker image, the content of the `deployment.yml` file will be similar to the one used for deploying a NodeJS application. You just need to update the image and port information accordingly.

apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-name
labels:
name: label-name
spec:
replicas: 1
selector:
matchLabels:
app: label-name
template:
metadata:
labels:
app: label-name
spec:
restartPolicy: Always
containers:
- name: golang-app
image: gcr.io/{project id}/golang-app # or use image from docker hub
---
apiVersion: v1
kind: Service
metadata:
name: service-name
labels:
service: label-name
spec:
selector:
app: label-name
type: LoadBalancer
ports:
- protocol: TCP
port: 80 # port service
targetPort: 8080 # port pod


After that, apply to initialize the resources:




Wait a moment to check that the pod, service, and deployment have been successfully created:



Then, access the EXTERNAL-IP of the LoadBalancer to see the results.



To delete the resources, use the following command:


Happy coding!

Comments

Popular posts from this blog

Kubernetes Practice Series

NodeJS Practice Series

Docker Practice Series

React Practice Series

Sitemap

Deploying a NodeJS Server on Google Kubernetes Engine

Setting up Kubernetes Dashboard with Kind

DevOps Practice Series

A Handy Guide to Using Dynamic Import in JavaScript

Create API Gateway with fast-gateway