La manera mas sencilla de tener una entrada DNS por cada servidor web es utilizar un servidor Consul ya que este nos generará dichas entradas de forma automática, en este artículo anterior ya aprendimos como configurar HAProxy para que se reconfigurase en base a los servidores dados de alta en los servicios de Consul, la diferencia entre hacerlo basándonos en los servicios o en las entradas DNS son:
- Servicio: Utilizamos DataPlaneAPI para la reescritura de la configuración, esto nos permite una absoluta flexibilidad, pudiendo aumentar o disminuir el pool de servidores del backend a antojo.
- DNS: La configuración del HAProxy es mucho mas sencilla sin necesidad de aplicaciones de terceros(DataPlaneAPI), el problema es que el número de servidores del backend es semiestático ya que en la configuración del HAProxy se definirá el máximo número de servidores.
Para una mayor claridad el artículo se ha divido en varias partes:
INTRODUCCIóN:
El escenario se compone de un servidor Consul que actuará a modo de DNS, un HAProxy y algunos servidores Nginx , todos ellos jails creadas mediante IOCage .
CONSUL: NYNEX-King
HAPROXY: BlindSnipper
NGINX: PeanutBrain00/01/02/03/04/05/06/07/09/10/11
+-----+---------------+-------+--------------+---------------+
| JID | NAME | STATE | RELEASE | IP4 |
+=====+===============+=======+==============+===============+
| 39 | BlindSnipper | up | 13.1-RELEASE | 192.168.69.51 |
+-----+---------------+-------+--------------+---------------+
| 36 | NYNEX-King | up | 13.1-RELEASE | 192.168.69.50 |
+-----+---------------+-------+--------------+---------------+
| 42 | PeanutBrain00 | up | 13.1-RELEASE | 192.168.69.52 |
+-----+---------------+-------+--------------+---------------+
| 45 | PeanutBrain01 | up | 13.1-RELEASE | 192.168.69.53 |
+-----+---------------+-------+--------------+---------------+
| 50 | PeanutBrain02 | up | 13.1-RELEASE | 192.168.69.54 |
+-----+---------------+-------+--------------+---------------+
| 53 | PeanutBrain03 | up | 13.1-RELEASE | 192.168.69.55 |
+-----+---------------+-------+--------------+---------------+
| 56 | PeanutBrain04 | up | 13.1-RELEASE | 192.168.69.56 |
+-----+---------------+-------+--------------+---------------+
| 59 | PeanutBrain05 | up | 13.1-RELEASE | 192.168.69.57 |
+-----+---------------+-------+--------------+---------------+
| 63 | PeanutBrain06 | up | 13.1-RELEASE | 192.168.69.58 |
+-----+---------------+-------+--------------+---------------+
| 66 | PeanutBrain07 | up | 13.1-RELEASE | 192.168.69.59 |
+-----+---------------+-------+--------------+---------------+
| 69 | PeanutBrain08 | up | 13.1-RELEASE | 192.168.69.60 |
+-----+---------------+-------+--------------+---------------+
| 72 | PeanutBrain09 | up | 13.1-RELEASE | 192.168.69.61 |
+-----+---------------+-------+--------------+---------------+
| 75 | PeanutBrain10 | up | 13.1-RELEASE | 192.168.69.62 |
+-----+---------------+-------+--------------+---------------+
| 78 | PeanutBrain11 | up | 13.1-RELEASE | 192.168.69.63 |
+-----+---------------+-------+--------------+---------------+
CONSUL SERVER:
Instalamos Consul:
Arrancamos Consul para que nos genere él mismo el directorio de configuración:
service consul start
Realizamos la configuración base:
datacenter = "AlfaExploitDC01"
server = true
data_dir = "/var/db/consul"
bind_addr = "192.168.69.50"
client_addr = "192.168.69.50"
bootstrap = true
bootstrap_expect = 1
ui_config {
enabled = true
}
enable_syslog = true
log_level = "INFO"
Reiniciamos Consul:
Accedemos a la interfaz web, tan solo veremos un servicio registrado, el del propio Consul:
http://192.168.69.50:8500
HAPROXY:
Instalamos el software necesario:
Nos aseguramos de que el servicio syslod esté bindeado por red, consultamos las flags de configuración, si aparece el parámetro -ss debemos reconfigurarlo:
syslogd_flags: -c -ss
Lo reconfiguramos y reiniciamos el servicio:
service syslogd restart
Configuramos HAProxy:
global
daemon
maxconn 5000
log 192.168.69.51:514 local0
user nobody
group nobody
stats socket /var/run/haproxy.sock user nobody group nobody mode 660 level admin
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
timeout connect 10s
timeout client 30s
timeout server 30s
log global
mode http
option httplog
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 5s
stats auth kr0m:PASSWORD
frontend http_front
bind *:80
default_backend http_back
backend http_back
balance roundrobin
server-template mywebapp 1-10 _web._tcp.service.consul resolvers consul resolve-opts allow-dup-ip resolve-prefer ipv4 check
resolvers consul
nameserver consul 192.168.69.50:8600
accepted_payload_size 8192
hold valid 5s
La línea mas importante es server-template, en ella indicamos como debe generarse el backend:
- mywebapp: Nombre de la app web, los servidores se nombrarán en base a este parámetro.
- 1-10: Número de servidores que habrá en el backend, como vemos se trata de un valor estático.
- _web._tcp.service.consul: Entrada DNS a consultar para obtener los servidores web del backend: _SERVICE_NAME._tcp.service.consul
- resolvers consul: Que resolver utilizar para realizar la query DNS.
- resolve-opts allow-dup-ip resolve-prefer ipv4 check: Opciones adicionales sobre la resolución DNS.
Asignamos los permisos correctos del fichero:
Comprobamos manualmente que la configuración sea correcta:
[NOTICE] (83382) : haproxy version is 2.6.1-f6ca66d
[NOTICE] (83382) : path to executable is /usr/local/sbin/haproxy
[WARNING] (83382) : config : ca-file: 0 CA were loaded from '@system-ca'
Warnings were found.
Configuration file is valid
Arrancamos el servicio:
service haproxy start
NGINX:
Instalamos Consul y Nginx en los servidores web:
Arrancamos Nginx:
service nginx start
Arrancamos Consul para que nos genere él mismo el directorio de configuración:
service consul start
En la configuración de Consul definimos la ip a la que bindearse y la ip del consul-server(192.168.69.50):
datacenter = "AlfaExploitDC01"
server = false
data_dir = "/var/db/consul"
bind_addr = "192.168.69.XX"
retry_join = ["192.168.69.50"]
enable_syslog = true
log_level = "INFO"
Reiniciamos el servicio:
Damos de alta el servidor como servidor web:
{
"service": {
"name": "web",
"port": 80
}
}
Node name "PeanutBrain00.alfaexploit.com" will not be discoverable via DNS due to invalid characters. Valid characters include all alpha-numerics and dashes.
Registered service: web
NOTA: Por ahora solo vamos a dar de alta del nodo 00-08, 9 en total, esto comprende las ips de la 192.168.69.52-60.
Podemos consultar las entradas DNS manualmente:
; <<>> DiG 9.18.5 <<>> @192.168.69.50 -p 8600 _web._tcp.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41802
;; flags: qr aa rd; QUERY: 1, ANSWER: 9, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;_web._tcp.service.consul. IN A
;; ANSWER SECTION:
_web._tcp.service.consul. 0 IN A 192.168.69.52
_web._tcp.service.consul. 0 IN A 192.168.69.55
_web._tcp.service.consul. 0 IN A 192.168.69.58
_web._tcp.service.consul. 0 IN A 192.168.69.56
_web._tcp.service.consul. 0 IN A 192.168.69.59
_web._tcp.service.consul. 0 IN A 192.168.69.54
_web._tcp.service.consul. 0 IN A 192.168.69.60
_web._tcp.service.consul. 0 IN A 192.168.69.53
_web._tcp.service.consul. 0 IN A 192.168.69.57
;; Query time: 6 msec
;; SERVER: 192.168.69.50#8600(192.168.69.50) (UDP)
;; WHEN: Tue Sep 13 09:18:35 CEST 2022
;; MSG SIZE rcvd: 197
Si accedemos de nuevo a la interfaz del servidor de Consul podremos ver las intancias dadas de alta en el servicio web:
http://192.168.69.50:8500/ui/alfaexploitdc01/services
Podemos ver como en el HAProxy se van añadiendo los servidores, en caso de haber menos de 10 servidores dados de alta en el DNS se deshabilita el excedente:
Damos de alta en Consul el resto de los servidores web: 192.168.69.61-63 y consultando las entradas DNS:
; <<>> DiG 9.18.5 <<>> @192.168.69.50 -p 8600 _web._tcp.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65031
;; flags: qr aa rd; QUERY: 1, ANSWER: 12, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;_web._tcp.service.consul. IN A
;; ANSWER SECTION:
_web._tcp.service.consul. 0 IN A 192.168.69.56
_web._tcp.service.consul. 0 IN A 192.168.69.62
_web._tcp.service.consul. 0 IN A 192.168.69.53
_web._tcp.service.consul. 0 IN A 192.168.69.60
_web._tcp.service.consul. 0 IN A 192.168.69.52
_web._tcp.service.consul. 0 IN A 192.168.69.63
_web._tcp.service.consul. 0 IN A 192.168.69.58
_web._tcp.service.consul. 0 IN A 192.168.69.61
_web._tcp.service.consul. 0 IN A 192.168.69.57
_web._tcp.service.consul. 0 IN A 192.168.69.55
_web._tcp.service.consul. 0 IN A 192.168.69.54
_web._tcp.service.consul. 0 IN A 192.168.69.59
;; Query time: 1 msec
;; SERVER: 192.168.69.50#8600(192.168.69.50) (UDP)
;; WHEN: Tue Sep 13 09:25:01 CEST 2022
;; MSG SIZE rcvd: 245
A pesar de haber 12 servidores web activos HAProxy solo utiliza 10 de ellos ya que en la configuración asignamos de forma estática dicho valor, esto se podría mitigar configurando un número muy alto de servidores al que sabemos que nunca vamos a llegar o utilizando
DataPlaneAPI
:
Los servidores utilizados los decide internamente HAProxy sin manera de conocer sus ips.
TROUBLESHOOTING:
Podemos consultar los logs de HAProxy:
Arrancar HAProxy en modo debug desde el script de RC:
: ${haproxy_flags:="-d -V -f ${haproxy_config} -p ${pidfile}"}
Arrancar manualmente HAProxy:
Consultar manualmente las entradas DNS: