Escribiendo los últimos posts de mod_cluster estuve echando un vistazo a la web del proyecto y acabé dando con la imagen que tienen para montar mod_cluster en un contenedor docker. Básicamente es una imagen con un Apache y mod_cluster embebidos listos para su uso, lo que nos quita de tener que compilar el módulo o bajar los binarios como veníamos haciendo tradicionalmente.
Para probarlo sin más podemos arrancarlo tal cual nos indica el autor de la imagen en el Hub de Docker. Sin embargo para integrarlo con una instancia de Jboss tenemos que personalizar la configuración de la imgen un poco más.
En el artículo, mi instancia de Jboss utiliza la IP 192.168.1.2
y el frontal Apache (que se ejecuta en docker) tiene la IP 192.168.1.154
Configuración de imagen y arranque del contenedor
Me he creado mi propia imagen con un Dockerfile. En el directorio de trabajo tengo los siguientes ficheros:
root@dev:/home/jota/dockerfiles/mod_cluster# ls -l total 12 -rwxr-xr-x 1 root root 2367 Mar 21 21:05 docker-entrypoint.sh -rw-r--r-- 1 root root 349 Apr 14 11:44 Dockerfile -rw-r--r-- 1 root root 1385 Apr 15 21:19 mod_cluster.conf
Donde en Dockerfile
tengo:
FROM karm/mod_cluster-master-dockerhub:latest MAINTAINER juliojosesb@gmail.com # Your own configuration located in the same directory as your Dockerfile COPY mod_cluster.conf ${HTTPD_MC_BUILD_DIR}/conf/extra/mod_cluster.conf # Your own entry point script located in the same directory as your Dockerfile COPY docker-entrypoint.sh /
El fichero docker-entrypoint.sh
contiene:
#!/bin/bash set -e if [ "$1" = 'start' ]; then #get the current ip addr of the continer CONTAINER_IP_ADDR=$(/sbin/ip route|awk '/default/ { print $3 }') MODCLUSTER_PORT=${MODCLUSTER_PORT:-6666} MODCLUSTER_ADVERTISE=${MODCLUSTER_ADVERTISE:-On} MODCLUSTER_ADVERTISE_GROUP=${MODCLUSTER_ADVERTISE_GROUP:-224.0.1.105:23364} MODCLUSTER_NET=${MODCLUSTER_NET:-172.} MODCLUSTER_MANAGER_NET=${MODCLUSTER_MANAGER_NET:-$MODCLUSTER_NET} echo echo "Starting httpd with mod_cluster" echo "===============================" echo "MODCLUSTER_PORT ${MODCLUSTER_PORT}" echo "MODCLUSTER_ADVERTISE ${MODCLUSTER_ADVERTISE}" echo "MODCLUSTER_ADVERTISE_GROUP ${MODCLUSTER_ADVERTISE_GROUP}" echo "MODCLUSTER_NET ${MODCLUSTER_NET}" echo "MODCLUSTER_MANAGER_NET ${MODCLUSTER_MANAGER_NET}" echo "mod_cluster server advertise url: http://${CONTAINER_IP_ADDR}:${MODCLUSTER_PORT}" echo MOD_CLUSTER_CONF_PATH=${HTTPD_MC_BUILD_DIR}/conf/extra/mod_cluster.conf if grep -q FACTORY_DEFAULTS ${MOD_CLUSTER_CONF_PATH}; then # create mod-cluster.conf from environment variables echo "Creating ${MOD_CLUSTER_CONF_PATH} configuration file:" echo cat >${MOD_CLUSTER_CONF_PATH} <<EOT LoadModule proxy_cluster_module modules/mod_proxy_cluster.so LoadModule cluster_slotmem_module modules/mod_cluster_slotmem.so LoadModule manager_module modules/mod_manager.so LoadModule advertise_module modules/mod_advertise.so MemManagerFile ${HTTPD_MC_BUILD_DIR}/cache/mod_cluster <IfModule manager_module> Listen ${MODCLUSTER_PORT} <VirtualHost ${CONTAINER_IP_ADDR}:${MODCLUSTER_PORT}> ErrorLog logs/mod_cluster_error.log CustomLog logs/mod_cluster.log common LogLevel debug <Directory /> Require ip ${MODCLUSTER_NET} </Directory> AllowDisplay On ServerAdvertise ${MODCLUSTER_ADVERTISE} http://${CONTAINER_IP_ADDR}:${MODCLUSTER_PORT} AdvertiseGroup ${MODCLUSTER_ADVERTISE_GROUP} EnableMCPMReceive <Location /mcm> SetHandler mod_cluster-manager Require ip ${MODCLUSTER_MANAGER_NET} </Location> </VirtualHost> </IfModule> EOT cat ${MOD_CLUSTER_CONF_PATH} echo fi echo "-- Cleaning lock files." rm -f /opt/httpd-build/logs/httpd.pid rm -f /opt/httpd-build/logs/authdigest_shm.* echo "-- ${HTTPD_MC_BUILD_DIR}/bin/apachectl $@" ${HTTPD_MC_BUILD_DIR}/bin/apachectl "$@" else exec "$@" fi
Y finalmente el fichero mod_cluster.conf
personalizado para mi caso es este:
# # MOD_CLUSTER MANAGER VHOST # LoadModule proxy_cluster_module modules/mod_proxy_cluster.so LoadModule cluster_slotmem_module modules/mod_cluster_slotmem.so LoadModule manager_module modules/mod_manager.so LoadModule advertise_module modules/mod_advertise.so MemManagerFile /opt/httpd-build/cache/mod_cluster Listen *:6666 <VirtualHost *:6666> ErrorLog logs/mod_cluster_error.log CustomLog logs/mod_cluster_access.log common LogLevel info <Directory /> Require ip 192.168.1 </Directory> AllowDisplay On ServerAdvertise On AdvertiseFrequency 5 AdvertiseGroup 224.0.1.105:23364 EnableMCPMReceive On <Location /mcm> SetHandler mod_cluster-manager Require ip 192.168.1 </Location> </VirtualHost> # # APP VHOST # Listen *:80 <VirtualHost *:80> ServerName lb_app1 <Directory /> Require all granted </Directory> # Balancer for this VirtualHost ManagerBalancerName lb_app1 ProxyPass / balancer://lb_app1/ stickysession=JSESSIONID|jsessionid nofailover=On ErrorLog logs/app1_error.log CustomLog logs/app1_access.log common </VirtualHost>
La configuración es similar a la comentada en el post anterior donde explicaba cómo configurar mod_cluster por UDP o TCP, separando la parte de administración de mod_cluster del LoadBalancer que doy de alta en cada VirtualHost.
Una vez tenemos esto construimos nuestra imagen:
docker build -q --rm --tag=mod_cluster_jota .
Después ejecutamos el contenedor:
docker run -it --rm --net host \ --name mod_cluster-app1 \ -e MODCLUSTER_PORT=6666 \ -e MODCLUSTER_ADVERTISE=On \ -e MODCLUSTER_NET=192.168.1 \ -e MODCLUSTER_MANAGER_NET=192.168.1 \ mod_cluster_jota
Veremos:
Starting httpd with mod_cluster =============================== MODCLUSTER_PORT 6666 MODCLUSTER_ADVERTISE On MODCLUSTER_ADVERTISE_GROUP 224.0.1.105:23364 MODCLUSTER_NET 192.168.1 MODCLUSTER_MANAGER_NET 192.168.1 mod_cluster server advertise url: http://192.168.1.1:6666 -- Cleaning lock files. -- /opt/httpd-build/bin/apachectl start -DFOREGROUND AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Si quisiera entrar dentro del contenedor para revisar logs, ficheros de configuración, etc… podemos hacerlo invocando una shell dentro:
docker exec -it mod_cluster-app1 bash
Configuración y arranque de Jboss
Se trata de una instancia Jboss EAP 7.1. Configuramos en standalone-ha.xml
:
- Subsistema mod_cluster:
<subsystem xmlns="urn:jboss:domain:modcluster:3.0"> <mod-cluster-config advertise-socket="modcluster" balancer="${modcluster.balancer}" proxies="apache1" connector="ajp"> <dynamic-load-provider> <load-metric type="cpu"/> </dynamic-load-provider> </mod-cluster-config> </subsystem>
-
Outbound-connection para que el proxy apache1 apunte al contenedor:
<outbound-socket-binding name="apache1"> <remote-destination host="192.168.1.154" port="6666"/> </outbound-socket-binding>
Arrancamos Jboss indicando el balanceador (lb_app1) donde se publica el contexto de nuestra aplicación:
./standalone.sh -c standalone-ha.xml \ -Dmodcluster.balancer=lb_app1 \ -Djboss.bind.address.management=192.168.1.2 \ -Djboss.bind.address=192.168.1.2
En un navegador comprobamos el estado de mod_cluster en http://192.168.1.154:6666/mcm
En mi caso la aplicación desplegada tiene el contexto /example como se puede ver en el monitor de mod_cluster. Si entro por el Apache con la dirección http://192.168.1.154/example podré acceder a mi aplicación. Según la aplicación que tengas desplegada en Jboss esto variará. Siempre puedes probar las de ejemplo del repo Jboss EAP Quickstarts.
Tanto la imagen como la instancia de JBoss la podemos configurar según necesidades. He dejado el fork del proyecto original en mi cuenta con los ficheros de configuración ya modificados para construir la imagen y ejecutar el contenedor.