Score:0

HAProxy health-check fails with Layer7 wrong status, code: 400, info: "HTTP status check returned code 400

cn flag

I have an HAProxy server that I'm using as a L7 load balancer for my k8s nodes. My cluster is istio enabled and I have an istio-ingressgateway service exposed via NodePort

NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                      AGE
istio-ingressgateway   NodePort    10.11.140.167   <none>        15021:30301/TCP,80:31916/TCP,443:31517/TCP,15012:30768/TCP,15443:32020/TCP   11d

From the HAProxy server I'm trying to perform health-checks on /healthz/ready endpoint. I'm using HAProxy 1.8 and my haproxy.cfg is as follows:

global
    log         /dev/log    local0
    log         /dev/log    local1 notice
    chroot      /var/lib/haproxy
    pidfile     /var/run/rh-haproxy18-haproxy.pid

    user        haproxy
    group       haproxy
    daemon
    stats       socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners

    spread-checks  21

    # Default SSL material locations
    ca-base     /etc/ssl/certs
    crt-base    /etc/ssl/private

    # Default ciphers to use on SSL-enabled listening sockets.
    # For more information, see ciphers(1SSL). This list is from:
    #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
    # An alternative list with additional directives can be obtained from
    #  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option                  http-server-close
    option                  redispatch
    retries                 3

    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 10000
    balance                 roundrobin


frontend http-80
        bind *:80
        mode http
        option httplog
        default_backend www-80

backend www-80
        balance roundrobin
        mode http
        option httpchk /healthz/ready HTTP/1.1
        http-check expect status 200
        server backendnode1 155.13.200.29:31916 check port 30301 fall 3 rise 2 inter 1597
        server backendnode2 155.13.200.28:31916 check port 30301 fall 3 rise 2 inter 1597
        server backendnode3 155.13.200.27:31916 check port 30301 fall 3 rise 2 inter 1597


frontend health-80
    bind *:8080
    acl backend_dead nbsrv(www-80) lt 1
    monitor-uri /haproxy_status
    monitor fail if backend_dead

listen stats # Define a listen section called "stats"
    bind :9000 # Listen on localhost:9000
    mode http
    stats enable  # Enable stats page
    stats hide-version  # Hide HAProxy version
    stats realm Haproxy\ Statistics  # Title text for popup window
    stats uri /haproxy_stats  # Stats URI
    stats auth haproxy:passwd  

I am using HTTP/1.1 for backend health-check because istio-ingressgateway is not accepting HTTP/1.0 requests, it results in error code 426.

Hitting the backend from HAProxy server results in success:

curl -I  http://155.13.200.29:31916/healthz/ready
HTTP/1.1 200 OK
date: Fri, 11 Jun 2021 07:21:09 GMT
x-envoy-upstream-service-time: 0
server: envoy
transfer-encoding: chunked

However, the HAProxy health-check still won't pass. I'm getting the following errors:

Jun 11 07:18:22 hap-server01 haproxy[12348]: Server www-80/backendnode2 is DOWN, reason: Layer7 wrong status, code: 400, info: "HTTP status check returned code <3C>400<3E>", check duration: 2ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Jun 11 07:18:22 hap-server01 haproxy[12348]: Server www-80/backendnode2 is DOWN, reason: Layer7 wrong status, code: 400, info: "HTTP status check returned code <3C>400<3E>", check duration: 2ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Jun 11 07:18:22 hap-server01 haproxy[11795]: [WARNING] 161/071821 (11795) : Former worker 11798 exited with code 0
Jun 11 07:18:22 hap-server01 haproxy[12348]: Server www-80/backendnode3 is DOWN, reason: Layer7 wrong status, code: 400, info: "HTTP status check returned code <3C>400<3E>", check duration: 3ms. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Jun 11 07:18:22 hap-server01 haproxy[12348]: Server www-80/backendnode3 is DOWN, reason: Layer7 wrong status, code: 400, info: "HTTP status check returned code <3C>400<3E>", check duration: 3ms. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.

I understand that status code 400 occurs for bad requests. Is there something miss configured in my haproxy.cfg? I feel like it's the way I am trying to send HTTP/1.1 request for health-check. But, I'm not sure what else to add or what to modify in the configuration.

Score:0
in flag

Check the manual, you can't specify version without specifying the method:

option httpchk <method> <uri> <version>

in your case, I'd try

option httpchk GET /healthz/ready HTTP/1.1

Also: learn about tcpdump, very interesting to watch the communication between systems and find out what's wrong.

bakadevops avatar
cn flag
I'm using HAProxy version 1.8. ```option httpchk GET /healthz/ready HTTP/1.1``` , this still returns ```400```. The manual says that ```Note that the Host field is mandatory in HTTP/1.1, use "http-check send" directive to add it.``` So, I added ```http-check send hdr Host www```. Now it works.
Gerard H. Pille avatar
in flag
In my time you had to append a newline and the host header to httpchk.
berndbausch avatar
us flag
Although the problem appears to be solved, I would have looked at the web server logs first, to understand what requests they receive. And I second the remark about tcpdump.
bakadevops avatar
cn flag
@berndbausch, thanks for the remark. I will make sure to verify the logs and tcpdumps.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.