DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Serverless vs Containers: Choosing the Right Architecture for Your Application
  • Container Checkpointing in Kubernetes With a Custom API
  • 7 Ways of Containerizing Your Node.js Application
  • Auto-Scaling a Spring Boot Native App With Nomad

Trending

  • Alternative Structured Concurrency
  • Why Round-Robin Won't Save You: Load Balancing Challenges in Data Streaming Services With Heterogeneous Traffic
  • Testing AI-Infused Apps: A Dual-Layer Framework for AI Quality Assurance
  • The Hidden Cost of AI Tokens: Engineering Patterns for 10x Resource Efficiency
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Deploying a Scalable Golang Application on Kubernetes: A Practical Guide

Deploying a Scalable Golang Application on Kubernetes: A Practical Guide

Learn how to deploy and scale a Golang app on Kubernetes using best practices like stateless design, concurrency, health checks, and autoscaling.

By 
Neel Shah user avatar
Neel Shah
·
Aug. 11, 25 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
3.0K Views

Join the DZone community and get the full member experience.

Join For Free

Golang is the finest programming language for constructing applications that can scale well and at high density due to the concurrency and performance inherent in the language itself. Kubernetes is the best standard for container orchestration, which gives a platform for deploying, managing, and scaling applications. Together, they constitute a formidable pair for creating unobtrusive and bulletproof microservices.

This blog will lead readers through the process of deploying a scalable Golang application on Kubernetes, highlighting essential considerations alongside the more practical 'doing it' steps.

Why Golang and Kubernetes?

Before we go into the how-tos, let's just touch briefly on the whys:

  • With Golang for performance and concurrency: Go's extremely efficient lightweight goroutines and channels enable this concurrency. The fast compilation time and statically linked binaries make deployments easy. 
  • Kubernetes for scalability and resilience: A containerized application can be deployed, scaled, and managed with Kubernetes. It also enables self-healing, load balancing, and rolling updates, ensuring that the application remains up and fully functional even under heavy load.

Key Considerations for Scalability in Golang Applications

The following are certain principles you may wish to consider while designing your application and making the best use of Kubernetes for your Go applications:

  1. Statelessness: The Go application should be designed as stateless, meaning that no session data or persistent state should be stored within the application instances in memory. Instead, all states should be handled by leveraging external services such as databases (Postgres, MongoDB), caching services (Redis, Memcached), or message queues (Kafka, RabbitMQ). This will allow Kubernetes to scale your pods freely without any risk of data loss or data consistency.
  2. Concurrency: Go channels and goroutines should be employed for concurrent processing. This allows one Go instance to spawn multiple requests and thus can truly take advantage of the CPU resources. 
  3. Graceful shutdowns: The Go application must have graceful shutdown logic. On receiving a terminate command from Kubernetes, the application should finish processing ongoing requests and free its resources before exiting. This way, no need for cleanup has to be made to protect against data corruption or dropped connections. Listening to a `SIGTERM` signal is only one common way to implement this.
  4. Configuration: The application will store its configuration externally through environment variables or config files. The application thus becomes highly portable and configurable within Kubernetes without needing to build a new Docker image.
  5. Health checks: Your app should provide HTTP endpoints for liveness and readiness checks. Kubernetes uses these to ascertain whether your application is up and running, ready to handle traffic, and healthy.

Step-by-Step Deployment on Kubernetes

Let's walk through the process with a hypothetical simple Go API.

1. Containerize Your Golang Application

First, you need a `Dockerfile` to package your Go application into a Docker image.

Go
 
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello from Golang App! Pod: %s\n", os.Getenv("HOSTNAME"))
	})

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	server := &http.Server{Addr: ":" + port}

	// Start HTTP server in a goroutine
	go func() {
		log.Printf("Server starting on port %s...", port)
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("Could not listen on %s: %v\n", port, err)
		}
	}()

	// Graceful shutdown
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
	<-sigChan // Block until a signal is received

	log.Println("Shutting down server gracefully...")
	shutdownCtx, cancel := time.WithTimeout(server.Context(), 5*time.Second)
	defer cancel()

	if err := server.Shutdown(shutdownCtx); err != nil {
		log.Fatalf("Server shutdown failed: %v", err)
	}
	log.Println("Server gracefully stopped.")
}


Dockerfile
 
# Use a minimal base image for the build stage
FROM golang:1.22 AS builder

WORKDIR /app

# Copy go mod and sum files to download dependencies
COPY go.mod go.sum ./
RUN go mod download

# Copy the source code
COPY . .

# Build the Go application
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Use a scratch image for the final, very small image
FROM alpine:latest

WORKDIR /root/

# Install ca-certificates for HTTPS calls if needed (optional but recommended)
RUN apk --no-cache add ca-certificates

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

# Expose the port your application listens on
EXPOSE 8080

# Run the executable
CMD ["./main"]


Build and push the Docker images to the registry:

docker build -t your-docker-repo/golang-app:1.0.0 .

docker push your-docker-repo/golang-app:1.0.0

2. Define Kubernetes Manifests

Now, let's create the Kubernetes resource definitions.

A. deployment.yaml

YAML
 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: golang-app-deployment
  labels:
    app: golang-app
spec:
  replicas: 3 # Start with 3 replicas for high availability
  selector:
    matchLabels:
      app: golang-app
  template:
    metadata:
      labels:
        app: golang-app
    spec:
      containers:
      - name: golang-app
        image: your-docker-repo/golang-app:1.0.0 # Replace with your image
        ports:
        - containerPort: 8080
        env:
        - name: PORT
          value: "8080"
        resources: # Define resource requests and limits for better scheduling and stability
          requests:
            memory: "64Mi"
            cpu: "100m" # 100 millicores (0.1 CPU core)
          limits:
            memory: "128Mi"
            cpu: "200m" # 200 millicores (0.2 CPU core)
        livenessProbe: # Checks if the app is still running
          httpGet:
            path: / # Or a dedicated /health endpoint
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        readinessProbe: # Checks if the app is ready to serve traffic
          httpGet:
            path: / # Or a dedicated /ready endpoint
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 15
          timeoutSeconds: 5


B. service.yaml

YAML
 
apiVersion: v1
kind: Service
metadata:
  name: golang-app-service
  labels:
    app: golang-app
spec:
  selector:
    app: golang-app
  ports:
  - protocol: TCP
    port: 80 # The port the service exposes
    targetPort: 8080 # The port your application listens on inside the container
  type: ClusterIP # Exposes the Service on a cluster-internal IP. Default for many apps.


C. Horizontal Pod Autoscaler (hpa.yaml)

YAML
 
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: golang-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: golang-app-deployment
  minReplicas: 3 # Minimum number of pods
  maxReplicas: 10 # Maximum number of pods
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70 # Target CPU utilization (percentage)
  # You can also scale based on memory or custom metrics
  # - type: Resource
  #   resource:
  #     name: memory
  #     target:
  #       type: Utilization
  #       averageUtilization: 80


3. Deploy to Kubernetes

Markdown
 
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f hpa.yaml


Some of the Best tools to monitor your Kubernetes resources are:

  • Grafana
  • Middleware
  • Prometheus
  • FluentD

Conclusion

Scale up a Golang application in Kubernetes to reap its user-friendliness in building modern, resilient, and performance-oriented systems. Ensure that you adopt best practices for Go application design, such as making the application stateless, concurrent, and ensuring graceful shutdowns. You will allow Kubernetes features such as deployments, services, and horizontal pod autoscaling to balance the workload on your application accordingly. Come on, adopt this combination to perfect your microservices architecture!

Golang Kubernetes application Docker (software) Go (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Serverless vs Containers: Choosing the Right Architecture for Your Application
  • Container Checkpointing in Kubernetes With a Custom API
  • 7 Ways of Containerizing Your Node.js Application
  • Auto-Scaling a Spring Boot Native App With Nomad

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook