MINOR: dns: new DNS options to allow/prevent IP address duplication
By default, HAProxy's DNS resolution at runtime ensure that there is no
IP address duplication in a backend (for servers being resolved by the
same hostname).
There are a few cases where people want, on purpose, to disable this
feature.
This patch introduces a couple of new server side options for this purpose:
"resolve-opts allow-dup-ip" or "resolve-opts prevent-dup-ip".
diff --git a/doc/configuration.txt b/doc/configuration.txt
index e901d7e..b443de6 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -11682,6 +11682,40 @@
after <count> consecutive successful health checks. This value defaults to 2
if unspecified. See also the "check", "inter" and "fall" parameters.
+resolve-opts <option>,<option>,...
+ Comma separated list of options to apply to DNS resolution linked to this
+ server.
+
+ Available options:
+
+ * allow-dup-ip
+ By default, HAProxy prevents IP address duplication in a backend when DNS
+ resolution at runtime is in operation.
+ That said, for some cases, it makes sense that two servers (in the same
+ backend, being resolved by the same FQDN) have the same IP address.
+ For such case, simply enable this option.
+ This is the opposite of prevent-dup-ip.
+
+ * prevent-dup-ip
+ Ensure HAProxy's default behavior is enforced on a server: prevent re-using
+ an IP address already set to a server in the same backend and sharing the
+ same fqdn.
+ This is the opposite of allow-dup-ip.
+
+ Example:
+ backend b_myapp
+ default-server init-addr none resolvers dns
+ server s1 myapp.example.com:80 check resolve-opts allow-dup-ip
+ server s2 myapp.example.com:81 check resolve-opts allow-dup-ip
+
+ With the option allow-dup-ip set:
+ * if the nameserver returns a single IP address, then both servers will use
+ it
+ * If the nameserver returns 2 IP addresses, then each server will pick up a
+ different address
+
+ Default value: not set
+
resolve-prefer <family>
When DNS resolution is enabled for a server and multiple IP addresses from
different families are returned, HAProxy will prefer using an IP address
diff --git a/include/types/dns.h b/include/types/dns.h
index 9b1d08d..488d399 100644
--- a/include/types/dns.h
+++ b/include/types/dns.h
@@ -245,6 +245,8 @@
} mask;
} pref_net[SRV_MAX_PREF_NET];
int pref_net_nb; /* The number of registered prefered networks. */
+ int accept_duplicate_ip; /* flag to indicate whether the associated object can use an IP address
+ already set to an other object of the same group */
};
/* Resolution structure associated to single server and used to manage name
diff --git a/src/dns.c b/src/dns.c
index 018c86a..77bf5c0 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -962,8 +962,10 @@
int currentip_sel;
int j;
int score, max_score;
+ int allowed_duplicated_ip;
family_priority = dns_opts->family_prio;
+ allowed_duplicated_ip = dns_opts->accept_duplicate_ip;
*newip = newip4 = newip6 = NULL;
currentip_found = 0;
*newip_sin_family = AF_UNSPEC;
@@ -1027,7 +1029,9 @@
* member of a group. If not, the score should be incremented
* by 2. */
if (owner && snr_check_ip_callback(owner, ip, &ip_type)) {
- continue;
+ if (!allowed_duplicated_ip) {
+ continue;
+ }
} else {
score += 2;
}
diff --git a/src/server.c b/src/server.c
index 277d140..17d7663 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1544,6 +1544,7 @@
if (src->resolvers_id != NULL)
srv->resolvers_id = strdup(src->resolvers_id);
srv->dns_opts.family_prio = src->dns_opts.family_prio;
+ srv->dns_opts.accept_duplicate_ip = src->dns_opts.accept_duplicate_ip;
if (srv->dns_opts.family_prio == AF_UNSPEC)
srv->dns_opts.family_prio = AF_INET6;
memcpy(srv->dns_opts.pref_net,
@@ -2082,6 +2083,7 @@
newsrv = &curproxy->defsrv;
cur_arg = 1;
newsrv->dns_opts.family_prio = AF_INET6;
+ newsrv->dns_opts.accept_duplicate_ip = 0;
}
while (*args[cur_arg]) {
@@ -2177,6 +2179,31 @@
newsrv->resolvers_id = strdup(args[cur_arg + 1]);
cur_arg += 2;
}
+ else if (!strcmp(args[cur_arg], "resolve-opts")) {
+ char *p, *end;
+
+ for (p = args[cur_arg + 1]; *p; p = end) {
+ /* cut on next comma */
+ for (end = p; *end && *end != ','; end++);
+ if (*end)
+ *(end++) = 0;
+
+ if (!strcmp(p, "allow-dup-ip")) {
+ newsrv->dns_opts.accept_duplicate_ip = 1;
+ }
+ else if (!strcmp(p, "prevent-dup-ip")) {
+ newsrv->dns_opts.accept_duplicate_ip = 0;
+ }
+ else {
+ ha_alert("parsing [%s:%d]: '%s' : unknown resolve-opts option '%s', supported methods are 'allow-dup-ip' and 'prevent-dup-ip'.\n",
+ file, linenum, args[cur_arg], p);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+
+ cur_arg += 2;
+ }
else if (!strcmp(args[cur_arg], "resolve-prefer")) {
if (!strcmp(args[cur_arg + 1], "ipv4"))
newsrv->dns_opts.family_prio = AF_INET;