Deploying a Go Application with NATS Messaging on Kubernetes
Dsysd Dev
Posted on May 30, 2023
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 installed on your machine.
Minikube and kubectl 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:
- app-deployment.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
- nats-deployment.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
- nats-service.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:
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:
### 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:
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:
minikube start
Next, load the Docker image into Minikube’s image repository:
minikube image load app-go-container
Finally, apply the deployment and service YAML files to create the necessary resources on Kubernetes:
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
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/
Posted on May 30, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.