Kubernetes at home - Part 3: HAProxy Ingress

In order to conveniently host websites using my single node Kubernetes cluster, I’m adding on a reverse proxy and load balancer. For no particular justification, I decided to run with HAProxy Ingress

Steps - haproxy

The installation steps for HAProxy Ingress are here. But for the sake of history, this is what I did.

  1. Install helm using arkade
daniel@bequiet:~$ arkade get helm
Downloading helm
https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz
12.33 MiB / 12.33 MiB [---------------------------------------------------------------------------------------------------------------------------------------------------] 100.00%
/tmp/linux-amd64 linux-amd64/
/tmp/helm linux-amd64/helm
/tmp/README.md linux-amd64/README.md
/tmp/LICENSE linux-amd64/LICENSE
2020/12/31 22:42:01 extracted tarball into /tmp: 3 files, 0 dirs (271.767355ms)
Tool written to: /home/daniel/.arkade/bin/helm

# Add (helm) to your PATH variable
export PATH=$PATH:$HOME/.arkade/bin/

# Test the binary:
/home/daniel/.arkade/bin/helm

# Or install with:
sudo mv /home/daniel/.arkade/bin/helm /usr/local/bin/

daniel@bequiet:~$ which helm
/home/daniel/.arkade/bin//helm
  1. Add haproxy-ingress helm repository.
daniel@bequiet:~$ helm repo add haproxy-ingress https://haproxy-ingress.github.io/charts
"haproxy-ingress" has been added to your repositories

daniel@bequiet:~$ helm search repo haproxy-ingress
NAME                            CHART VERSION   APP VERSION     DESCRIPTION                                
haproxy-ingress/haproxy-ingress 0.11.0          v0.11           Ingress controller for HAProxy loadbalancer
  1. Install haproxy-ingress chart. I do change the configuration slightly because I’m going to be running it as a daemonset on the node and I want ports 80 and 443 to be taken over by it.
helm install haproxy-ingress haproxy-ingress/haproxy-ingress \
     --create-namespace --namespace=ingress-controller \
     --set controller.kind=DaemonSet \
     --set controller.daemonset.useHostPort=true
daniel@bequiet:~$ helm install haproxy-ingress haproxy-ingress/haproxy-ingress \
>      --create-namespace --namespace=ingress-controller \
>      --set controller.kind=DaemonSet \
>      --set controller.daemonset.useHostPort=true
NAME: haproxy-ingress
LAST DEPLOYED: Thu Dec 31 23:10:37 2020
NAMESPACE: ingress-controller
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
HAProxy Ingress has been installed!

HAProxy is exposed as a `LoadBalancer` type service.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running:

    kubectl --namespace ingress-controller get services haproxy-ingress -o wide -w

An example Ingress that makes use of the controller:

  apiVersion: networking.k8s.io/v1beta1
  kind: Ingress
  metadata:
    annotations:
      kubernetes.io/ingress.class: haproxy
    name: example
    namespace: default
  spec:
    rules:
      - host: www.example.com
        http:
          paths:
            - backend:
                serviceName: exampleService
                servicePort: 8080
              path: /
              
daniel@bequiet:~$ helm list --all-namespaces
NAME            NAMESPACE               REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
haproxy-ingress ingress-controller      1               2020-12-31 23:10:37.639625167 -0500 EST deployed        haproxy-ingress-0.11.0  v0.11
  1. Verify the installation using the recommend haproxy ingress method via creating an echoserver.

    • Create echoserver deployment
    • Use port 8080 on the pods
    • Create an ingress that haproxy will pick up on, that uses an external service to redirect a website to a local IP address.
daniel@bequiet:~$ kubectl create deployment echoserver --image k8s.gcr.io/echoserver:1.3
deployment.apps/echoserver created

daniel@bequiet:~$ kubectl expose deployment echoserver --port=8080
service/echoserver exposed

daniel@bequiet:~$ kubectl create -f - <<EOF
> apiVersion: networking.k8s.io/v1beta1
> kind: Ingress
> metadata:
>   annotations:
>     kubernetes.io/ingress.class: haproxy
>   name: echoserver
> spec:
>   rules:
>   - host: echoserver.192.168.0.45.nip.io
>     http:
>       paths:
>       - backend:
>           serviceName: echoserver
>           servicePort: 8080
>         path: /
> EOF
Warning: networking.k8s.io/v1beta1 Ingress is deprecated in v1.19+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.networking.k8s.io/echoserver created

daniel@bequiet:~$ curl -k https://echoserver.192.168.0.45.nip.io/
CLIENT VALUES:
client_address=10.133.205.238
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://echoserver.192.168.0.45.nip.io:8080/

SERVER VALUES:
server_version=nginx: 1.9.11 - lua: 10001

HEADERS RECEIVED:
accept=*/*
host=echoserver.192.168.0.45.nip.io
user-agent=curl/7.68.0
x-forwarded-for=192.168.0.49
x-forwarded-proto=https
BODY:
-no body in request-
  1. Cleanup the above echoserver test resources.

Summary

The kubernetes node now has a way to direct incoming requests using annotations on Kubernetes ingress resources. I intend to put applications on Kubernetes behind HAProxy.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
   annotations:
      kubernetes.io/ingress.class: haproxy