# Checking out HAProxy Ingress Controller

## Introduction

For me HAProxy is reminiscent of the days when I am still figuring out my way around software world. I started my career while working with HAProxy load-balancer. Back then we used to use automated shell scripts to dynamically configure backends for load-balancing. Both of us have came long way since then 😀

## Yet another Ingress Controller

In the eco-system over crowded with multiple Ingress controllers, HAProxy comes with an enterprise focused approach and innovative approaches like rootless containers and QUIC protocol. Coming from a legacy of LBing in VMs, all the existing features are extended to the Ingress Controller as well. [Here](https://github.com/haproxytech/kubernetes-ingress/blob/master/documentation/controller.md) is the list of all config map options that are available.

## Installation

The HAProxy Ingress controller installation is straightforward. Here I have created a simple EKS cluster and installed HAProxy using Helm

```markdown
## Cluster
➜  ~ k get nodes
NAME                                       STATUS   ROLES    AGE     VERSION
ip-10-0-1-221.us-east-2.compute.internal   Ready    <none>   2m15s   v1.27.9-eks-5e0fdde
ip-10-0-2-143.us-east-2.compute.internal   Ready    <none>   2m21s   v1.27.9-eks-5e0fdde

## HAProxy installation
➜  ~ helm install haproxy-kubernetes-ingress haproxytech/kubernetes-ingress \
  --create-namespace \
  --namespace haproxy-controller
NAME: haproxy-kubernetes-ingress
LAST DEPLOYED: Tue Mar 26 16:31:10 2024
NAMESPACE: haproxy-controller
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
HAProxy Kubernetes Ingress Controller has been successfully installed.

Controller image deployed is: "haproxytech/kubernetes-ingress:1.11.2".
Your controller is of a "Deployment" kind. Your controller service is running as a "NodePort" type.
RBAC authorization is enabled.
Controller ingress.class is set to "haproxy" so make sure to use same annotation for
Ingress resource.

Service ports mapped are:
  - name: http
    containerPort: 8080
    protocol: TCP
  - name: https
    containerPort: 8443
    protocol: TCP
  - name: stat
    containerPort: 1024
    protocol: TCP
  - name: quic
    containerPort: 8443
    protocol: UDP

## Components Installed

➜  learn_haproxy_ingress k get all -n haproxy-controller                                         
NAME                                              READY   STATUS      RESTARTS   AGE
pod/haproxy-kubernetes-ingress-6b9d5f976c-bvqfd   1/1     Running     0          18s
pod/haproxy-kubernetes-ingress-6b9d5f976c-v2lb4   1/1     Running     0          18s
pod/haproxy-kubernetes-ingress-crdjob-1-qzr5p     0/1     Completed   0          18s

NAME                                 TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                                  AGE
service/haproxy-kubernetes-ingress   NodePort   10.110.187.218   <none>        80:32563/TCP,443:30875/TCP,443:30875/UDP,1024:32400/TCP,6060:31395/TCP   18s

NAME                                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/haproxy-kubernetes-ingress   2/2     2            2           18s

NAME                                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/haproxy-kubernetes-ingress-6b9d5f976c   2         2         2       18s
```

## Testing with sample application

*On a side note, I am trying the ingress controller in minikube so Ingress runs as a nodePort service. I have to portforward these ports using command*

```markdown
➜  learn_haproxy_ingress minikube service haproxy-kubernetes-ingress -n haproxy-controller --url
http://127.0.0.1:50314
http://127.0.0.1:50315
http://127.0.0.1:50316
http://127.0.0.1:50317
http://127.0.0.1:50318
```

*Now you have to figure out which host port forwards to which service port in ingress. I found 50317 is HTTP(80) and 50315 is HTTPS(443). If you are trying this out, it may be same for you or might be different*

For trying the Ingress, I have followed their book "[HAProxy in Kubernetes - Supercharge Your Ingress Routing](https://www.haproxy.com/content-library/ebooks/haproxy-in-kubernetes-supercharge-your-ingress-routing)".

I have deployed sample application using below definition  

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: app
  name: app
spec:
  replicas: 2
  selector:
    matchLabels:
      run: app
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: jmalloc/echo-server
        ports:
        - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: app
  name: app
  annotations:
    haproxy.org/check: "enabled"
    haproxy.org/forwarded-for: "enabled"
    haproxy.org/load-balance: "roundrobin"
spec:
  selector:
    run: app
  ports:
  - name: port-1
    port: 80
    protocol: TCP
    targetPort: 8080

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  namespace: default
spec:
  rules:
  - host: foo.bar
  - http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: app
              port: 
                number: 80
```

## Features

HAProxy Ingress Controller comes with all the features HAProxy has. It also has support to create TLS certs on the go for induvidual services as required.

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    # add an annotation indicating the issuer to
use
    cert-manager.io/cluster-issuer:
letsencrypt-staging
  name: mysite-ingress
  namespace: default
spec: rules:
  - host: mysite.com
    http:
      paths:
      - path: /
        backend:
          serviceName: mysite-service
          servicePort: 80
  tls:
  - secretName: mysite-cert
    hosts:
    - mysite.com
```

It will allow you to define backend, global and default groups to have fine-grained access controls like setting up `algorithm` `keep-alive` and `forwardfor` etc.

## Conclusion

HAProxy ingress is a compelling choice for the companies looking for enterprise supported tooling for safety and compliance and for companies who already uses HAProxy LB for their legacy systems.
