A Docker Compose, els contenidors es comuniquen a través d’una xarxa bridge local. Això funciona perquè tots els contenidors s’executen a la mateixa màquina. A Docker Swarm, les tasques es distribueixen entre múltiples nodes, així que necessitam un mecanisme diferent per permetre la comunicació entre elles.
Docker Swarm utilitza xarxes overlay per connectar contenidors que s’executen en nodes diferents, com si estiguessin a la mateixa xarxa local. A més, proporciona descobriment de serveis automàtic i balanceig de càrrega integrat.
Tipus de xarxes #
Docker Swarm fa feina amb diversos tipus de xarxes:
| Tipus | Àmbit | Ús principal |
|---|---|---|
bridge |
Node local | Contenidors individuals al mateix node |
host |
Node local | Contenidor usa directament la xarxa del host |
overlay |
Tot el clúster | Comunicació entre serveis a diferents nodes |
ingress |
Tot el clúster | Routing mesh per a ports publicats (automàtica) |
La xarxa bridge és la xarxa per defecte de Docker quan fem feina amb contenidors individuals (fora de Swarm). Cada node té la seva pròpia xarxa bridge, i els contenidors connectats a ella només es poden comunicar amb altres contenidors del mateix node. És la que has estat usant fins ara amb docker run i docker compose.
La xarxa host elimina l’aïllament de xarxa entre el contenidor i el node. El contenidor comparteix directament la xarxa del host, sense cap traducció de ports. És útil quan necessitam el màxim rendiment de xarxa o accés a la IP real del client, però perds l’aïllament i la flexibilitat de mapejat de ports.
La xarxa ingress és una xarxa overlay especial que Docker Swarm crea automàticament quan inicialitzam el clúster. Gestiona el tràfic extern que entra als serveis publicats (els que tenen --publish). No cal crear-la ni gestionar-la manualment, car Swarm s’encarrega del seu funcionament intern per fer possible el routing mesh.
Les xarxes overlay són les que crearem i gestionarem habitualment per connectar els nostres serveis.
Xarxes overlay #
Una xarxa overlay és una xarxa virtual que s’estén per tots els nodes del clúster. Els contenidors connectats a la mateixa xarxa overlay es poden comunicar directament, independentment de a quin node s’executin.
Per crear una xarxa overlay usarem la següent ordre:
docker network create --driver overlay backendPer defecte, les xarxes overlay només són accessibles per als serveis de Swarm. Si volem que contenidors individuals (creats amb docker run) també s’hi puguin connectar, cal usar l’opció --attachable:
docker network create --driver overlay --attachable backendCom és d’esperar, apareixen al llistat de xarxes que podem obtenir amb docker network ls:
NETWORK ID NAME DRIVER SCOPE
abc123def456 bridge bridge local
def789ghi012 host host local
ghi345jkl678 ingress overlay swarm
jkl901mno234 backend overlay swarmLes xarxes amb SCOPE igual a swarm són accessibles des de tots els nodes del clúster.
En crear un servei, el podem connectar a una xarxa:
docker service create \
--name api \
--network backend \
httpd:2.4També podem connectar un servei existent a una xarxa addicional:
docker service update --network-add frontend apiI, més tard, desconnectar-lo:
docker service update --network-rm frontend apiDescobriment de serveis #
Docker Swarm inclou un servidor DNS intern que permet als serveis trobar-se pel seu nom. Quan cream un servei, Swarm registra automàticament el nom del servei al DNS.
Imaginem que tenim dos serveis: api i database, ambdós connectats a la xarxa backend.
docker network create --driver overlay backend
docker service create --name database --network backend postgres:16
docker service create --name api --network backend myapp/apiDes de qualsevol contenidor del servei api, podem accedir a la base de dades simplement pel nom:
# Des de dins d'un contenidor del servei api
ping database
psql -h database -U postgresEl DNS intern resol database a l’adreça IP del servei. Si el servei té múltiples rèpliques, el DNS retorna l’adreça IP virtual (VIP) del servei, que balanceja automàticament entre les rèpliques.
Dins d’una xarxa overlay, cada servei és accessible per:
| Format | Exemple | Resolució |
|---|---|---|
servei |
database |
IP virtual del servei (amb balanceig) |
tasks.servei |
tasks.database |
Totes les IPs de les tasques |
servei.slot.id |
database.1.abc123 |
IP d’una tasca específica |
Normalment, utilitzarem simplement el nom del servei per aprofitar el balanceig automàtic.
Balanceig de càrrega #
Quan un servei té múltiples rèpliques, Docker Swarm balanceja automàticament les peticions entre elles. Hi ha dos modes:
- Mode VIP (Virtual IP, per defecte).
- Mode DNSRR (DNS Round Robin).
En el mode VIP, el servei té una IP virtual (VIP) única. El DNS resol el nom del servei a aquesta VIP, i Swarm s’encarrega de distribuir les peticions entre les rèpliques.
docker service create \
--name api \
--replicas 3 \
--network backend \
httpd:2.4Totes les peticions a api van a la mateixa VIP, però internament es distribueixen entre les 3 rèpliques.
En el mode DNSRR, el DNS retorna directament les IPs de totes les rèpliques, i el client tria a quina connectar-se (normalment la primera).
docker service create \
--name api \
--replicas 3 \
--network backend \
--endpoint-mode dnsrr \
httpd:2.4El mode DNSRR és útil quan necessitam controlar el balanceig des del client o quan usam protocols que no funcionen bé amb VIP (com alguns sistemes de missatgeria).
%%{init: {'theme': 'base'}}%%
flowchart TB
subgraph vip["MODE VIP (per defecte)"]
C1["Client"] --> VIP["VIP: 10.0.0.5"]
VIP --> R1["api.1"]
VIP --> R2["api.2"]
VIP --> R3["api.3"]
end
subgraph dnsrr["MODE DNSRR"]
C2["Client"] --> DNS["DNS"]
DNS -->|"10.0.0.10"| D1["api.1"]
DNS -.->|"10.0.0.11"| D2["api.2"]
DNS -.->|"10.0.0.12"| D3["api.3"]
end
vip ~~~ dnsrr
Routing mesh #
El routing mesh és el mecanisme que permet accedir a un servei publicat des de qualsevol node del clúster, encara que el node no executi cap tasca d’aquell servei.
Quan publicam un port amb --publish, Docker Swarm:
- Obre el port a tots els nodes del clúster.
- Redirigeix les peticions cap a una tasca activa del servei, independentment de quin node rebi la petició.
Per exemple, suposem que cream el següent servei:
docker service create \
--name webserver \
--replicas 2 \
--publish 80:80 \
httpd:2.4Si el servei només té tasques a node1 i node2, però accedim a http://node3:80, el routing mesh redirigeix la petició a node1 o node2.
Avantatges del routing mesh:
- Podem posar un balancejador extern apuntant a qualsevol node (o a tots).
- No cal saber a quin node s’executen les tasques.
- Si una tasca es mou a un altre node, el routing mesh s’actualitza automàticament.
Mode host (bypass del routing mesh)
Si volem que un servei només escolti al node on s’executa (sense routing mesh), podem usar el mode host:
docker service create \
--name webserver \
--publish mode=host,target=80,published=80 \
--mode global \
httpd:2.4En mode host:
- El port només s’obre als nodes que executen tasques del servei.
- No hi ha balanceig automàtic entre nodes.
- Útil quan necessites rendiment màxim o accés a la IP real del client.
Normalment s’usa amb --mode global per assegurar que cada node té una tasca.
Xarxes externes i internes #
Per defecte, les xarxes overlay permeten sortida a Internet. Si volem crear una xarxa interna o aïllada (per exemple, per a bases de dades que no han de tenir accés extern), usarem el paràmetre --internal:
docker network create --driver overlay --internal database-netEls serveis connectats a una xarxa --internal només es poden comunicar amb altres serveis de la mateixa xarxa, sense accés a Internet.
Una pràctica habitual és crear xarxes separades o aïllades per a cada capa de l’arquitectura. Per exemple, una xarxa pel front-end i una altra pel back-end:
# Xarxa per al frontend (accessible des de l'exterior)
docker network create --driver overlay frontend
# Xarxa per al backend (comunicació api-database)
docker network create --driver overlay --internal backendUna vegada creades les xarxes, connectarem els serveis a les xarxes pertinents:
# El proxy invers es connecta al frontend
docker service create --name proxy --network frontend --publish 80:80 traefik:v3.6.7
# L'API es connecta a ambdues xarxes
docker service create --name api --network frontend --network backend myapp/api
# La base de dades només es connecta al backend
docker service create --name database --network backend postgres:18
%%{init: {'theme': 'base'}}%%
flowchart LR
U["Usuari"] --> P["proxy
:80"]
subgraph frontend["Xarxa frontend"]
P
A["api"]
end
subgraph backend["Xarxa backend"]
A2["api"]
DB["database"]
end
P --> A
A --- A2
A2 --> DB
Amb aquesta configuració:
- El proxy és accessible des de l’exterior.
- L’API rep peticions del proxy i pot connectar a la base de dades.
- La base de dades només és accessible des de l’API, no des de l’exterior ni des d’Internet.
Inspeccionar xarxes #
Podem veure els detalls d’una xarxa amb la següent comanda:
docker network inspect backendLa sortida JSON mostra els serveis i contenidors connectats, les IPs assignades, i la configuració de la xarxa.
També podem veure a quines xarxes està connectat un servei:
docker service inspect --pretty apiLa secció Networks a la sortida és on trobarem la informació.
Resum #
| Comanda | Funció |
|---|---|
docker network create --driver overlay NOM |
Crea una xarxa overlay |
docker network create --driver overlay --attachable NOM |
Crea una xarxa accessible per contenidors individuals |
docker network create --driver overlay --internal NOM |
Crea una xarxa sense accés a Internet |
docker network ls |
Llista les xarxes |
docker network inspect NOM |
Mostra detalls d’una xarxa |
docker network rm NOM |
Elimina una xarxa |
docker service create --network NOM |
Connecta un servei a una xarxa |
docker service update --network-add NOM |
Afegeix una xarxa a un servei existent |
docker service update --network-rm NOM |
Desconnecta un servei d’una xarxa |
docker service create --endpoint-mode dnsrr |
Usa DNS Round Robin en lloc de VIP |
docker service create --publish mode=host,... |
Publica en mode host (sense routing mesh) |
Exercici pràctic #
L’objectiu d’aquest exercici és comprendre les xarxes overlay, el descobriment de serveis i el routing mesh.
Requisits:
- Un clúster Docker Swarm amb almanco 3 nodes.
- Connectivitat de xarxa entre els nodes.
Tasques:
-
Crear xarxes:
- Crea una xarxa overlay anomenada
web-public. - Crea una xarxa overlay interna anomenada
db-private. - Verifica que ambdues apareixen a
docker network ls.
- Crea una xarxa overlay anomenada
-
Desplegar una base de dades aïllada:
- Crea un servei
redisamb la imatgeredis:7-alpine, connectat només adb-private. - Verifica que el servei està en execució.
- Crea un servei
-
Desplegar una aplicació web:
- Crea un servei
webappamb la imatgecontainous/whoamii 3 rèpliques. - Connecta’l a ambdues xarxes:
web-publicidb-private. - Publica el port 8080.
- Verifica que hi ha una tasca a cada node.
- Crea un servei
-
Comprovar el descobriment de serveis:
- Accedeix a un contenidor del servei
webapp:docker exec -it $(docker ps -q -f name=webapp) sh - Des de dins, comprova que pots resoldre el nom
redis:ping -c 3 redis - Surt del contenidor.
- Accedeix a un contenidor del servei
-
Comprovar el routing mesh:
- Identifica a quins nodes s’executen les tasques de
webappambdocker service ps webapp. - Des de la teva màquina o des d’un node sense tasques, accedeix a
http://<ip-node>:8080. - Fes diverses peticions i observa com el
Hostnamecanvia (balanceig entre rèpliques):for i in $(seq 1 10) do curl -s http://<ip-node>:8080 | grep Hostname done
- Identifica a quins nodes s’executen les tasques de
-
Comprovar l’aïllament:
- Intenta accedir a
redisdes de fora del clúster (hauria de fallar, no té port publicat). - Crea un servei temporal per verificar que des de
web-publicno es pot accedir aredis:docker service create --name test --network web-public alpine sleep 3600 docker exec -it $(docker ps -q -f name=test) ping -c 3 redis - Hauria de fallar perquè
redisnomés està adb-private.
- Intenta accedir a
-
Neteja:
- Elimina tots els serveis creats.
- Elimina les xarxes
web-publicidb-private.