Herramientas de usuario

Herramientas del sitio


informatica:sistemas_operativos:cursos:docker_avanzado:networking_y_service_discovery

¡Esta es una revisión vieja del documento!


Networking y Service Discovery (Docker avanzado)

Contenido perteneciente al curso Docker avanzado.

Network

Docker crea una interfaz de red propia con el nombre de docker0. Esta red tiene un rango típico: 174.17.0.1/24

Al principio, solo se podía manejar esta red. Eso generaba problemas de seguridad (confiabilidad y aislamiento).

Esto se mejoró con el avance de Docker

Con el comando docker network ls podemos ver las redes que tenemos configuradas por defecto:

  • host representa la red del propio equipo y haría referencia a eth0 / enp0s3, etc. Un contenedor con esta red tendrá una IP local (192.168.0.12)
  • bridge representa la red docker0 y a ella se conectan todos los contenedores por defecto. Vincula los contenedores con nuestro equipo.
  • none significa que el contenedor no se incluye en ninguna red y si verificamos esto con el comando ifconfig dentro del contenedor veríamos que solo tiene la interfaz de loopback lo.

Podemos obtener más información de las redes con inspect:

docker network inspect bridge

Ejemplo de salida:

[
    {
        "Name": "bridge",
        "Id": "66ed3ed28d43f355bd4d79e01e58d571154d5a16cc33e5c2a0d7836cc4ee039e",
        "Created": "2023-10-13T18:45:27.937713085Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

Si queremos aislar un contenedor o un grupo de contenedores, simplemente tenemos que crear una red:

docker network create --driver bridge red_aislada

y asociársela a los contenedores que queramos:

docker run --net=red_aislada -itd --name=container3 busybox

Podemos indicar que un contenedor tenga acceso a distintas redes.

Existe un comando para conectar un contenedor a cierta red:

docker network connect red_aislada contenedor

Y para desconectarlo:

docker network disconnect red_aislada contenedor

Para crear un sandbox sería útil la opción de desconectar de la red.

Overlay Network

Cuando necesitamos manejar una infraestructura compleja y grande puede ser necesario usar varios hosts en conjunto como si solo fuera uno.

Para ello necesitamos poder generar redes suprahost o superpuestas. Son redes para conectar nodos.

Para ese fin Docker hace uso de la librería VXLAN

Es imprescindible disponer de un servicio de almacenamiento key-value como Consul , Etcd , o ZooKeeper

El servicio se instala en un nodo, y en el resto se instala Docker.

Service Discovery

Un service discovery es un proceso de detección automática de dispositivos y servicios en una red.

Es un estándar de red que logra la detección de redes mediante la identificación de recursos.

Tradicionalmente, la detección de servicios ayuda a reducir los esfuerzos de configuración de los usuarios a los que se les presentan recursos compatibles, como una impresora o un servidor habilitado para Bluetooth

Más recientemente, el concepto se ha ampliado a los recursos de red o de contenedores distribuidos como “servicios”, que se descubren y a los que se accede.

Cuando trabajamos con Docker Compose, ya vemos esta característica ya que los contenedores pueden verse y podemos acceder a ellos desde el nombre de host.

El service provider tiene el service discovery. Al aparecer un nuevo servicio, se guarda en el service registry.

Service Discovery con Spring Boot

Ejemplos de implementación de un Service Discovery usando Eureka Service Discovery en Spring Boot:

Ejercicios

Ejercicio 1

Crear un contenedor con el comando docker run de cualquier imagen. Podemos usar por ejemplo la imagen busybox

docker run -d --name container1 busybox sleep infinity

1. ¿Qué redes tiene disponibles el container?

docker inspect container1

Salida:

            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "66ed3ed28d43f355bd4d79e01e58d571154d5a16cc33e5c2a0d7836cc4ee039e",
                    "EndpointID": "2d5086c60d536dd9848015a736884bfb8d78e08ee8086eb2f094cd1989a6ce6f",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }

Tiene disponible la red bridge.

2. ¿Mostrar solo las IPs del containter con el comando inspect?

docker inspect --format='{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container1

3. ¿Qué otros contenedores hay en esa misma red?

docker network inspect bridge

Podemos verlo en la sección “Containers”:

        "Containers": {
            "422af392e56a5c8dde4941fdce10e8b9618c17b8a2040f78f764cd88421032e5": {
                "Name": "container1",
                "EndpointID": "2d5086c60d536dd9848015a736884bfb8d78e08ee8086eb2f094cd1989a6ce6f",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },

Ejercicio 2

1. Crear una red de tipo bridge llamada net1 para la subred 172.60.0.0/16

docker network create --driver=bridge --subnet=172.60.0.0/16 net1

2. Vincular el contenedor del ejercicio1 con esta nueva red

docker network connect net1 container1

3. Lista las IPs del contenedor1

Podemos verlas en la sección “Networks” al hacer:

docker inspect container1

Salida:

(...)
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "66ed3ed28d43f355bd4d79e01e58d571154d5a16cc33e5c2a0d7836cc4ee039e",
                    "EndpointID": "2d5086c60d536dd9848015a736884bfb8d78e08ee8086eb2f094cd1989a6ce6f",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                },
                "net1": {
                    "IPAMConfig": {},
                    "Links": null,
                    "Aliases": [
                        "422af392e56a"
                    ],
                    "NetworkID": "7e2ba91752dfc88d29ceec5a0783c445ad9802c97cbc41a88c89445020c91f66",
                    "EndpointID": "f0e49b9bea8dfd49163e7a29e0657b7a191a1f9ecdc27fa9471e5b8c8ff380da",
                    "Gateway": "172.60.0.1",
                    "IPAddress": "172.60.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:3c:00:02",
                    "DriverOpts": {}
                }
(...)

También podríamos entrar en el contenedor y hacer un ifconfig:

docker exec -it container1 ifconfig

4. Crea un container2 que se vincule solo a la red net1

docker run -d --name container2 --network=net1 busybox sleep infinity

5. Verifica que desde container1 tenemos acceso a container2 y viceversa. Para ello puedes usar docker exec para ejecutar el comando ping entre los contenedores

Ping desde el container1 a container2:

docker exec container1 ping -c 3 container2
PING container2 (172.60.0.3): 56 data bytes
64 bytes from 172.60.0.3: seq=0 ttl=64 time=0.205 ms
64 bytes from 172.60.0.3: seq=1 ttl=64 time=0.081 ms
64 bytes from 172.60.0.3: seq=2 ttl=64 time=0.410 ms

--- container2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.081/0.232/0.410 ms

Ping desde el container2 a container1:

docker exec container2 ping -c 3 container1
PING container1 (172.60.0.2): 56 data bytes
64 bytes from 172.60.0.2: seq=0 ttl=64 time=0.178 ms
64 bytes from 172.60.0.2: seq=1 ttl=64 time=0.454 ms
64 bytes from 172.60.0.2: seq=2 ttl=64 time=0.163 ms

--- container1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.163/0.265/0.454 ms

6. Desconecta todas las redes del container1

docker network disconnect bridge container1
docker network disconnect net1 container1

7. Lista las IPs del container1

Mediante:

docker inspect --format={{.NetworkSettings.IPA
ddress}} container1

No obtenemos ningún resultado.

Si ejecutamos ifconfig en el contenedor:

docker exec container1 ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:750 (750.0 B)  TX bytes:750 (750.0 B)

8. Prueba a hace un ping al container2 y a google.es

Ping a container2 desde container1:

docker exec container1 ping -c 3 container2
ping: bad address 'container2'

Ping a google.es desde container1:

docker exec container1 ping -c 3 google.es
ping: bad address 'google.es'

Ejercicio redes y Compose

1. Crear un docker compose que levante una instancia de busybox

services:
  bb:
    image: busybox
    command: sleep infinity
    restart: always

2. Listar las redes del contenedor

docker inspect network-compose-bb-1

3. Modificar el yaml para crear una red personalizada llamada net2 en la subnet 172.80.0.0/16 (la configuración de la subnet se hace en el path de propiedades ipam > config > subnet)

services:
  bb:
    image: busybox
    command: sleep infinity
    restart: always
    networks:
      - net2

networks:
  net2:
    ipam:
      config:
        - subnet: 172.80.0.0/16

4. Tirar y levantar de nuevo el compose y verificar que la red creada es correcta y que el contenedor hace uso de esa red

Detenemos y eliminamos:

docker compose down -v

Después de hacer los cambios levantamos todo de nuevo:

docker compose up -d

Verificamos qué red usa ahora el contenedor:

docker inspect network-compose-bb-1

También podemos hacer:

docker exec network-compose-bb-1 ifconfig

Salida:

eth0      Link encap:Ethernet  HWaddr 02:42:AC:50:00:02
          inet addr:172.80.0.2  Bcast:172.80.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:33 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:11999 (11.7 KiB)  TX bytes:0 (0.0 B)

5. Modificar el yaml para crear otro contenedor que hará uso de la misma red net2

services:
  bb:
    image: busybox
    command: sleep infinity
    restart: always
    networks:
      - net2

  bb2:
    image: busybox
    command: sleep infinity
    restart: always
    networks:
      - net2

networks:
  net2:
    ipam:
      config:
        - subnet: 172.80.0.0/16

6. Tirar y levantar de nuevo compose. Comprobar que los contenedores están en la misma red y son accesible entre ellos

Detenemos y eliminamos:

docker compose down -v

Después de hacer los cambios levantamos todo de nuevo:

docker compose up -d

Hacemos ping de un contenedor a otro:

$ docker exec network-compose-bb-1 ping -c 3 bb2
PING bb2 (172.80.0.3): 56 data bytes
64 bytes from 172.80.0.3: seq=0 ttl=64 time=0.185 ms
64 bytes from 172.80.0.3: seq=1 ttl=64 time=0.088 ms
64 bytes from 172.80.0.3: seq=2 ttl=64 time=0.101 ms

--- bb2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.088/0.124/0.185 ms

Hacemos ping desde el otro contenedor al primero:

$ docker exec network-compose-bb2-1 ping -c 3 bb
PING bb (172.80.0.2): 56 data bytes
64 bytes from 172.80.0.2: seq=0 ttl=64 time=0.142 ms
64 bytes from 172.80.0.2: seq=1 ttl=64 time=0.090 ms
64 bytes from 172.80.0.2: seq=2 ttl=64 time=0.099 ms

--- bb ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.090/0.110/0.142 ms

7. Modifica el yaml para que el segundo contenedor se conecte a otra red diferente de net2

services:
  bb:
    image: busybox
    command: sleep infinity
    restart: always
    networks:
      - net2

  bb2:
    image: busybox
    command: sleep infinity
    restart: always
    networks:
      - net1

networks:
  net1:
  net2:
    ipam:
      config:
        - subnet: 172.80.0.0/16

8. Tirar y levantar de nuevo compose. Comprobar que efectivamente los contenedores no están en la misma red

docker exec network-compose-bb-1 ping -c3 bb2
ping: bad address 'bb2'

9. Modifica el yaml para que el segundo contenedor ahora se conecte a la net2 donde está el contenedor1 y además a la net1 externa (la que usamos en el ejercicio de redes básico). Para ello tendremos que configurarla como external:true y si el nombre no coincide con el nombre externo cambiarlo con name: net1

services:
  bb:
    image: busybox
    command: sleep infinity
    restart: always
    networks:
      - net2

  bb2:
    image: busybox
    command: sleep infinity
    restart: always
    networks:
      - net1
      - net2

networks:
  net1:
    name: net1
    external: true
  net2:
    ipam:
      config:
        - subnet: 172.80.0.0/16

10. Tirar y levantar de nuevo compose. Comprobar que los contenedores tienen las redes correctas y que tenemos acceso a los contedores de la red1 levantados de forma externa a compose

11. Modifica el yaml elimina todas las redes personalizadas y la asignación de redes en los contenedores. Pon en el contenedor1 la propiedad network_mode: bridge

services:
  bb:
    image: busybox
    command: sleep infinity
    restart: always
    network_mode: bridge

  bb2:
    image: busybox
    command: sleep infinity
    restart: always

12. Tirar y levantar de nuevo compose. ¿qué configuración de red tienen los contenedores?

docker inspect network-compose-bb-1
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "ca2555f0ebdc8ec786d99f4911b2dc17151ca8955c826345291199ec0bda559c",
                    "EndpointID": "7d467005b795e9ae7895b94458f22c9ecf3789c6c9160a37bbe6373626843c25",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }

En el segundo contenedor:

docker inspect network-compose-bb2-1
            "Networks": {
                "network-compose_default": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": [
                        "network-compose-bb2-1",
                        "bb2",
                        "95dca5a4e30e"
                    ],
                    "NetworkID": "73471d80a0b4127dc6856c93a17bb3b7f34a1be2ebb286e6a9969a0098d740dd",
                    "EndpointID": "9c8f4cee41e8016a1c04cbb8d3b4013ada5906f6b8f2834ca0fb213a7e14542a",
                    "Gateway": "172.25.0.1",
                    "IPAddress": "172.25.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:19:00:02",
                    "DriverOpts": null
                }

13. Modificar el yaml para que el container2 no tenga servicio de red. Usar network_mode

services:
  bb:
    image: busybox
    command: sleep infinity
    restart: always
    network_mode: bridge

  bb2:
    image: busybox
    command: sleep infinity
    restart: always
    network_mode: none
            "Networks": {
                "none": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "5aabf5bab278005297359d26991878dab65725bb051ffb98e6a83780ab5e1e6c",
                    "EndpointID": "09e574cb240da878d71828f43c6bb6f1bff9706f06696964532bf6fcb86f751a",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "",
                    "DriverOpts": null
                }
informatica/sistemas_operativos/cursos/docker_avanzado/networking_y_service_discovery.1697556644.txt.gz · Última modificación: por tempwin