Learning Haproxy Load Balancer with Podman and Go Backends

+------------------+          +-------------------+               +-------------------+
|   Client              |          |   Haproxy LB   |                |   Podman Pod   |
| (e.g., Browser)  + ---->      (Port 8181)    +---------->-------------------+
+------------------+          +---------+---------+                |                         |
                                        |                                            |  +-------------+  |
                                        |                                            |  | go www1    |  |
                                        |                                            |  | (Port 8888) |  |
                                        |                                            |  +-------------+  |
                                        |                                            |                          |
                                        |                                            |  +-------------+  |
                                        +------------------------------> |  | go www2    |  |
                                                                                     |  | (Port 8888) |  |
                                                                                     |  +-------------+  |
                                                                                    +-------------------+



This guide walks through deploying a Kubernetes-like setup using Podman to route traffic via Haproxy (on port 8181) to two Go-based backend services (`www1` and `www2`). The solution addresses basic Haproxy load balancer configuration, Go module dependencies and build, and port configuration.


Architecture Overview  
- Haproxy LB: Routes requests on port `8181` to backend services based on URL paths.  
- Backend Services:  
  - `www1`: Serves "hello world1" on port `8888`.  
  - `www2`: Serves "hello world2" on port `8888`.  
- Podman: Used to deploy Kubernetes-style manifests in a containerized environment.  


Step 1: Create the Go Applications  

1.1 Write the Go Code  
Create two directories (`www1` and `www2`) with the following files:  

 file main.go (for go www1):  



package main


import (
"fmt"
"net/http"
)

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world1")
})
http.ListenAndServe(":8888", nil)
}


Repeat for `www2`, replacing `hello world1` with `hello world2`.  

generate go.mod (for both services):  

go mod init example.com/app


1.2 Build Local Container Images  
Create a `Dockerfile` in each directory:  

Dockerfile:  

FROM golang:alpine
WORKDIR /app
COPY go.mod .
COPY main.go .
RUN go build -o server .
EXPOSE 8888
CMD ["./server"]


Build the Images:  
# For www1
podman build -t localhost/www1:latest 

# For www2 (after updating main.go)
podman build -t localhost/www2:latest 


Step 2: Kubernetes Manifests  

2.1 Deployments and Services  
Save this as `deploy.yaml`:  


# Backend Service: www1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: www1
spec:
  selector:
    matchLabels:
      app: www1
  template:
    metadata:
      labels:
        app: www1
    spec:
      containers:
      - name: www1
        image: localhost/www1:latest
        ports:
        - containerPort: 8888
---
apiVersion: v1
kind: Service
metadata:
  name: www1
spec:
  selector:
    app: www1
  ports:
    - protocol: TCP
      port: 8888
      targetPort: 8888
---
# Backend Service: www2
apiVersion: apps/v1
kind: Deployment
metadata:
  name: www2
spec:
  selector:
    matchLabels:
      app: www2
  template:
    metadata:
      labels:
        app: www2
    spec:
      containers:
      - name: www2
        image: localhost/www2:latest
        ports:
        - containerPort: 8888
---
apiVersion: v1
kind: Service
metadata:
  name: www2
spec:
  selector:
    app: www2
  ports:
    - protocol: TCP
      port: 8888
      targetPort: 8888
---
# HAProxy ConfigMap (Round-Robin at Root Path)
apiVersion: v1
kind: ConfigMap
metadata:
  name: haproxy-config
data:
  haproxy.cfg: |
    frontend http-in
        bind *:8181
        default_backend backend_servers

    backend backend_servers
        balance roundrobin
        server www1 www1:8888
        server www2 www2:8888
---
# HAProxy Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: haproxy
spec:
  selector:
    matchLabels:
      app: haproxy
  template:
    metadata:
      labels:
        app: haproxy
    spec:
      containers:
      - name: haproxy
        image: haproxy:latest
        ports:
        - containerPort: 8181
          hostPort: 8181
        volumeMounts:
        - name: haproxy-config
          mountPath: /usr/local/etc/haproxy/haproxy.cfg
          subPath: haproxy.cfg
      volumes:
      - name: haproxy-config
        configMap:
          name: haproxy-config
          items:
          - key: haproxy.cfg
            path: haproxy.cfg


Step 3: Deploy with Podman  

sudo podman play kube deploy.yaml


Step 4: Verify the Setup  

1. Check Podman Pods:  
   sudo podman pod list

2. Test Endpoints:  
   curl http://localhost:8181  # Returns "hello world1" or "hello world2"


Troubleshooting  

Common Issues:  
1. Check if there is port conflicts:  
   - Ensure port `8181` is not in use another service:  
   sudo lsof -i :8181

2. Add host machine firewall rules if needed:  
   sudo firewall-cmd --add-port=8181/tcp


Conclusion  

This setup demonstrates:  
- Creating Go applications and container images.  
- Deploying Kubernetes-style manifests with Podman.  
- Configuring Haproxy as a load balancer on port (8181).  

By using local images and explicit port configurations, you avoid dependency on external registries and ensure predictable routing.


Komentar

Postingan populer dari blog ini

Cara restart / stop windows service (services.msc) dengan bat / cmd

How to convert VMDK to OVA

Pembahasan IT Network Systems Administration Module A DNS (Forward Zone, Reverse Zone, CNAME, MX, Split View)