Deploying a Go Application with NATS Messaging on Kubernetes
Tags: go, kubernetes, docker, tutorial
Published: 2023-05-30 06:17:52

We will go through the step-by-step process, from writing the deployment YAML files to building the Docker image and finally deploying the application on Kubernetes.
Prerequisites

Before we begin, make sure you have the following prerequisites in 

[Docker](https://docs.docker.com/engine/install/) installed on your machine.
[Minikube](https://minikube.sigs.k8s.io/docs/start/) and [kubectl](https://kubernetes.io/docs/tasks/tools/) installed for setting up a local Kubernetes cluster.

## Step 1

> Writing the Deployment YAML Files

To start, we need to define the deployment YAML files for our Go application and NATS messaging system. Let’s create the following YAML files:

> 1. app-deployment.yaml:


```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-go-img-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-go
  template:
    metadata:
      labels:
        app: app-go
    spec:
      containers:
        - name: app-go-container
          image: app-go
          imagePullPolicy: Never
          ports:
            - containerPort: 8080
```

> 2. nats-deployment.yaml:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nats
spec:
  replicas: 1
  strategy: {}
  selector:
    matchLabels:
      app: nats
  template:
    metadata:
      labels:
        app: nats
    spec:
      containers:
        - name: nats
          image: nats:2.7.0-alpine
          ports:
            - containerPort: 4222
              targetPort: 4222
```

> 3. nats-service.yaml:

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nats-service
spec:
  selector:
    app: nats
  ports:
    - name: client
      port: 4222
      targetPort: 4222
      protocol: TCP
```

## Step 2

> Writing the Go Application Code

Next, we need to write the code for our Go application. Create a file named main.go and add the following code:

```go
package main

import (
 "fmt"
 "log"
 "os"
 "time"

 "github.com/nats-io/nats.go"
)

func main() {

 url := os.Getenv("NATS_URL")
 if url == "" {
  url = nats.DefaultURL

  // url = "nats://nats-service.default.svc.cluster.local:4222"
  // works fine in case of interpod communication

  // another way is to use the service-url directly
  url = "nats-service:4222"
 }

 nc, err := nats.Connect(url)
 if err != nil {
  log.Fatalln(err)
 }

 defer nc.Drain()

 nc.Publish("greet.joe", []byte("hello"))

 sub, _ := nc.SubscribeSync("greet.*")

 msg, _ := sub.NextMsg(10 * time.Millisecond)
 fmt.Println("subscribed after a publish...")
 fmt.Printf("msg is nil? %v\n", msg == nil)

 nc.Publish("greet.joe", []byte("hello"))
 nc.Publish("greet.pam", []byte("hello"))

 msg, _ = sub.NextMsg(10 * time.Millisecond)
 fmt.Printf("msg data: %q on subject %q\n", string(msg.Data), msg.Subject)

 msg, _ = sub.NextMsg(10 * time.Millisecond)
 fmt.Printf("msg data: %q on subject %q\n", string(msg.Data), msg.Subject)

 nc.Publish("greet.bob", []byte("hello"))

 msg, _ = sub.NextMsg(10 * time.Millisecond)
 fmt.Printf("msg data: %q on subject %q\n", string(msg.Data), msg.Subject)


}
```

This code connects to the NATS messaging system, publishes and subscribes to messages, and demonstrates basic functionality.
Step 3

## Building the Docker Image

Now, let’s build the Docker image for our Go application. We will use a multi-stage Dockerfile to ensure a lightweight and optimized image. Create a file named Dockerfile and add the following code:

```yaml
### Stage 1: Build the Go binary
FROM golang:1.17 AS builder

### Set the working directory inside the container
WORKDIR /app

### Copy the Go modules files and download dependencies

COPY go.mod go.sum ./
RUN go mod download


### Copy the application source code to the container
COPY . .

### Build the Go application

RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Stage 2: Create the final image
FROM alpine:latest

# Set the working directory inside the container
WORKDIR /app

# Copy the Go binary from the builder stage
COPY --from=builder /app/main .

# Expose the port that the application listens on
EXPOSE 8080

# Define the command to run the application when the container starts
CMD ["./main"]
```

To build the image on a Mac, execute the following command:

```shell
docker buildx build --platform linux/amd64 -t app-go-container .
```

After doing everything, your folder structure should look like this
## Step 4

> Deploying the Application on Kubernetes

With our Docker image ready, let’s deploy the application on Kubernetes using Minikube.

Ensure Minikube is running by executing the following command:

```shell
minikube start
```

Next, load the Docker image into Minikube’s image repository:

```shell
minikube image load app-go-container
```

Finally, apply the deployment and service YAML files to create the necessary resources on Kubernetes:

```shell
kubectl apply -f app-deployment.yaml
kubectl apply -f nats-deployment.yaml
kubectl apply -f nats-service.yaml
```

## Conclusion

In this article, we have walked through the process of deploying a Go application with NATS messaging on Kubernetes.

We covered writing the deployment YAML files, writing the Go application code, building the Docker image, and deploying the application on Kubernetes using Minikube.

By following these steps, you can easily deploy your Go application with NATS messaging on a Kubernetes cluster, leveraging the power of containerization and orchestration.

Feel free to customize the configurations and expand upon the concepts covered here to suit your specific needs.

Happy coding and deploying!

## Newsletter

If you like my content, then consider subscribing to my free newsletter, to get exclusive, educational, technical, interesting and career related content directly delivered to your inbox

> https://dsysd.beehiiv.com/subscribe

## Important Links

Thanks for reading the post, be sure to follow the links below for even more awesome content in the future.

Twitter: https://twitter.com/dsysd_dev
Youtube: https://www.youtube.com/@dsysd-dev
Github: https://github.com/dsysd-dev
Medium: https://medium.com/@dsysd-dev
Email: dsysd.mail@gmail.com
Linkedin: https://www.linkedin.com/in/dsysd-dev/
Newsletter: https://dsysd.beehiiv.com/subscribe
Gumroad: https://dsysd.gumroad.com/