This episode takes HAProxy into the container world: DaemonSet, Deployment, and sidecar deployment patterns, the ingress controller versus standalone HAProxy comparison, and managing configuration with ConfigMaps and Secrets.

HAProxy was born as a Linux daemon, but the modern ecosystem asks it to live in containers under Kubernetes orchestration. Episode 19 bridges the two.
You'll look at three deployment patterns, understand the position of the ingress controller, and learn to store configuration and secrets as Kubernetes objects. By the end of the episode, you'll be able to run HAProxy in a cluster with full confidence.
The most common pattern: running HAProxy as a Deployment managed by a ReplicaSet:
apiVersion: apps/v1
kind: Deployment
metadata:
name: haproxy-edge
spec:
replicas: 2
selector:
matchLabels:
app: haproxy
template:
metadata:
labels:
app: haproxy
spec:
containers:
- name: haproxy
image: haproxy:2.9-alpine
volumeMounts:
- name: config
mountPath: /usr/local/etc/haproxy
volumes:
- name: config
configMap:
name: haproxy-configkind: Deployment gives you replicas, rolling updates, and self-healing. The config volume mounts the haproxy-config ConfigMap into the configuration directory. This Deployment is then exposed to the outside world through a Service of type LoadBalancer.
For node-based routing, a DaemonSet places one HAProxy pod on every node:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: haproxy-node
spec:
template:
metadata:
labels:
app: haproxy-node
spec:
hostNetwork: true
containers:
- name: haproxy
image: haproxy:2.9-alpinehostNetwork: true makes the pod use the node's network namespace, so HAProxy's bound ports are directly visible on the node IP. This pattern is used by architectures that want to bypass the Service layer.
As a sidecar, HAProxy shares the pod with the application and acts as a local proxy: the app can be proxied via localhost. Just add a second container with arguments that override the default configuration path:
containers:
- name: app
image: myapp:v1
- name: haproxy-sidecar
image: haproxy:2.9-alpine
args: ["-f", "/etc/haproxy/haproxy.cfg"]
volumeMounts:
- name: config
mountPath: /etc/haproxyThe HAProxy ecosystem provides an official ingress controller that manages configuration from Ingress objects:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
ingressClassName: haproxy
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-svc
port: 8080The Ingress object above is automatically translated by the ingress controller into HAProxy configuration. You no longer write haproxy.cfg by hand. That said, standalone HAProxy still wins when you need full control over every directive or already have your own configuration pipeline — the choice depends on how much control you want to hand over to the controller.
The whole haproxy.cfg is stored as a ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: haproxy-config
data:
haproxy.cfg: |
global
log stdout format raw local0
defaults
mode http
timeout server 30s
frontend web
bind *:80
default_backend app
backend app
server s1 10.0.0.11:8080 checkThe log stdout format raw local0 directive directs logs to stdout so they can be captured by kubectl logs — the standard practice for containerized applications.
Sensitive data like TLS certificates is stored as a Secret:
kubectl create secret generic haproxy-secrets \
--from-file=tls=fullchain.pemkubectl create secret generic haproxy-secrets creates a Secret containing the TLS certificate, then mounted as a file:
volumes:
- name: tls
secret:
secretName: haproxy-secretsThe mount becomes a file that can be referenced in the crt directive. Certificates never touch git or the image.
When a ConfigMap is updated, the file in the pod changes, but the HAProxy process doesn't reload automatically. The common pattern: a sidecar reloader that watches files, or a Deployment restart:
Episode 19 bridges HAProxy and Kubernetes: flexible deployment patterns, an ingress controller for full automation, and configuration and secrets storage aligned with cloud native practices.
Key takeaways:
kubectl logs.In the next episode we'll cover CI/CD & configuration management — validating HAProxy configuration in pipelines, automated deployment and rollout strategies, and testing configuration changes before they touch production.