Hi,

As the issue reported on Github haproxy repo are disabled, I transfer
the issue here.

I created a Github repo for this issue,
https://github.com/twang2218/haproxy-dns-issue

All the information are there. Here is the issue description.

# The issue

The HAProxy doesn't respect the `hold valid 1s` setting, so after the
`docker-compose scale app=10`, the reverse proxy will not redirect the
traffic to the other `app` service, only to the original resolved IP
address. [haproxy/haproxy#74](https://github.com/haproxy/haproxy/issues/74)

# Setup

Here is a Docker Compose project to reproduce the issue.

3 services are defined in the `docker-compose.yml`.

```yaml
version: '2'
services:
    haproxy:
        image: haproxy:latest
        volumes:
            - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
        ports:
            - "80:80"
        depends_on:
            - app
            - syslog
    app:
        image: node:latest
        volumes:
            - ./index.js:/app/index.js
        command: node /app/index.js
    syslog:
        image: bobrik/syslog-ng:latest
        volumes:
            - ./log:/var/log/syslog-ng
```

`haproxy` is an HAProxy server as a reverse proxy server. The
`haproxy.cfg` is the following:

```python
global
    log syslog daemon

defaults
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

resolvers docker_dns
    nameserver dns "127.0.0.11:53"
    timeout retry   1s
    hold valid 1s

listen tcp_proxy
    mode tcp
    bind :80
    option tcplog
    log global
    server app app:8000 check resolvers docker_dns resolve-prefer ipv4
```

`app` is just a simple node.js web service which return the client IP
and the IP and hostname of current, so it will be easy to know which
server served the request.

# Reproduce the problem

Start up the stack.

```bash
$ docker-compose up -d
Creating network "haproxyissue74_default" with the default driver
Creating haproxyissue74_app_1
Creating haproxyissue74_syslog_1
Creating haproxyissue74_haproxy_1
```

Scale the `app` to `10`.

```bash
$ docker-compose scale app=10
Creating and starting haproxyissue74_app_2 ... done
Creating and starting haproxyissue74_app_3 ... done
Creating and starting haproxyissue74_app_4 ... done
Creating and starting haproxyissue74_app_5 ... done
Creating and starting haproxyissue74_app_6 ... done
Creating and starting haproxyissue74_app_7 ... done
Creating and starting haproxyissue74_app_8 ... done
Creating and starting haproxyissue74_app_9 ... done
Creating and starting haproxyissue74_app_10 ... done
```

And check load balance result.

```bash
$ curl http://localhost/
::ffff:172.30.0.4 → 7d10f99e3d60 @ [172.30.0.2]%
$ curl http://localhost/
::ffff:172.30.0.4 → 7d10f99e3d60 @ [172.30.0.2]%
$ curl http://localhost/
::ffff:172.30.0.4 → 7d10f99e3d60 @ [172.30.0.2]%
$ curl http://localhost/
::ffff:172.30.0.4 → 7d10f99e3d60 @ [172.30.0.2]%
$
```

If the `hold valid 1s` works, HAProxy should resolve the `app` ip
address in different, however, it looks like doesn't work.

To verify the DNS resolution's randomness, we can query the `app` DNS
within `haproxy` container.

Enter the container

```bash
$ docker-compose exec haproxy bash
root@a2243d2c5e7c:/#
```

Install `dnsutils` for `nslookup` and `dig` command.

```bash
root@a2243d2c5e7c:/# apt-get update && apt-get install -y dnsutils
Get:1 http://security.debian.org jessie/updates InRelease [63.1 kB]
Get:2 http://security.debian.org jessie/updates/main amd64 Packages [366 kB]
...
Setting up rename (0.20-3) ...
update-alternatives: using /usr/bin/file-rename to provide
/usr/bin/rename (rename) in auto mode
Setting up xml-core (0.13+nmu2) ...
Processing triggers for libc-bin (2.19-18+deb8u4) ...
Processing triggers for sgml-base (1.26+nmu4) ...
root@a2243d2c5e7c:/#
```

And then, we can use `dig` command to check the DNS query result.

```bash
root@a2243d2c5e7c:/# dig app | grep app
; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> app
;app. IN A
app. 600 IN A 172.30.0.5
app. 600 IN A 172.30.0.9
app. 600 IN A 172.30.0.7
app. 600 IN A 172.30.0.12
app. 600 IN A 172.30.0.2
app. 600 IN A 172.30.0.11
app. 600 IN A 172.30.0.8
app. 600 IN A 172.30.0.10
app. 600 IN A 172.30.0.13
app. 600 IN A 172.30.0.6
root@a2243d2c5e7c:/# dig app | grep app
; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> app
;app. IN A
app. 600 IN A 172.30.0.6
app. 600 IN A 172.30.0.10
app. 600 IN A 172.30.0.13
app. 600 IN A 172.30.0.11
app. 600 IN A 172.30.0.7
app. 600 IN A 172.30.0.2
app. 600 IN A 172.30.0.5
app. 600 IN A 172.30.0.9
app. 600 IN A 172.30.0.12
app. 600 IN A 172.30.0.8
root@a2243d2c5e7c:/# dig app | grep app
; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> app
;app. IN A
app. 600 IN A 172.30.0.13
app. 600 IN A 172.30.0.11
app. 600 IN A 172.30.0.8
app. 600 IN A 172.30.0.12
app. 600 IN A 172.30.0.5
app. 600 IN A 172.30.0.6
app. 600 IN A 172.30.0.7
app. 600 IN A 172.30.0.9
app. 600 IN A 172.30.0.2
app. 600 IN A 172.30.0.10
root@a2243d2c5e7c:/#

```

As shown above, DNS will return the records in random order, so the
first one is different every time.

Regards,
Tao

Reply via email to