====== 04 - DHCP: Kea ======
En esta práctica, vamos a instalar y configurar un servidor DHCP [[https://www.isc.org/kea/?gad_source=1&gclid=CjwKCAjw8fu1BhBsEiwAwDrsjEAp4bri_nQKn2SPsZaaOSC2_sbjPCMpJzsl02LVX10dCUANrS-7vhoCWdUQAvD_BwE|Kea]] utilizando Docker. Kea es una solución moderna y potente para la gestión de direcciones IP en redes.
A diferencia del antiguo **ISC DHCP Server**, Kea está construido con un enfoque moderno y modular, permitiendo una mayor flexibilidad y escalabilidad. Kea soporta una amplia gama de características avanzadas, incluyendo soporte para múltiples subredes, reservas de IP, y almacenamiento de datos en bases de datos SQL como MySQL o PostgreSQL.
Empezaremos creando un servidor DHCP Kea y un par de clientes que obtendrán sus direcciones IP del servidor. Posteriormente, iremos ampliando la funcionalidad con características avanzadas como la reserva de IPs por dirección MAC, la configuración de múltiples subredes y el uso de MySQL como almacenamiento de datos...
===== Configuración básica =====
==== docker-compose ====
Lo primero que haremos será crear un docker-compose.yml con la configuración de los contenedores y la red. Empezaremos indicando el nombre del proyecto y creando el contenedor del servidor usando la imagen [[https://gitlab.isc.org/isc-projects/kea-docker|kea-dhcp]]. Además, crearemos una red para nuestros contenedores y los conectaremos a ella. También pondremos una ip fija a nuestro servidor y mapearemos la carpeta local //config// (que estará en el mismo directorio que nuestro docker-compose.yml) a la del contendor // /etc/kea //.
name: dhcp-kea
services:
dhcp-server:
image: docker.cloudsmith.io/isc/docker/kea-dhcp4:2.7.0
container_name: kea-server
networks:
dhcp-net:
ipv4_address: 172.18.2.2
volumes:
- ./config:/etc/kea
networks:
dhcp-net:
driver: bridge
ipam:
config:
- subnet: 172.18.2.0/24
Fíjate que al poner la ip fija al servidor, eliminamos el guión en el nombre de la red
El siguiente paso será crear los dos clientes basados en Ubuntu. Sin embargo, antes de proceder, hay un par de consideraciones importantes. La idea es que estos clientes no tengan ninguna IP asignada al principio. Queremos que, al iniciar, los clientes estén sin IP y que posteriormente utilicemos herramientas como **dhclient** para solicitar una dirección IP a nuestro servidor DHCP Kea. Esto nos permitirá observar la secuencia completa de mensajes DHCP intercambiados entre el servidor y los clientes.
El problema es que Docker asigna una dirección IP automáticamente a cada contenedor a través de su propio servidor DHCP interno cuando se utiliza una red bridge. Para evitar conflictos y asegurar que los clientes comiencen sin IP, debemos eliminar esta IP asignada por Docker. Esto se logrará utilizando el comando **ip addr flush dev eth0** dentro del contenedor. Este comando eliminará cualquier IP previamente asignada a la interfaz de red del contenedor, permitiendo que el cliente solicite una IP nueva al servidor DHCP Kea.
Para trabajar eficazmente con redes y realizar la configuración y prueba del cliente DHCP, instalaremos algunos complementos útiles dentro de los contenedores clientes. Estos complementos incluyen:
* **iproute2**: Herramientas para la administración de redes y manejo de direcciones IP.
* **nmap**: Herramienta para escaneo de redes y descubrimiento de servicios.
* **isc-dhcp-client**: Cliente DHCP que puede ser utilizado para probar la obtención de IPs.
* **iputils-ping**: Utilidad para verificar la conectividad de red mediante pings.
* **net-tools**: Conjunto de herramientas para diagnóstico de redes, incluyendo ifconfig.
Para que los contenedores clientes puedan administrar la red y solicitar una dirección IP del servidor DHCP Kea, necesitamos otorgarles permisos adicionales. Estos permisos son necesarios para que el contenedor pueda manipular la configuración de la interfaz de red, como eliminar direcciones IP existentes y ejecutar herramientas de cliente DHCP.
Podemos proporcionar estos privilegios de varias maneras, entre ellas:
* Usando [[https://docs.docker.com/compose/compose-file/05-services/#cap_add|cap_add]]: La opción **cap_add** permite añadir capacidades específicas al contenedor. En este caso, añadiremos la capacidad **NET_ADMIN**, que otorga permisos para realizar configuraciones avanzadas de red, como modificar interfaces y eliminar direcciones IP asignadas. Esto es una solución más segura y granular, ya que solo otorga las capacidades necesarias sin conceder acceso completo al sistema.
* Usando [[https://docs.docker.com/compose/compose-file/05-services/#privileged|privileged]]: La opción **privileged** otorga al contenedor permisos completos sobre el sistema operativo huésped, incluyendo la administración total de la red. Esto proporciona un nivel de acceso más alto que cap_add y puede ser útil en casos donde se requieren permisos adicionales más allá de NET_ADMIN. Sin embargo, usar privileged: true implica que el contenedor tiene acceso total al host, lo cual puede representar un riesgo de seguridad si no se maneja adecuadamente.
Además, para que nos resulte más cómodo después, especificaremos las direcciones MAC de los clientes con la opción [[https://docs.docker.com/compose/compose-file/05-services/#mac_address|mac_address]].
De esta forma, nuestros clientes quedarían:
client1:
image: ubuntu
container_name: kea-client1
command: bash -c "apt-get update && apt-get install -y iproute2 nmap dhcpcd isc-dhcp-client iputils-ping net-tools && ip addr flush dev eth0 && sleep infinity"
networks:
dhcp-net:
mac_address: 00:11:22:33:44:55
cap_add:
- NET_ADMIN
client2:
image: ubuntu
container_name: kea-client2
command: bash -c "apt-get update && apt-get install -y iproute2 nmap dhcpcd isc-dhcp-client iputils-ping net-tools && ip addr flush dev eth0 && sleep infinity"
networks:
dhcp-net:
mac_address: 66:77:88:99:AA:BB
privileged: true
En el ejemplo anterior hemos utilizado ambas formas de otorgar permisos a modo de ejemplo, aunque ésto no es lo ideal. En este caso, deberíamos utilizar **cap_add** en ambos contendores
Por último, necesitamos asegurarnos que el dhcp integrado en Docker no asigne la ip fija de nuestro servidor. Esto lo podemos hacer usando la opción [[https://docs.docker.com/compose/compose-file/06-networks/#ipam|ip_range]] al especificar la red, para indicar qué direcciones tiene que asignar a los contendores.
De esta forma, nuestro docker-compose.yml completo quedaría:
name: dhcp-kea
services:
dhcp-server:
image: docker.cloudsmith.io/isc/docker/kea-dhcp4:2.7.0
container_name: kea-server
networks:
dhcp-net:
ipv4_address: 172.18.2.2
volumes:
- ./config:/etc/kea
client1:
image: ubuntu
container_name: kea-client1
command: bash -c "apt-get update && apt-get install -y iproute2 nmap dhcpcd isc-dhcp-client iputils-ping net-tools && ip addr flush dev eth0 && sleep infinity"
networks:
dhcp-net:
mac_address: 00:11:22:33:44:55
cap_add:
- NET_ADMIN
client2:
image: ubuntu
container_name: kea-client2
command: bash -c "apt-get update && apt-get install -y iproute2 nmap dhcpcd isc-dhcp-client iputils-ping net-tools && ip addr flush dev eth0 && sleep infinity"
networks:
dhcp-net:
mac_address: 66:77:88:99:AA:BB
cap_add:
- NET_ADMIN
networks:
dhcp-net:
driver: bridge
ipam:
config:
- subnet: 172.18.2.0/24
ip_range: 172.18.2.96/28 # Asignar IPs entre 172.18.2.100 y 172.18.2.115
==== configuración de Kea ====
Una vez tenemos nuestros contenedores listos, es hora de configurar nuestro servidor DHCP. Para ello, necesitamos crear dos archivos de configuración: **kea-ctrl-agent.conf** y **kea-dhcp4.conf** dentro de nuestra carpeta //config//.
Copia el siguiente contenido en el archivo **kea-ctrl-agent.conf**:
{
"Control-agent": {
"http-host": "0.0.0.0",
"http-port": 8000,
"control-sockets": {
"dhcp4": {
"socket-type": "unix",
"socket-name": "/run/kea/control_socket_4"
}
},
"loggers": [
{
"name": "kea-ctrl-agent",
"output_options": [
{
"output": "stdout"
}
],
"severity": "INFO"
}
]
}
}
En esta práctica, no nos detendremos en los detalles específicos de cada opción en el archivo de configuración **kea-ctrl-agent.conf**. Dado que el archivo es relativamente sencillo y se utiliza para configurar aspectos básicos del agente de control de Kea, la explicación detallada de cada opción no es necesaria para los objetivos de esta práctica. Nos centraremos en la funcionalidad general del servidor DHCP y la interacción con los clientes.\\ \\
Si quieres saber más de cómo configurar este archivo, visita este [[https://kea.readthedocs.io/en/kea-2.2.0/arm/agent.html|enlace]]
El contenido del archivo **kea-dhcp4.conf** será:
{
"Dhcp4": {
# First we set up global values
"valid-lifetime": 4000,
"renew-timer": 1000,
"rebind-timer": 2000,
# Next we set up the interfaces to be used by the server.
"interfaces-config": {
"interfaces": ["eth0"]
},
# And we specify the type of lease database
"lease-database": {
"type": "memfile",
"persist": true,
"name": "/var/lib/kea/dhcp4.leases"
},
# Finally, we list the subnets from which we will be leasing addresses.
"subnet4": [
{
"id": 1,
"subnet": "172.18.2.0/24",
"pools": [
{
"pool": "172.18.2.70 - 172.18.2.90"
}
],
"interface": "eth0"
}
]
}
}
Vamos a explicar brevemente cada concepto:
* **valid-lifetime**: Define el tiempo en segundos durante el cual una dirección IP es válida después de ser asignada a un cliente.
* **renew-timer**: Especifica el tiempo en segundos que el cliente debe esperar antes de intentar renovar su dirección IP.
* **rebind-timer**: Indica el tiempo en segundos que el cliente debe esperar antes de intentar volver a solicitar una dirección IP en caso de que la renovación haya fallado.
* **interfaces-config**: Configura las interfaces de red en las que el servidor DHCP escuchará y responderá a las solicitudes DHCP.
* **["eth0"]**: Indica que el servidor escuchará en la interfaz eth0.
* **lease-database**: Define la base de datos utilizada para almacenar la información de los arrendamientos de IP.
* **type: "memfile"**: Especifica que la base de datos se almacenará en un archivo en disco.
* **persist**: true: Indica que la base de datos debe persistir y conservar los arrendamientos incluso después de reiniciar el servidor.
* **name**: La ruta del archivo de base de datos de arrendamientos. En este caso, /var/lib/kea/dhcp4.leases.
* **subnet4**: Define las subredes de las cuales el servidor DHCP asignará direcciones IP.
* **id**: Identificador único para esta subred en particular.
* **subnet**: La dirección de la subred y la máscara de red. En este caso, 172.18.2.0/24 cubre la gama de direcciones IP desde 172.18.2.1 hasta 172.18.2.255.
* **pools**: Especifica el rango de direcciones IP disponibles para asignar a los clientes dentro de la subred.
* **pool**: Rango de IPs desde 172.18.2.70 hasta 172.18.2.90.
* **interface**: Define la interfaz de red en la que el servidor escuchará y asignará direcciones IP para esta subred.
[[https://kea.readthedocs.io/en/kea-2.6.1/arm/intro.html|Aquí]] tienes la documentación completa de cómo configurar Kea
Ya tenemos listo nuestro servidor DHCP. Volvemos a la carpeta donde está nuestro docker-compose.yml y lo ejectuamos con:
docker compose up -d
Si todo ha ido bien, veremos como se crean y ejecutar los tres contendores, además de la red.
[+] Running 4/4
✔ Network dhcp-kea_dhcp-net Created
✔ Container server Started
✔ Container client1 Started
✔ Container client2 Started
Una vez creados, nos metemos en uno de los clientes:
docker exec -it client1 bash
Primero vamos a comprobar que **eth0** no tiene ninguna IP asignada:
ip a
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
31: eth0@if32: mtu 1500 qdisc noqueue state UP group default
link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff link-netnsid 0
Fíjate que la MAC de eth0 coincide con la que hemos configurado en docker-compose.yml
A continuación, ejecutamos la siguiente instrucción para pedir una nueva IP al servidor DHCP:
dhclient -v eth0
En este punto, deberemos ver (entre otras cosas) los mensajes intercambiados con el servidor;
DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 3 (xid=0x93643256)
DHCPOFFER of 172.18.2.70 from 172.18.2.2
DHCPREQUEST for 172.18.2.70 on eth0 to 255.255.255.255 port 67 (xid=0x56326493)
DHCPACK of 172.18.2.70 from 172.18.2.2 (xid=0x93643256)
bound to 172.18.2.70 -- renewal in 913 seconds.
Si volvemos a comprobar la ip, deberíamos ver que se ha asignado correctamente:
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
31: eth0@if32: mtu 1500 qdisc noqueue state UP group default
link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.2.70/24 brd 172.18.2.255 scope global dynamic eth0
valid_lft 3997sec preferred_lft 3997sec
===== Reserva de host =====
Una reserva de host en un servidor DHCP permite asignar una dirección IP específica a un dispositivo basándose en su dirección MAC. Esto asegura que el dispositivo recibirá siempre la misma IP cada vez que se conecte a la red. Esta función es especialmente útil en escenarios donde se necesita una IP fija, como en servidores, impresoras de red, o cámaras de seguridad, facilitando la gestión y el acceso constante a estos dispositivos sin necesidad de configurarlos manualmente en cada uno de ellos.
Para probar esta funcionalidad, primero vamos a añadir un nuevo contenedor a nuestro docker-compose.yml que simulará ser una impresora:
printer:
image: ubuntu
container_name: kea-printer
command: bash -c "apt-get update && apt-get install -y iproute2 nmap dhcpcd isc-dhcp-client iputils-ping net-tools && ip addr flush dev eth0 && sleep infinity"
networks:
dhcp-net:
mac_address: CC:DD:EE:FF:00:11
cap_add:
- NET_ADMIN
Asegúrate de configurar bien la dirección MAC del host, ya que si no, no será posible asignarle una IP fija
Lo siguiente, será configurar Kea para indicar que reserve una IP para la máquina con esa MAC. Ésto se puede hacer mediante la opción **reservations** en el archivo de configuración **kea-dhcp4.conf**:
"subnet4": [
{
"id": 1,
"subnet": "172.18.2.0/24",
"pools": [
{
"pool": "172.18.2.70 - 172.18.2.90"
}
],
"interface": "eth0",
"reservations": [
{
"hw-address": "CC:DD:EE:FF:00:11",
"ip-address": "172.18.2.84"
}
]
}
]
Si arrancamos los contenedores, nos metemos en //printer// y pedimos una IP al servidor DHCP, debería darnos siempre la 172.168.2.84:
DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 3 (xid=0x2f3f8d5a)
DHCPOFFER of 172.18.2.84 from 172.18.2.2
DHCPREQUEST for 172.18.2.84 on eth0 to 255.255.255.255 port 67 (xid=0x5a8d3f2f)
DHCPACK of 172.18.2.84 from 172.18.2.2 (xid=0x2f3f8d5a)
bound to 172.18.2.84 -- renewal in 890 seconds.
===== Subredes =====
La capacidad de un servidor DHCP para servir diferentes rangos de IP a diferentes subredes permite una gestión más eficiente y flexible de redes complejas. Esto es útil en entornos donde existen múltiples subredes que requieren configuraciones de red específicas, como oficinas con departamentos separados, redes de invitados y redes internas. Al administrar varios rangos de IP, el servidor DHCP puede asignar automáticamente las direcciones adecuadas a cada dispositivo según la subred a la que pertenece, lo que facilita la segmentación de la red, mejora la seguridad y optimiza el uso de los recursos de red.
Vamos a simular un entorno con diferentes subredes. Para ello, crearemos 2 subredes (con diferentes rangos de IP) en nuestro docker-compose.yml. Añadiremos el host //client1// a la primera subred y //client2// y la impresora a la otra. Nuestro servidor tendrá dos tarjetas de red y estará en ambas subredes:
name: dhcp-kea
services:
dhcp-server:
image: docker.cloudsmith.io/isc/docker/kea-dhcp4:2.7.0
container_name: kea-server
networks:
dhcp-1floor:
ipv4_address: 172.18.2.2
dhcp-2floor:
ipv4_address: 172.18.3.2
volumes:
- ./config:/etc/kea
client1:
image: ubuntu
container_name: kea-client1
command: bash -c "apt-get update && apt-get install -y iproute2 nmap dhcpcd isc-dhcp-client iputils-ping net-tools && ip addr flush dev eth0 && sleep infinity"
networks:
dhcp-1floor:
mac_address: 00:11:22:33:44:55
cap_add:
- NET_ADMIN
client2:
image: ubuntu
container_name: kea-client2
command: bash -c "apt-get update && apt-get install -y iproute2 nmap dhcpcd isc-dhcp-client iputils-ping net-tools && ip addr flush dev eth0 && sleep infinity"
networks:
dhcp-2floor:
mac_address: 66:77:88:99:AA:BB
cap_add:
- NET_ADMIN
printer:
image: ubuntu
container_name: kea-printer
command: bash -c "apt-get update && apt-get install -y iproute2 nmap dhcpcd isc-dhcp-client iputils-ping net-tools && ip addr flush dev eth0 && sleep infinity"
networks:
dhcp-2floor:
mac_address: CC:DD:EE:FF:00:11
cap_add:
- NET_ADMIN
networks:
dhcp-1floor:
driver: bridge
ipam:
config:
- subnet: 172.18.2.0/24
ip_range: 172.18.2.96/28 # Asignar IPs entre 172.18.2.100 y 172.18.2.115
dhcp-2floor:
driver: bridge
ipam:
config:
- subnet: 172.18.3.0/24
ip_range: 172.18.3.96/28 # Asignar IPs entre 172.18.3.100 y 172.18.3.115
Nuestras dos subredes se llamas **dhcp-1floor** y **dhcp-2floor**. La primera tiene el rango de direcciones 172.18.2.0/24 y la segunda 172.18.3.0/24.
Un servidor Kea es capaz de servir IPs a diferentes subredes. Basta con definir en el archivo de configuración (**kea-dhcp4.conf**) las 2 subredes creadas:
{
"Dhcp4": {
# First we set up global values
"valid-lifetime": 4000,
"renew-timer": 1000,
"rebind-timer": 2000,
# Next we set up the interfaces to be used by the server.
"interfaces-config": {
"interfaces": ["eth0", "eth1"]
},
# And we specify the type of lease database
"lease-database": {
"type": "memfile",
"persist": true,
"name": "/var/lib/kea/dhcp4.leases"
},
# Finally, we list the subnets from which we will be leasing addresses.
"subnet4": [
{
"id": 1,
"subnet": "172.18.2.0/24",
"pools": [
{
"pool": "172.18.2.70 - 172.18.2.90"
}
],
"interface": "eth0"
},
{
"id": 2,
"subnet": "172.18.3.0/24",
"pools": [
{
"pool": "172.18.3.70 - 172.18.3.90"
}
],
"interface": "eth1",
"reservations": [
{
"hw-address": "CC:DD:EE:FF:00:11",
"ip-address": "172.18.3.84"
}
]
}
]
}
}
Fíjate que en el archivo de configuración configuramos las dos interfaces: eth0 y eth1. Ésto es para indicar a Kea que el servidor DHCP servirá IPs por ambas interfaces
===== Administración BBDD =====
En nuestra configuración de Kea, indicamos al principio que la base de datos utilizada para almacenar la información de los arrendamientos de IP era en memoria mediante la opción **lease-database**:
"lease-database": {
"type": "memfile",
"persist": true,
"name": "/var/lib/kea/dhcp4.leases"
}
De hecho, si arrancamos los contenedores Docker y hacemos varias peticiones al servidor para que sirva IPs, podemos ver en el contenido de ese archivo (**/var/lib/kea/dhcp4.leases**) las IPs que ha ido sirviendo el servidor:
address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context,pool_id
172.18.2.70,00:11:22:33:44:55,,4000,1724234915,1,0,0,2d1a2137a76e,0,,0
172.18.3.70,66:77:88:99:aa:bb,,4000,1724234927,2,0,0,7366e6e03c6d,0,,0
172.18.3.84,cc:dd:ee:ff:00:11,,4000,1724234943,2,0,0,d3b9c1306036,0,,0
172.18.3.84,cc:dd:ee:ff:00:11,,4000,1724235702,2,0,0,d3b9c1306036,0,,0
172.18.3.70,66:77:88:99:aa:bb,,4000,1724235760,2,0,0,7366e6e03c6d,0,,0
172.18.2.70,00:11:22:33:44:55,,4000,1724235778,1,0,0,2d1a2137a76e,0,,0
Podemos variar este comportamiento para hacer que toda esa información se almacene en una bbdd, lo que ofrece varios beneficios:
* **Persistencia de datos**: El almacenamiento en memoria se pierde si el servidor Kea se reinicia o se apaga. Al usar una base de datos, los datos se mantienen a salvo incluso después de reinicios o caídas del sistema.
* **Escalabilidad**: Con una base de datos, Kea puede manejar un mayor volumen de direcciones IP y reservas, lo que lo hace más adecuado para entornos más grandes o distribuidos.
* **Centralización**: En escenarios donde varios servidores DHCP necesitan acceder a la misma información, el uso de una base de datos permite una administración centralizada de direcciones IP y reservas.
* **Mejor administración de la red**: Te permitirá tener un mayor control sobre las asignaciones de IP, estadísticas y registros que pueden ser fácilmente consultados o gestionados desde la base de datos.
Para implementar este cambio, realizaremos los siguientes ajustes:
* Añadir un contenedor MySQL en Docker Compose: Kea se conectará a esta base de datos MySQL para almacenar las asignaciones y reservas de IP.
* Configurar Kea para usar MySQL: Cambiaremos la configuración de Kea para que utilice la base de datos en lugar de la memoria. Esto implica modificar el archivo de configuración kea-dhcp4.conf para que apunte al contenedor MySQL.
* Crear la base de datos y tablas necesarias: Kea necesita ciertas tablas en la base de datos para funcionar correctamente. El esquema de la base de datos deberá ser creado, y podemos utilizar los scripts de instalación que proporciona Kea.
Uno de los primeros problemas que debemos enfrentar es garantizar que, al iniciar el servidor Kea, la base de datos ya esté lista. Esto es importante porque, si Kea intenta conectarse a la base de datos antes de que esta esté completamente operativa, generará errores de conexión. Para solucionar esto, normalmente podríamos usar una herramienta como [[https://kea.readthedocs.io/en/kea-2.6.1/arm/admin.html#the-kea-admin-tool|kea-admin]] para crear la base de datos y las tablas necesarias antes de que el servidor Kea comience a funcionar.
Sin embargo, utilizar kea-admin complica el proceso de creación de contenedores. Esto nos obliga a buscar una solución que sea más sencilla y automática dentro del entorno de Docker.
En lugar de utilizar kea-admin, optamos por una solución más directa: crear la base de datos y las tablas necesarias a través de un {{ :clase:smr:sr:1eval:dhcpdb_create.zip |}}. Este script contendrá todas las instrucciones necesarias para crear la base de datos y las tablas que Kea necesita para funcionar correctamente.
Guardaremos este script en una carpeta llamada script dentro de nuestro proyecto. Luego, aprovechamos una funcionalidad de MySQL en Docker: cuando iniciamos un contenedor de MySQL, el propio contenedor ejecuta automáticamente cualquier script que esté en la carpeta **docker-entrypoint-initdb.d**.
Al mapear la carpeta script a //docker-entrypoint-initdb.d// en nuestro archivo docker-compose.yml, logramos que MySQL ejecute el script automáticamente al iniciarse el contenedor. De esta forma, la base de datos y las tablas estarán listas antes de que Kea intente conectarse, resolviendo el problema de dependencia entre los dos servicios.
Este enfoque no solo simplifica el proceso de creación de la base de datos, sino que también asegura que el contenedor MySQL siempre tenga la estructura correcta sin necesidad de ejecutar comandos adicionales o complicar el flujo de creación de contenedores.
En nuestro entorno de Docker, es crucial asegurarnos de que el contenedor kea-server no intente conectarse a la base de datos MySQL hasta que esta esté completamente lista y aceptando conexiones. Para lograr esto, utilizamos la funcionalidad de [[https://docs.docker.com/reference/compose-file/services/#healthcheck|healthcheck]] en Docker, que nos permite verificar si un servicio está listo antes de que otro servicio dependiente intente conectarse:
dhcp-mysql:
image: mysql:8.0
container_name: kea-mysql
networks:
dhcp-net:
ipv4_address: 172.18.4.3
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: dhcp_kea
volumes:
- ./mysql:/var/lib/mysql
- ./script:/docker-entrypoint-initdb.d
healthcheck:
test: mysqladmin ping -h 127.0.0.1 -u root --password=root
interval: 10s
retries: 5
start_period: 30s
timeout: 10s
Luego, añadimos la clave [[https://docs.docker.com/reference/compose-file/services/#depends_on|depends_on]] en el contenedor kea-server. Esto garantiza que kea-server no se cargue hasta que el contenedor kea-mysql pase las comprobaciones de salud.
dhcp-server:
build: .
depends_on:
dhcp-mysql:
condition: service_healthy
container_name: kea-server
networks:
dhcp-1floor:
ipv4_address: 172.18.2.2
dhcp-2floor:
ipv4_address: 172.18.3.2
dhcp-net:
ipv4_address: 172.18.4.2
volumes:
- ./config:/etc/kea
Fíjate que en nuestra configuración de Docker, utilizamos la opción **build** para crear una imagen personalizada del contenedor kea-server. Esta opción nos permite definir instrucciones adicionales en un Dockerfile que ajusta la imagen base según nuestras necesidades. En este caso, estamos utilizando un Dockerfile que extiende la imagen base de Kea para añadir algunas herramientas adicionales que requerimos en nuestro entorno:
FROM docker.cloudsmith.io/isc/docker/kea-dhcp4:2.7.0
RUN apk update && apk add --no-cache bash curl mysql-client
La opción build es necesaria porque estamos personalizando la imagen base de Kea. La imagen oficial no incluye todas las herramientas que necesitamos, como el cliente MySQL o Bash. En lugar de crear un contenedor desde una imagen que no está completamente adaptada a nuestras necesidades, utilizamos esta opción para construir una imagen que ya contiene todas las herramientas necesarias, lo que hace más eficiente el desarrollo y la ejecución de nuestra aplicación.
Al agregar estas utilidades directamente en la imagen, no tenemos que instalarlas cada vez que el contenedor se inicie, lo que ahorra tiempo y evita problemas de configuración en el futuro.
Por último, sólo nos queda cambiar la configuración de kea en el archivo kea-dhcp4.conf para indicar que vamos a utilizar MySql como almacenamiento:
"lease-database": {
"type": "mysql",
"host": "kea-mysql",
"user": "root",
"password": "root",
"name": "dhcp_kea"
},
Una vez que hemos configurado Kea para que utilice MySQL como almacenamiento, verificamos que las asignaciones de direcciones IP (leases) se están guardando correctamente en la base de datos. Para hacer esta comprobación, podemos realizar una consulta SQL sencilla sobre la tabla lease4, que es donde se almacenan las direcciones IPv4 asignadas.
Para ello, accedemos a cualquier cliente para pedir una IP al servidor DHCP. A continuación, entramos al contenedor mysql y ejecutamos:
mysql -u root -p
Una vez estamos conectados a MySql:
use dhcp_kea;
SELECT * FROM lease4;
Esto mostrará todas las entradas de direcciones IPv4 asignadas, junto con información relevante como el tiempo de expiración de la lease, la dirección MAC del cliente, entre otros detalles.
===== Práctica =====
Configura un servidor Kea DHCP para una oficina de tres pisos. Cada piso debe tener la siguiente configuración:
**Piso 1**:
Subred: 192.168.1.0/24
Dispositivos: 3 PCs y una impresora
Reserva de IP para una impresora: 192.168.1.20
**Piso 2**:
Subred: 192.168.2.0/24
Dispositivos: 2 PCs
Reserva de IP para una impresora: 192.168.2.15
**Piso 3**:
Subred: 192.168.3.0/24
Dispositivos: 3 PCs
El almacenamiento de las asignaciones debe hacerse en una bbdd MySql.
Asegúrate de que los PCs y las impresoras obtengan las configuraciones de IP adecuadas.