Gestionar las redes de servicios de Swarm
Esta página describe el funcionamiento de las redes para servicios de Swarm.
Swarm y tipos de tráfico
Un swarm de Docker genera dos tipos diferentes de tráfico:
Tráfico del plano de control y gestión: Incluye mensajes de gestión del swarm, como las solicitudes para unirse o abandonar el swarm. Este tráfico siempre está cifrado.
Tráfico del plano de datos de la aplicación: Incluye el tráfico de los contenedores y el tráfico hacia y desde clientes externos.
Conceptos clave de red
Los siguientes tres conceptos de red son importantes para los servicios de swarm:
Las redes superpuestas (overlay networks) gestionan las comunicaciones entre los demonios Docker que participan en el swarm. Puedes crear redes superpuestas de la misma manera que las redes definidas por el usuario para contenedores independientes. También puedes conectar un servicio a una o más redes superpuestas existentes para permitir la comunicación de servicio a servicio. Las redes superpuestas son redes de Docker que utilizan el controlador de red
overlay.La red ingress es una red superpuesta especial que facilita el balanceo de carga entre los nodos de un servicio. Cuando cualquier nodo del swarm recibe una solicitud en un puerto publicado, entrega esa solicitud a un módulo llamado
IPVS.IPVSrealiza el seguimiento de todas las direcciones IP que participan en ese servicio, selecciona una de ellas y le redirige la solicitud a través de la redingress.La red
ingressse crea automáticamente cuando inicializas o te unes a un swarm. La mayoría de los usuarios no necesitan personalizar su configuración, pero Docker te permite hacerlo.El docker_gwbridge es una red de puente (bridge) que conecta las redes superpuestas (incluyendo la red
ingress) a la red física de un demonio Docker individual. Por defecto, cada contenedor que ejecuta un servicio está conectado a la reddocker_gwbridgedel host de su demonio Docker local.La red
docker_gwbridgese crea automáticamente al inicializar o unirse a un swarm. La mayoría de los usuarios no necesitan personalizar su configuración, pero Docker te permite hacerlo.
TipConsulta también la Descripción general de redes para obtener más detalles sobre el funcionamiento de las redes en Swarm de forma general.
Consideraciones del cortafuegos
Los demonios Docker que participan en un swarm necesitan comunicarse entre sí a través de los siguientes puertos:
- Puerto
7946TCP/UDP para el descubrimiento de redes de contenedores. - Puerto
4789UDP (configurable) para la ruta de datos de la red superpuesta (incluyendo ingress).
Al configurar las redes en un Swarm, se debe tener especial cuidado. Consulta el tutorial para obtener una descripción general.
Redes superpuestas (Overlay networking)
Al inicializar un swarm o unir un host de Docker a un swarm existente, se crean dos nuevas redes en ese host de Docker:
- Una red superpuesta llamada
ingress, que maneja el tráfico de control y datos relacionado con los servicios del swarm. Cuando creas un servicio de swarm y no lo conectas a una red superpuesta definida por el usuario, se conecta a la redingresspor defecto. - Una red de puente (bridge) llamada
docker_gwbridge, que conecta el demonio Docker individual con los demás demonios que participan en el swarm.
Crear una red superpuesta
Para crear una red superpuesta, especifica el controlador overlay al utilizar el comando docker network create:
$ docker network create \
--driver overlay \
my-network
El comando anterior no especifica ninguna opción personalizada, por lo que Docker asigna una subred y utiliza las opciones predeterminadas. Puedes ver información sobre la red utilizando docker network inspect.
Cuando no hay contenedores conectados a la red superpuesta, su configuración no muestra detalles de subredes activas:
$ docker network inspect my-network
[
{
"Name": "my-network",
"Id": "fsf1dmx3i9q75an49z36jycxd",
"Created": "0001-01-01T00:00:00Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": []
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"Containers": null,
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4097"
},
"Labels": null
}
]
En la salida anterior, observa que el controlador es overlay y que el ámbito (scope) es swarm, en lugar de los ámbitos local, host o global que podrías ver en otros tipos de redes de Docker. Este ámbito indica que solo los hosts que participan en el swarm pueden acceder a esta red.
La subred y la puerta de enlace de la red se configuran dinámicamente cuando un servicio se conecta a la red por primera vez. El siguiente ejemplo muestra la misma red anterior, pero con tres contenedores de un servicio redis conectados a ella.
$ docker network inspect my-network
[
{
"Name": "my-network",
"Id": "fsf1dmx3i9q75an49z36jycxd",
"Created": "2017-05-31T18:35:58.877628262Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"Containers": {
"0e08442918814c2275c31321f877a47569ba3447498db10e25d234e47773756d": {
"Name": "my-redis.1.ka6oo5cfmxbe6mq8qat2djgyj",
"EndpointID": "950ce63a3ace13fe7ef40724afbdb297a50642b6d47f83a5ca8636d44039e1dd",
"MacAddress": "02:42:0a:00:00:03",
"IPv4Address": "10.0.0.3/24",
"IPv6Address": ""
},
"88d55505c2a02632c1e0e42930bcde7e2fa6e3cce074507908dc4b827016b833": {
"Name": "my-redis.2.s7vlybipal9xlmjfqnt6qwz5e",
"EndpointID": "dd822cb68bcd4ae172e29c321ced70b731b9994eee5a4ad1d807d9ae80ecc365",
"MacAddress": "02:42:0a:00:00:05",
"IPv4Address": "10.0.0.5/24",
"IPv6Address": ""
},
"9ed165407384f1276e5cfb0e065e7914adbf2658794fd861cfb9b991eddca754": {
"Name": "my-redis.3.hbz3uk3hi5gb61xhxol27hl7d",
"EndpointID": "f62c686a34c9f4d70a47b869576c37dffe5200732e1dd6609b488581634cf5d2",
"MacAddress": "02:42:0a:00:00:04",
"IPv4Address": "10.0.0.4/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4097"
},
"Labels": {},
"Peers": [
{
"Name": "moby-e57c567e25e2",
"IP": "192.168.65.2"
}
]
}
]
Personalizar una red superpuesta
Pueden existir situaciones en las que no desees utilizar la configuración predeterminada para una red superpuesta. Para obtener una lista completa de las opciones configurables, ejecuta el comando docker network create --help. Las siguientes son algunas de las opciones más comunes que se pueden cambiar.
Configurar la subred y la puerta de enlace
Por defecto, la subred y la puerta de enlace de la red se configuran automáticamente al conectar el primer servicio a la red. Puedes configurarlas al crear una red utilizando las opciones --subnet y --gateway. El siguiente ejemplo configura la subred y la puerta de enlace.
$ docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--gateway 10.0.9.99 \
my-network
Uso de grupos de direcciones predeterminadas personalizadas
Para personalizar la asignación de subredes para tus redes Swarm, puedes configurarlas opcionalmente durante swarm init.
Por ejemplo, el siguiente comando se utiliza al inicializar Swarm:
$ docker swarm init --default-addr-pool 10.20.0.0/16 --default-addr-pool-mask-length 26
Cada vez que creas una red sin utilizar la opción de línea de comandos --subnet, la subred para esta red se asignará secuencialmente a partir del siguiente rango disponible en el grupo de direcciones. Si la red especificada ya está asignada, esa red no se utilizará para Swarm.
Se pueden configurar múltiples grupos de direcciones si se requiere un espacio de direcciones no contiguo. Sin embargo, no se admite la asignación desde grupos de direcciones específicos. Las subredes de red se asignarán secuencialmente a partir del espacio de direcciones IP y las subredes se reutilizarán a medida que se liberen al eliminar redes.
La longitud de la máscara predeterminada se puede configurar y es la misma para todas las redes. Está establecida en /24 por defecto. Para cambiar la longitud de la máscara de subred predeterminada, utiliza la opción de línea de comandos --default-addr-pool-mask-length.
NoteLos grupos de direcciones predeterminados solo se pueden configurar durante
swarm inity no se pueden modificar después de la creación del clúster.
Limitaciones de tamaño de red superpuesta
Docker recomienda crear redes superpuestas con bloques /24. Los bloques de red superpuesta /24 limitan la red a 256 direcciones IP.
Esta recomendación aborda las limitaciones existentes en el modo swarm. Si necesitas más de 256 direcciones IP, no aumentes el tamaño del bloque IP. Puedes utilizar el modo de endpoint dnsrr con un balanceador de carga externo o utilizar múltiples redes superpuestas más pequeñas. Consulta Configurar el descubrimiento de servicios para obtener más información sobre los diferentes modos de endpoint.
Configurar el cifrado de los datos de la aplicación
Los datos del plano de gestión y control relacionados con un swarm siempre están cifrados. Para obtener más detalles sobre los mecanismos de cifrado, consulta el Modelo de seguridad de red superpuesta en modo Docker Swarm.
Los datos de la aplicación entre los nodos del swarm no se cifran por defecto. Para cifrar este tráfico en una red superpuesta determinada, utiliza la opción --opt encrypted en docker network create. Esto habilita el cifrado IPSEC a nivel de vxlan. Este cifrado conlleva una penalización de rendimiento no despreciable, por lo que debes probar esta opción antes de utilizarla en producción.
NoteDebes personalizar la red ingress creada automáticamente para habilitar el cifrado. Por defecto, todo el tráfico ingress está sin cifrar, ya que el cifrado es una opción a nivel de red.
Conectar un servicio a una red superpuesta
Para conectar un servicio a una red superpuesta existente, pasa la opción --network a docker service create, o la opción --network-add a docker service update.
$ docker service create \
--replicas 3 \
--name my-web \
--network my-network \
nginx
Los contenedores del servicio conectados a una red superpuesta pueden comunicarse entre sí a través de ella.
To ver a qué redes está conectado un servicio, utiliza docker service ls para encontrar el nombre del servicio, y luego docker service ps <service-name> para listar las redes. Alternativamente, para ver qué contenedores de servicios están conectados a una red, utiliza docker network inspect <network-name>. Puedes ejecutar estos comandos desde cualquier nodo de swarm que esté unido al swarm y se encuentre en estado running.
Configurar el descubrimiento de servicios
El descubrimiento de servicios es el mecanismo que utiliza Docker para redirigir una solicitud desde los clientes externos de tu servicio a un nodo individual del swarm, sin que el cliente necesite saber cuántos nodos participan en el servicio o sus direcciones IP o puertos. No necesitas publicar los puertos que se utilizan entre servicios en la misma red. Por ejemplo, si tienes un servicio WordPress que almacena sus datos en un servicio MySQL, y están conectados a la misma red superpuesta, no necesitas publicar el puerto de MySQL al cliente, solo el puerto HTTP de WordPress.
El descubrimiento de servicios puede funcionar de dos formas diferentes: balanceo de carga interno basado en conexiones en las capas 3 y 4 utilizando el DNS integrado y una IP virtual (VIP), o balanceo de carga externo y personalizado basado en solicitudes en la capa 7 utilizando DNS round robin (DNSRR). Puedes configurar esto por servicio.
Por defecto, cuando conectas un servicio a una red y ese servicio publica uno o más puertos, Docker asigna al servicio una IP virtual (VIP), que es el "front end" para que los clientes accedan al servicio. Docker mantiene una lista de todos los nodos trabajadores en el servicio y redirige las solicitudes entre el cliente y uno de los nodos. Cada solicitud del cliente puede ser redirigida a un nodo diferente.
Si configuras un servicio para utilizar el descubrimiento de servicios por DNS round-robin (DNSRR), no habrá una única IP virtual. En su lugar, Docker configura entradas DNS para el servicio de modo que una consulta DNS para el nombre del servicio devuelve una lista de direcciones IP y el cliente se conecta directamente a una de ellas.
El DNS round-robin es útil en casos donde deseas utilizar tu propio balanceador de carga, como HAProxy. Para configurar un servicio para usar DNSRR, utiliza la opción
--endpoint-mode dnsrral crear un nuevo servicio o actualizar uno existente.
Personalizar la red ingress
La mayoría de los usuarios nunca necesitan configurar la red ingress, pero Docker te permite hacerlo. Esto puede ser útil si la subred elegida automáticamente entra en conflicto con una que ya existe en tu red, si necesitas personalizar otros ajustes de red de bajo nivel como la MTU, o si deseas habilitar el cifrado.
Personalizar la red ingress implica eliminarla y volver a crearla. Esto se realiza generalmente antes de crear cualquier servicio en el swarm. Si tienes servicios existentes que publican puertos, esos servicios deben ser eliminados antes de poder retirar la red ingress.
Durante el tiempo en que no exista la red ingress, los servicios existentes que no publican puertos seguirán funcionando pero no estarán balanceados. Esto afecta a los servicios que publican puertos, como un servicio WordPress que publica el puerto 80.
Inspecciona la red
ingressutilizandodocker network inspect ingress, y elimina cualquier servicio cuyos contenedores estén conectados a ella. Estos son servicios que publican puertos, como un servicio WordPress que publica el puerto 80. Si no se detienen todos estos servicios, el siguiente paso fallará.Elimina la red
ingressexistente:$ docker network rm ingress WARNING! Before removing the routing-mesh network, make sure all the nodes in your swarm run the same docker engine version. Otherwise, removal may not be effective and functionality of newly created ingress networks will be impaired. Are you sure you want to continue? [y/N]Crea una nueva red superpuesta utilizando la opción
--ingress, junto con las opciones personalizadas que desees establecer. Este ejemplo establece la MTU en 1200, la subred en10.11.0.0/16y la puerta de enlace en10.11.0.2.$ docker network create \ --driver overlay \ --ingress \ --subnet=10.11.0.0/16 \ --gateway=10.11.0.2 \ --opt com.docker.network.driver.mtu=1200 \ my-ingressNotePuedes nombrar a tu red
ingresscon un nombre diferente aingress, pero solo puedes tener una. El intento de crear una segunda fallará.Reinicia los servicios que detuviste en el primer paso.
Personalizar el docker_gwbridge
El docker_gwbridge es un puente virtual que conecta las redes superpuestas (incluyendo la red ingress) a la red física de un demonio Docker individual. Docker lo crea automáticamente cuando inicializas un swarm o unes un host de Docker a un swarm, pero no es un dispositivo de Docker. Existe en el kernel del host de Docker. Si necesitas personalizar sus ajustes, debes hacerlo antes de unir el host de Docker al swarm, o después de retirar temporalmente el host del swarm.
Necesitas tener la aplicación brctl instalada en tu sistema operativo para poder eliminar un puente existente. El nombre del paquete suele ser bridge-utils.
Detén Docker.
Utiliza el comando
brctl show docker_gwbridgepara comprobar si existe un dispositivo de puente llamadodocker_gwbridge. Si es así, elimínalo usandobrctl delbr docker_gwbridge.Inicia Docker. No te unas ni inicialices el swarm.
Crea o vuelve a crear el puente
docker_gwbridgecon tus ajustes personalizados. Este ejemplo utiliza la subred10.11.0.0/16. Para obtener una lista completa de las opciones personalizables, consulta Opciones del controlador bridge.$ docker network create \ --subnet 10.11.0.0/16 \ --opt com.docker.network.bridge.name=docker_gwbridge \ --opt com.docker.network.bridge.enable_icc=false \ --opt com.docker.network.bridge.enable_ip_masquerade=true \ docker_gwbridgeInicializa o únete al swarm.
Usar una interfaz independiente para el tráfico de control y de datos
Por defecto, todo el tráfico del swarm se envía a través de la misma interfaz, incluyendo el tráfico de control y gestión para mantener el swarm y el tráfico de datos hacia y desde los contenedores del servicio.
Puedes separar este tráfico pasando la opción --data-path-addr al inicializar o unirse al swarm. Si hay múltiples interfaces, se debe especificar explícitamente --advertise-addr, y --data-path-addr tomará el valor predeterminado de --advertise-addr si no se especifica. El tráfico relacionado con la unión, abandono y gestión del swarm se envía a través de la interfaz --advertise-addr, y el tráfico entre los contenedores de un servicio se envía a través de la interfaz --data-path-addr. Estas opciones pueden tomar una dirección IP o un nombre de dispositivo de red, como eth0.
Este ejemplo inicializa un swarm con un --data-path-addr independiente. Asume que tu host de Docker tiene dos interfaces de red diferentes: 10.0.0.1 debe utilizarse para el tráfico de control y gestión y 192.168.0.1 debe utilizarse para el tráfico relacionado con los servicios.
$ docker swarm init --advertise-addr 10.0.0.1 --data-path-addr 192.168.0.1
Este ejemplo se une al swarm gestionado por el host 192.168.99.100:2377 y establece la opción --advertise-addr en eth0 y la opción --data-path-addr en eth1.
$ docker swarm join \
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2d7c \
--advertise-addr eth0 \
--data-path-addr eth1 \
192.168.99.100:2377
Publicar puertos en una red superpuesta
Los servicios de Swarm conectados a la misma red superpuesta exponen de forma efectiva todos los puertos entre sí. Para que un puerto sea accesible desde fuera del servicio, ese puerto debe ser publicado utilizando la opción -p o --publish en docker service create o docker service update. Se admite tanto la sintaxis antigua separada por dos puntos como la sintaxis más nueva de valores separados por comas. Se prefiere la sintaxis larga porque es autodocumentada.
| Valor de la opción | Descripción |
|---|---|
| -p 8080:80 o -p published=8080,target=80 | Mapea el puerto TCP 80 del servicio al puerto 8080 en la malla de enrutamiento. |
| -p 8080:80/udp o -p published=8080,target=80,protocol=udp | Mapea el puerto UDP 80 del servicio al puerto 8080 en la malla de enrutamiento. |
| -p 8080:80/tcp -p 8080:80/udp o -p published=8080,target=80,protocol=tcp -p published=8080,target=80,protocol=udp | Mapea el puerto TCP 80 del servicio al puerto TCP 8080 en la malla de enrutamiento, y mapea el puerto UDP 80 del servicio al puerto UDP 8080 en la malla de enrutamiento. |