HAProxy Kubernetes Ingress Controller

The architecture of modern container orchestration relies heavily on the ability to manage how external traffic reaches internal services. In a Kubernetes environment, ingress represents the web traffic entering the cluster, destined for one pod or another. This is contrasted with egress, which refers to the responses and traffic leaving the network to travel outwards toward the end user. The HAProxy Kubernetes Ingress Controller serves as the critical implementation of traffic routing, functioning by interpreting Ingress rules to direct this incoming flow effectively.

The implementation of an ingress controller is fundamental because it exposes internal services to the external world. For this mechanism to function, at least one cluster node must be accessible externally. In cloud-based environments, this is typically achieved by configuring a cloud load balancer to route traffic toward the nodes running the ingress controller. This architecture ensures that the internal complexity of the Kubernetes pod network is abstracted from the end user, who interacts only with a stable external entry point.

Beyond standard ingress, the ecosystem includes the HAProxy Unified Gateway, which supports the Gateway API for advanced traffic management. Furthermore, the HAProxy One platform provides an expanded suite of solutions for load balancing and routing across any Kubernetes environment. This includes critical capabilities such as service discovery, external load balancing, multi-cluster routing, and direct-to-pod load balancing, allowing for a more granular and scalable approach to network traffic than traditional ingress controllers.

Architecture and Functional Logic

The HAProxy Kubernetes Ingress Controller operates as a specialized agent within the cluster that watches for the creation and modification of Ingress resources. When a user defines an Ingress rule, the controller interprets these rules and configures the underlying HAProxy instance to route traffic accordingly.

The controller utilizes specific networking extensions to ensure requests reach the correct destination:

  • TLS SNI (Server Name Indication) extension: This allows the controller to identify which hostname the client is requesting during the TLS handshake.
  • Host header: The controller inspects the HTTP Host header to associate incoming requests with the correct ingress host.

For developers working in local environments, using services like nip.io is the most efficient way to test these host-based associations. However, in production environments, the deployment of dynamic DNS solutions or wildcard DNS records is mandatory to ensure reliable and scalable name resolution.

Regarding data privacy and security, HAProxy Technologies, LLC. maintains a strict policy regarding traffic flow. When the HAProxy Kubernetes Ingress Controller is deployed, the provider does not store or process any customer data related to the traffic flowing through the load balancers, ensuring that the data plane remains private to the cluster owner.

Deployment Prerequisites

Before initiating the installation of the HAProxy Ingress Controller, specific environment requirements must be met to ensure stability and compatibility.

The primary requirement is a running Kubernetes cluster. For those utilizing Controller version v0.16, the cluster must be running Kubernetes version 1.21 or newer. This versioning dependency ensures that the controller can leverage the necessary API primitives provided by the Kubernetes control plane.

The controller is highly versatile and is compatible with a wide range of local and production distributions, including:

  • minikube
  • kind
  • k3s
  • k3d
  • colima

Installation via Helm

The primary and recommended method for installing and configuring the HAProxy Ingress Controller is through Helm. This approach allows for repeatable deployments and easy configuration management.

Helm Repository Setup

To begin, the HAProxy Ingress Helm repository must be added to the local environment to allow the Helm client to fetch the necessary charts.

nix helm repo add haproxytech https://haproxytech.github.io/helm-charts

Following the addition of the repository, the local chart list must be updated to ensure the latest versions are available for deployment:

nix helm repo update

Version Management

Users can search for available versions of the Helm chart by using the --versions flag. This is critical for maintaining environment parity across development, staging, and production.

nix helm search repo --versions

The following table details the available versions and their corresponding application versions as of the current documentation:

Chart Version App Version Description
1.44.0 3.1.0-rc1 Helm chart for HAProxy Kubernetes Ingress Controller
1.43.0 3.1.0-rc1 Helm chart for HAProxy Kubernetes Ingress Controller
1.42.0 3.0.4 Helm chart for HAProxy Kubernetes Ingress Controller
1.41.0 3.0.1 Helm chart for HAProxy Kubernetes Ingress Controller
1.40.1 3.0.1 Helm chart for HAProxy Kubernetes Ingress Controller
1.40.0 3.0.0 Helm chart for HAProxy Kubernetes Ingress Controller

Deployment Execution

The installation can be performed using the standard Helm chart or via the OCI registry.

For a basic installation with a dedicated namespace:

nix helm install haproxy-kubernetes-ingress haproxytech/kubernetes-ingress \--create-namespace \--namespace haproxy-controller

Alternatively, using the OCI registry:

nix helm install haproxy-kubernetes-ingress oci://ghcr.io/haproxytech/helm-charts/kubernetes-ingress \--create-namespace \--namespace haproxy-controller

Advanced Configuration and Customization

The HAProxy Ingress Controller provides several customization options via Helm chart fields to adapt to different infrastructure requirements.

NodePort Configuration

In environments where a cloud load balancer is not available, NodePort can be used to expose the controller. By default, the controller may assign ports, but these can be specified manually.

The following command demonstrates how to assign specific ports for HTTP, HTTPS, Statistics, and Prometheus:

nix helm install haproxy-kubernetes-ingress haproxytech/kubernetes-ingress \--create-namespace \--namespace haproxy-controller \--set controller.service.nodePorts.http=30000 \--set controller.service.nodePorts.https=30001 \--set controller.service.nodePorts.stat=30002 \--set controller.service.nodePorts.prometheus=30003

When using these settings, the following port mappings are established:

  • Port 30000: Handles HTTP traffic.
  • Port 30001: Handles HTTPS traffic.
  • Port 30002: Publishes the HAProxy Stats page.
  • Port 30003: Provides Prometheus metrics.

Verification of the service status can be performed with the following command:

nix kubectl get service haproxy-kubernetes-ingress --namespace haproxy-controller

DaemonSet Deployment

For high-availability scenarios where HAProxy should run on every node in the cluster, a DaemonSet can be used instead of a standard Deployment. This is particularly useful for reducing network hops and utilizing the host's networking stack directly.

To implement this, the controller.kind field must be set to DaemonSet and the controller.daemonset.useHostPort field must be set to true.

nix helm install haproxy-kubernetes-ingress haproxytech/kubernetes-ingress \--create-namespace \--namespace haproxy-controller \--set controller.kind=DaemonSet \--set controller.daemonset.useHostPort=true

Using the OCI registry for a DaemonSet deployment:

nix helm install haproxy-kubernetes-ingress oci://ghcr.io/haproxytech/helm-charts/kubernetes-ingress \--create-namespace \--namespace haproxy-controller \--set controller.kind=DaemonSet \--set controller.daemonset.useHostPort=true

Critical Customization Parameters

When deploying the controller, several key parameters define the operational behavior of the system:

  • --version: This ensures that a specific version is installed, preventing accidental updates to a newer release that might introduce breaking changes.
  • --namespace: This specifies the target namespace for the deployment (e.g., ingress-controller). If the namespace is not provided, the controller is deployed into the current active kubectl namespace.
  • ingressClassResource.enabled: This enables the application of an IngressClass to the cluster. IngressClasses are the modern mechanism by which HAProxy Ingress identifies which Ingress resources it is responsible for controlling. This replaces the deprecated kubernetes.io/ingress.class annotation used in Kubernetes versions prior to v1.18.
  • kind, daemonset.useHostPort, and service.type: These are primarily used when a service load balancer is not available. They allow the controller to disable the service load balancer and expose HAProxy via the host port on all cluster nodes.

Manual Installation via kubectl

For users who prefer not to use Helm, the HAProxy Ingress Controller can be installed directly using YAML manifests.

The process involves the following steps:

  1. Download the latest source code from the official HAProxy Kubernetes Ingress Controller GitHub page.
  2. Deploy the controller using the kubectl apply command.

The execution command is as follows:

nix kubectl apply -f deploy/haproxy-ingress.yaml

Users have the option to download the YAML file and modify its contents locally—such as changing the namespace—before applying it to the cluster. To save the output of the deployment process, users can redirect the output to a file:

```nix

haproxy-ingress-install.yaml
```

Alternatively, the --output-dir output/ command line option can be used to save individual files for each manifest.

Traffic Management Analysis

The deployment of the HAProxy Kubernetes Ingress Controller transforms the cluster's network edge from a simple entry point into a programmable gateway. By interpreting Ingress rules, the controller allows for sophisticated routing logic. For example, an echoserver image can be deployed and exposed to the external world through a specific Ingress resource, allowing the user to verify that the path from the external client to the internal pod is fully operational.

The transition from the legacy kubernetes.io/ingress.class annotation to the IngressClass resource represents a shift toward a more structured and scalable way of managing multiple ingress controllers within a single cluster. This allows different controllers to handle different types of traffic based on the class assigned to the Ingress resource, preventing conflicts and allowing for specialized routing configurations.

Furthermore, the ability to switch between a standard Deployment and a DaemonSet provides infrastructure flexibility. While a Deployment is suitable for general-purpose scaling, the DaemonSet ensures that every node can handle ingress traffic, effectively turning the entire cluster into a load-balanced entry point. This is combined with the useHostPort setting, which minimizes the overhead associated with the Kubernetes service proxy (kube-proxy) by binding HAProxy directly to the node's network interface.

Sources

  1. HAProxy Documentation - Kubernetes Ingress Overview
  2. HAProxy Documentation - Community Installation On-Prem
  3. HAProxy Ingress GitHub - Getting Started

Related Posts