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