HAProxy kubernetes rewrite-targets not taking effect

Here is a simple HAProxy ingress configuration:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: httpserver-ingress
  namespace: default
  annotations:
    ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: haproxy
spec:
  rules:
    - http:
        paths:
          - path: /httpserver
            pathType: Prefix
            backend:
              service:
                name: httpserver-service
                port:
                  number: 9088
My understanding is that if I make a GET request as follows:

 curl -XGET  "http://100.107.20.22/httpserver/nosql"

HAProxy should strip the "httpserver" from the URL path and rewrite the URL to  

/nosql

Is this true? The reason I ask is because configuration results in a 404 - Not found response from the Ingress. 

Note: I am running an arm64 version of HAProxy retrieved from: gcr.io/google_containers/defaultbackend-arm

This image was installed using Helm.

Do I have an out of date version or is there something else I am missing? 

Thanks for any help in advance.

You will have to provide the actual configuration file that is passed to the haproxy executable, not the abstracted kubernetes configuration.

If this configuration does what I think it does (content switching based on the /httpserver) then no, haproxy will not strip it.

Thanks lukastribus for help. This is my haproxy config - or at least a the frontend part of it. If I understand you correctly the missing directive should be in here somewhere. Since I am not a haproxy expert at all, any tips on what the key directives are and how they can be changed would be greatly appreciated:


.....

frontend http
  mode http
  bind 0.0.0.0:80 name v4
  bind :::80 name v6
  http-request set-var(txn.base) base
  http-request set-var(txn.path) path
  http-request set-var(txn.host) req.hdr(Host),field(1,:),lower
  http-request set-var(txn.host_match) var(txn.host),map(/etc/haproxy/maps/host.map)
  http-request set-var(txn.host_match) var(txn.host),regsub(^[^.]*,,),map(/etc/haproxy/maps/host.map,'') if !{ var(txn.host_match) -m found }
  http-request set-var(txn.path_match) var(txn.host_match),concat(,txn.path,),map(/etc/haproxy/maps/path-exact.map)
  http-request set-var(txn.path_match) var(txn.host_match),concat(,txn.path,),map_beg(/etc/haproxy/maps/path-prefix.map) if !{ var(txn.path_match) -m found }
  http-request replace-path (.*) / if { var(txn.path_match) -m dom 43b315f758eafb40dea2961a0801639d }
  use_backend %[var(txn.path_match),field(1,.)]
  default_backend default-haproxy-controller-kubernetes-ingress-default-backend-http

frontend https
  mode http
  bind 0.0.0.0:443 name v4 crt /etc/haproxy/certs/frontend ssl alpn h2,http/1.1
  bind :::443 name v6 crt /etc/haproxy/certs/frontend ssl alpn h2,http/1.1
  http-request set-var(txn.base) base
  http-request set-var(txn.path) path
  http-request set-var(txn.host) req.hdr(Host),field(1,:),lower
  http-request set-var(txn.host_match) var(txn.host),map(/etc/haproxy/maps/host.map)
  http-request set-var(txn.host_match) var(txn.host),regsub(^[^.]*,,),map(/etc/haproxy/maps/host.map,'') if !{ var(txn.host_match) -m found }
  http-request set-var(txn.path_match) var(txn.host_match),concat(,txn.path,),map(/etc/haproxy/maps/path-exact.map)
  http-request set-var(txn.path_match) var(txn.host_match),concat(,txn.path,),map_beg(/etc/haproxy/maps/path-prefix.map) if !{ var(txn.path_match) -m found }
  http-request set-header X-Forwarded-Proto https
  http-request replace-path (.*) / if { var(txn.path_match) -m dom 43b315f758eafb40dea2961a0801639d }
  use_backend %[var(txn.path_match),field(1,.)]
  default_backend default-haproxy-controller-kubernetes-ingress-default-backend-http

I don’t see anything in there that would strip /httpserver. I can see that it would reset the entire path to / based on the content of txn.path_match.

Does this mean that if the configuration specifies the path with /httpserver then that would be rewritten as /. (slash

So curl -XGET “http://100.107.20.22/httpserver/nosql” would be rewritten as / (slash). Is this true?

Interestingly if the config is changed to:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: httpserver-ingress
  namespace: default
  annotations:
    ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: haproxy
spec:
  rules:
    - http:
        paths:
          - path: /nosql
            pathType: Prefix
            backend:
              service:
                name: httpserver-service
                port:
                  number: 9088

And I make the following request:
curl -XGET “http://gulfstream-one/nosql
It works!

I have no idea. The generated configuration is so complicated, I cannot spend the time to reverse engineer it to understand what it is actually doing; it would also require reading all the referenced map files.

I don’t know anything about kuberenets or the haproxy ingress controller, maybe someone else can clarify what this is supposed to be doing.

Maybe you need to specify is the entire path, for this configuration to strip it all:

- path: /httpserver/nosql

But that is just a shoot in the dark.

Yeah - the configuration is quite complex. Of course, this is the configuration provided by Helm and the reasons for such an involved configuration escapes me. Maybe, the solution is to install haproxy using docker and use a simpler configuration. One that is easier to rationalize.

Many thanks for your help. It is greatly appreciated.