FREE Palestine 🇵🇸#Stop Genocide Now!

☸ Gophernetes: Deploy or Cry
-- K8s + Go and Ingress

Deploy Golang servers with K8s and Ingress.

alt img

Intro

Deploying Golang applications with Kubernetes marries the simplicity and efficiency of Go with the powerful orchestration capabilities of Kubernetes, and managing external access with the help of Ingress. This integration not only streamlines the deployment process but also enhances the resilience and scalability of applications.
In this writing, we w'll walk through a simple example of deploying a Go app on K8s. We'll cover how containerization and K8s' features like scaling and self-healing, and Ingress routing work together to keep our apps running smoothly, while ensuring seamless external access.

Desired State

We'll set up three web apps on our K8s cluster. The configuration should ensure that when a client accesses the domain app1.com, the server displays the first one; when he uses app2.com, the second application is server and the same for the third one.

Implementation

1- Building the Application

We setup a basic HTTP server that listens for requests and responds with a simple message.

package main

import (
	"fmt"
	"net/http"
	"os"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
	hostname, _ := os.Hostname()
	pageContent := `
	<!DOCTYPE html>
	<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Greeting App</title>
		<style>
			body {
				font-family: Arial, sans-serif;
				text-align: center;
				margin: 50px;
				background-color: #f4f4f9;
				color: #333;
			}
			.container {
				background-color: #fff;
				padding: 20px;
				border-radius: 10px;
				box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
			}
			h1 {
				color: #007BFF;
			}
			p {
				font-size: 18px;
			}
			footer {
				margin-top: 20px;
				font-size: 14px;
				color: #777;
			}
		</style>
	</head>
	<body>
		<div class="container">
			<h1>Greeting App</h1>
			<img src="https://miro.medium.com/v2/resize:fit:960/1*Omyx9_Tare9Dyhht9m9Ivw.jpeg" alt="img" />
			<p>Welcome to the Greeting Application!</p>
			<p>This application is running in a Kubernetes environment.</p>
		</div>
		<footer>
			<p>&copy; 2024 Greeting App | Powered by Go and Kubernetes</p>
		</footer>
	</body>
	</html>
	`
	fmt.Fprintf(w, pageContent, hostname)
}

func main() {
	http.HandleFunc("/", homeHandler)

	port := "8080"
	fmt.Printf("Starting server on :%s\n", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		fmt.Println("Error starting server:", err)
	}
}

2- Containerizing The Application

Creating a lightweight final image which will be pushed to Docker registry and pulled later when deploying the app using the deployment YAML.

# Build stage
FROM golang:1.23.6-alpine AS builder
WORKDIR /app

RUN if [ ! -f go.mod ]; then \
      go mod init auto/module; \
    fi
RUN go mod tidy
COPY . .
RUN go build -o server .

# Final image stage
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]

3- Kubernetes Manifest For Deployment

Defining in Deployment.yaml file the way our app runs in Kubernetes, specifying the number of replicas, container image(the one we created in the previous step), and resource settings.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: dockeruser/myapp:latest
        ports:
        - containerPort: 8080

Creating s stable network endpoint for the app using a Service.yaml file, allowing communication between pods and external clients, ensuring traffic is routed correctly to the running application instances.

apiVersion: v1
kind: Service
metadata:
  name:  service-myapp
spec:
  selector:
    app: myapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: ClusterIP

Managing external access to the application using host-based routing with the use of Ingress.yaml file, which directs requests to the appropriate service based on the domain name.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-myapp
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-myapp
            port:
              number: 80
             number: 80

By following the steps outlined, we'll be able to deploy our apps seamlessly and achieve the desired states, with external access routed correctly and the apps maintaining high availability.

catch me on: