Virtualizar en Mac

Si por alguna razón cuentas con un equipo de la marca de la manzana y buscas una alternativa para virtualizar, te recomiendo Lima ya que a diferencia de otros proyectos funciona en las arquitectura x86_64 y ARM 64.

Lima utiliza QEMU para virtualizar, la gestión se realiza a través de la linea de comandos por lo que si estás buscando una alternativa gráfica o una maquina virtual con interfaz te recomiendo UTM que funciona igualmente con QEMU.

Instalación

Para la instalación de Lima utilizaremos el gestor de paquetes de Mac llamado Homebrew, sino cuentas con él puedes instalarlo de manera fácil de la siguiente forma:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Una vez instalado el gestor de paquetes podremos instalar Lima.

$ brew install lima

Lima utiliza archivos yaml para la creación de maquinas virtuales, existe una lista de templates que pueden usarse para desplegar nuestras maquinas, estos archivos los podemos localizar en el directorio, /opt/homebrew/share/lima/templates.

Administración

Crearemos una maquina virtual con ubuntu como imagen linux y asignaremos 2 gigas de memoria y 2 cpus.

personal-mac:templates tusysadmin$ pwd
/opt/homebrew/share/lima/templates

personal-mac:templates tusysadmin$ limactl create --name linux-server --set='.cpus = 2 | .memory = "2GiB"' ubuntu-lts.yaml
? Creating an instance "linux-server" Proceed with the current configuration
INFO[0001] Attempting to download the image              arch=aarch64 digest="sha256:5167c1b13cb33274955e36332ecb7b14f02b71fd19a37a9c1a3a0f8a805ab8e5" location="https://cloud-images.ubuntu.com/releases/22.04/release-20231010/ubuntu-22.04-server-cloudimg-arm64.img"
INFO[0001] Using cache "/Users/tusysadmin/Library/Caches/lima/download/by-url-sha256/f55d2d250bd1df34e6c082a8cbfea153f1ef6a5ec8a7300dd0ab8cbc13ec946b/data"
INFO[0002] Attempting to download the nerdctl archive    arch=aarch64 digest="sha256:ea30ab544c057e3a0457194ecd273ffbce58067de534bdfaffe4edf3a4da6357" location="https://github.com/containerd/nerdctl/releases/download/v1.6.2/nerdctl-full-1.6.2-linux-arm64.tar.gz"
INFO[0002] Using cache "/Users/tusysadmin/Library/Caches/lima/download/by-url-sha256/21921213c0426e38e2f26d2844446767e2a19c0b6655c774f9e4adbb5c368d8f/data"
INFO[0002] Run `limactl start linux-server` to start the instance.

Iniciemos la maquina.

personal-mac:templates tusysadmin$ limactl start linux-server
INFO[0000] Using the existing instance "linux-server"
INFO[0000] QEMU binary "/opt/homebrew/bin/qemu-system-aarch64" seems properly signed with the "com.apple.security.hypervisor" entitlement
INFO[0001] [hostagent] hostagent socket created at /Users/tusysadmin/.lima/linux-server/ha.sock
INFO[0001] [hostagent] Starting QEMU (hint: to watch the boot progress, see "/Users/tusysadmin/.lima/linux-server/serial*.log")
INFO[0001] SSH Local Port: 50965
INFO[0001] [hostagent] Waiting for the essential requirement 1 of 5: "ssh"
INFO[0018] [hostagent] Waiting for the essential requirement 1 of 5: "ssh"
INFO[0028] [hostagent] Waiting for the essential requirement 1 of 5: "ssh"
INFO[0029] [hostagent] The essential requirement 1 of 5 is satisfied
INFO[0029] [hostagent] Waiting for the essential requirement 2 of 5: "user session is ready for ssh"
INFO[0029] [hostagent] The essential requirement 2 of 5 is satisfied
INFO[0029] [hostagent] Waiting for the essential requirement 3 of 5: "sshfs binary to be installed"
INFO[0038] [hostagent] The essential requirement 3 of 5 is satisfied
INFO[0038] [hostagent] Waiting for the essential requirement 4 of 5: "/etc/fuse.conf (/etc/fuse3.conf) to contain \"user_allow_other\""
INFO[0041] [hostagent] The essential requirement 4 of 5 is satisfied
INFO[0041] [hostagent] Waiting for the essential requirement 5 of 5: "the guest agent to be running"
INFO[0041] [hostagent] The essential requirement 5 of 5 is satisfied
INFO[0041] [hostagent] Mounting "/Users/tusysadmin" on "/Users/tusysadmin"
INFO[0041] [hostagent] Mounting "/tmp/lima" on "/tmp/lima"
INFO[0041] [hostagent] Waiting for the optional requirement 1 of 2: "systemd must be available"
INFO[0041] [hostagent] Forwarding "/run/lima-guestagent.sock" (guest) to "/Users/tusysadmin/.lima/linux-server/ga.sock" (host)
INFO[0041] [hostagent] The optional requirement 1 of 2 is satisfied
INFO[0041] [hostagent] Waiting for the optional requirement 2 of 2: "containerd binaries to be installed"
INFO[0041] [hostagent] Not forwarding TCP 127.0.0.53:53
INFO[0041] [hostagent] Not forwarding TCP 0.0.0.0:22
INFO[0041] [hostagent] Not forwarding TCP [::]:22
INFO[0047] [hostagent] The optional requirement 2 of 2 is satisfied
INFO[0047] [hostagent] Waiting for the final requirement 1 of 1: "boot scripts must have finished"
INFO[0057] [hostagent] The final requirement 1 of 1 is satisfied
INFO[0057] READY. Run `limactl shell linux-server` to open the shell.

Para entrar a la maquina.

personal-mac:~ tusysadmin$ limactl shell linux-server

tusysadmin@lima-linux-server:/Users/tusysadmin$ sudo su -

root@lima-linux-server:~# apt-get update
Hit:1 http://ports.ubuntu.com/ubuntu-ports jammy InRelease
Get:2 http://ports.ubuntu.com/ubuntu-ports jammy-updates InRelease [119 kB]
Hit:3 http://ports.ubuntu.com/ubuntu-ports jammy-backports InRelease
Get:4 http://ports.ubuntu.com/ubuntu-ports jammy-security InRelease [110 kB]
Get:5 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main arm64 Packages [1021 kB]
Get:6 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main Translation-en [248 kB]
Get:7 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe arm64 Packages [917 kB]
Fetched 2415 kB in 4s (567 kB/s)
Reading package lists... Done
root@lima-linux-server:~# htop

root@lima-linux-server:~# cat /etc/issue
Ubuntu 22.04.3 LTS \n \l

Al salir de la maquina virtual podemos listar el resto de equipos y el estado en el que se encuentran.

personal-mac:~ tusysadmin$ limactl list
NAME            STATUS     SSH                VMTYPE    ARCH       CPUS    MEMORY    DISK      DIR
docker          Stopped    127.0.0.1:0        qemu      aarch64    4       4GiB      100GiB    ~/.lima/docker
linux-server    Running    127.0.0.1:49404    qemu      aarch64    2       2GiB      100GiB    ~/.lima/linux-server
personal-mac:~ tusysadmin$

Para explorar más opciones de administración podemos usar el comando limactl -h.

Configurar interfaz puente KVM

[tusysadmin@lab ~]$ ifconfig virbr0
virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.124.1  netmask 255.255.255.0  broadcast 192.168.124.255
        ether 52:54:00:f8:5e:07  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[tusysadmin@lab ~]$ sudo nmcli con show id virbr0
connection.id:                          virbr0
connection.uuid:                        c18c5902-35cf-4da8-8360-864b6b09e922
connection.stable-id:                   --
connection.type:                        bridge
connection.interface-name:              virbr0
----
IP4.ADDRESS[1]:                         192.168.124.1/24
IP4.GATEWAY:                            --
IP4.ROUTE[1]:                           dst = 192.168.124.0/24, nh = 0.0.0.0, mt = 0
[tusysadmin@lab ~]$ sudo dnf install bridge-utils
Última comprobación de caducidad de metadatos hecha hace 1:15:12, el jue 08 feb 2024 20:18:00.
Dependencias resueltas.
================================================================================================================================================
 Paquete                              Arquitectura                   Versión                               Repositorio                     Tam.
================================================================================================================================================
Instalando:
 bridge-utils                         x86_64                         1.7.1-6.fc38                          fedora                          34 k

Resumen de la transacción
================================================================================================================================================
Instalar  1 Paquete
[tusysadmin@lab ~]$ sudo nmcli con show
NAME      UUID                                  TYPE      DEVICE
cableada  8531cd56-9e22-3a04-9f99-44ca92be00c4  ethernet  eno1
lo        0486ec18-04a3-4141-ae25-01de6f20809b  loopback  lo
SSID      51229f3b-5809-439e-a328-5b641b1a80ee  wifi      wlp0s20f0u2i2

[tusysadmin@lab ~]$ sudo nmcli con add ifname br0 type bridge con-name br0
Conexión «br0» (4f60f6ee-6003-4fa6-88e1-856af2446c8e) añadida con éxito.

[tusysadmin@lab ~]$ nmcli con show
NAME      UUID                                  TYPE      DEVICE
br0       4f60f6ee-6003-4fa6-88e1-856af2446c8e  bridge    br0
cableada  8531cd56-9e22-3a04-9f99-44ca92be00c4  ethernet  eno1
lo        0486ec18-04a3-4141-ae25-01de6f20809b  loopback  lo
SSID      51229f3b-5809-439e-a328-5b641b1a80ee  wifi      wlp0s20f0u2i2
[tusysadmin@lab ~]$

[tusysadmin@lab ~]$ sudo nmcli con add type bridge-slave ifname eno1 master br0
Conexión «bridge-slave-eno1» (7e3eb64d-faf0-4e9f-8620-4f24f286b102) añadida con éxito.

[tusysadmin@lab ~]$ nmcli con show
NAME               UUID                                  TYPE      DEVICE
br0                4f60f6ee-6003-4fa6-88e1-856af2446c8e  bridge    br0
cableada           8531cd56-9e22-3a04-9f99-44ca92be00c4  ethernet  eno1
lo                 0486ec18-04a3-4141-ae25-01de6f20809b  loopback  lo
SSID               51229f3b-5809-439e-a328-5b641b1a80ee  wifi      wlp0s20f0u2i2
bridge-slave-eno1  7e3eb64d-faf0-4e9f-8620-4f24f286b102  ethernet  --

[tusysadmin@lab ~]$ sudo nmcli con down cableada
La conexión «cableada» se desactivó correctamente (ruta activa D-Bus: /org/freedesktop/NetworkManager/ActiveConnection/3)

[tusysadmin@lab ~]$ sudo nmcli con up br0
La conexión se ha activado correctamente (master waiting for slaves) (ruta activa D-Bus: /org/freedesktop/NetworkManager/ActiveConnection/7)

[tusysadmin@lab ~]$ sudo nmcli con show
NAME               UUID                                  TYPE      DEVICE
br0                39c7beb8-6b2f-4094-b732-4484cbadef11  bridge    br0
lo                 f0bf6f96-1ffa-4770-a620-0fa0a6e78575  loopback  lo
SSID               51229f3b-5809-439e-a328-5b641b1a80ee  wifi      wlp0s20f0u2i2
bridge-slave-eno1  5ec11066-d8fb-42c9-a949-88c2b0c10820  ethernet  eno1
cableada           534d9e32-6edf-4e00-9e53-962abd1bec30  ethernet  --


[tusysadmin@lab ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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 noprefixroute
       valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether 10:62:e5:19:83:60 brd ff:ff:ff:ff:ff:ff
    altname enp0s31f6
3: wlp0s20f0u2i2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e0:e1:a9:3a:60:e4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.20/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp0s20f0u2i2
       valid_lft 85579sec preferred_lft 85579sec
    inet6 fe80::b145:75ae:fc15:38f4/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 10:62:e5:19:83:60 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.21/24 brd 192.168.1.255 scope global dynamic noprefixroute br0
       valid_lft 85580sec preferred_lft 85580sec
    inet6 fe80::38a6:e06:84ee:34a7/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

[tusysadmin@lab ~]$ sudo brctl show
bridge name	bridge id		STP enabled	interfaces
br0		8000.1062e5198360	no		eno1
[tusysadmin@lab ~]$

Gestión de interfaces con nmcli

La utilidad nmcli (NetworkManager Command Line Interface) es utilizada para gestionar el estado de las redes. Con esta herramienta podemos, crear, editar, activar, eliminar y desactivar conexiones de red. Aprender el uso de esta herramienta es necesario ya que las nuevas versiones de Red Hat (9) y sus Forks (Rocky y Alma) han depreciado el funcionamiento de las interfaces ifcfg.

La sintaxis para usar este comando es la siguiente:

nmcli [OPTIONS] OBJECT { COMMAND | help }

Listar información de las interfaces

[tusysadmin@lab ~]$ sudo nmcli con show
NAME      UUID                                  TYPE      DEVICE
cableada  8531cd56-9e22-3a04-9f99-44ca92be00c4  ethernet  eno1
lo        3115100c-122b-482b-8653-fe4802d55f2e  loopback  lo
SSID      51229f3b-5809-439e-a328-5b641b1a80ee  wifi      wlp0s20f0u2i2
virbr0    88690a18-991b-4ec5-81fb-83bdc24aca57  bridge    virbr0

Las interfaces mostradas son de un equipo con cuenta con wifi y cable de red activos, la interfaz virbr0 corresponde al servicio de libvirtd ya que el mencionado dispositivo es un anfitrión de maquinas virtuales. De ser necesario, puede mostrarse la información de una interfaz en concreto:

[tusysadmin@lab ~]$ sudo nmcli con show id cableada
connection.id:                          cableada
connection.uuid:                        8531cd56-9e22-3a04-9f99-44ca92be00c4
connection.stable-id:                   --
connection.interface-name:              eno1
connection.autoconnect:                 sí
------
IP4.ADDRESS[1]:                         192.168.1.21/24
IP4.GATEWAY:                            192.168.1.1

Establecer IP

[tusysadmin@lab ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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 noprefixroute
       valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 10:62:e5:19:83:60 brd ff:ff:ff:ff:ff:ff
    altname enp0s31f6
    inet 192.168.1.21/24 brd 192.168.1.255 scope global dynamic noprefixroute eno1
       valid_lft 71830sec preferred_lft 71830sec
    inet6 fe80::4845:e957:bf2b:b3f4/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: wlp0s20f0u2i2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e0:e1:a9:3a:60:e4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.20/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp0s20f0u2i2
       valid_lft 71830sec preferred_lft 71830sec
    inet6 fe80::b145:75ae:fc15:38f4/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

[tusysadmin@lab ~]$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        0.0.0.0         UG    100    0        0 eno1
default         _gateway        0.0.0.0         UG    600    0        0 wlp0s20f0u2i2
192.168.1.0     0.0.0.0         255.255.255.0   U     100    0        0 eno1
192.168.1.0     0.0.0.0         255.255.255.0   U     600    0        0 wlp0s20f0u2i2
192.168.124.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0
Ipaddress = 192.168.1.15
Netmask   = 255.255.255.0
Gateway   = 192.168.1.1
DNS       = 80.80.80.80
[tusysadmin@lab ~]$ sudo nmcli con modify cableada ipv4.method manual
[tusysadmin@lab ~]$ sudo nmcli con modify cableada ipv4.addresses 192.168.1.15/24
[tusysadmin@lab ~]$ sudo nmcli con modify cableada ipv4.gateway 192.168.1.1
[tusysadmin@lab ~]$ sudo nmcli con modify cableada ipv4.dns 80.80.80.80
[tusysadmin@lab ~]$ sudo nmcli con up cableada
Conexión activada con éxito (ruta activa D-Bus: /org/freedesktop/NetworkManager/ActiveConnection/7)
[tusysadmin@lab ~]$
[tusysadmin@lab ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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 noprefixroute
       valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 10:62:e5:19:83:60 brd ff:ff:ff:ff:ff:ff
    altname enp0s31f6
    inet 192.168.1.15/24 brd 192.168.1.255 scope global noprefixroute eno1
       valid_lft forever preferred_lft forever
    inet6 fe80::4845:e957:bf2b:b3f4/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
[tusysadmin@lab ~]$ ping -c3 google.com
PING google.com (142.250.74.206) 56(84) bytes of data.
64 bytes from fra24s02-in-f14.1e100.net (142.250.74.206): icmp_seq=1 ttl=48 time=152 ms
64 bytes from fra24s02-in-f14.1e100.net (142.250.74.206): icmp_seq=2 ttl=48 time=152 ms
64 bytes from fra24s02-in-f14.1e100.net (142.250.74.206): icmp_seq=3 ttl=48 time=152 ms

--- google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 151.663/151.773/151.925/0.111 ms
[tusysadmin@lab ~]$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        0.0.0.0         UG    100    0        0 eno1
192.168.1.0     0.0.0.0         255.255.255.0   U     100    0        0 eno1
[tusysadmin@lab ~]$ nslookup google.com
Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
Name:	google.com
Address: 142.250.74.206
Name:	google.com
Address: 2a00:1450:4001:803::200e

[tusysadmin@lab ~]$

Crear contenedor desde archivo

Como ya lo hemos mencionado, las imágenes de los contenedores las podemos encontrar en el repositorio Docker Hub. Sin embargo; en ocasiones querremos usar nuestras propias aplicaciones o simplemente adaptarlo a nuestras necesidades.

Para hacer eso requerimos crear un Dockerfile, el siguiente archivo nos ayudara a crear un contenedor que ejecutara un archivo bash.

FROM ubuntu

LABEL maintainer="Tusysadmin.net"

USER root

COPY ./primer_archivo.bash /

RUN apt -y update
RUN apt -y install curl bash
RUN chmod 755 /primer_archivo.bash

USER nobody

ENTRYPOINT [ "/primer_archivo.bash" ]

La palabra FROM es para indicar que imagen utilizaremos, sino esta descargada la descargara del repositorio. LABEL, es solo la «etiqueta» que usamos como descripción; USER, es el usuario que ejecutará los comandos que le siguen. COPY y RUN serán las comandos que correrá nuestro usuario root.

El archivo primer_archivo.bash sera copiado al contenedor, al encontrarse en la misma ruta de Dockerfile no es necesario especificar una ruta diferente. RUN, actualiza el contenedor, instala curl y bash y otorga permisos al archivo copiado, es importante usar el gestor de paquetes correspondiente de la imagen sino mostrará error.

Construyamos la imagen.

[tusysadmin@local contenedores]$ ls
Dockerfile  primer_archivo.bash

[tusysadmin@local contenedores]$ docker build -t primer_imagen .
[+] Building 0.5s (10/10) FINISHED
 => [internal] load build definition from Dockerfile                                                                                      0.0s
 => => transferring dockerfile: 334B                                                                                                      0.0s
 => [internal] load .dockerignore                                                                                                         0.0s
 => => transferring context: 2B                                                                                                           0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                                          0.4s
 => [internal] load build context                                                                                                         0.0s
 => => transferring context: 99B                                                                                                          0.0s
 => [1/5] FROM docker.io/library/ubuntu@sha256:ec050c32e4a6085b423d36ecd025c0d3ff00c38ab93a3d71a460ff1c44fa6d77                           0.0s
 => => resolve docker.io/library/ubuntu@sha256:ec050c32e4a6085b423d36ecd025c0d3ff00c38ab93a3d71a460ff1c44fa6d77                           0.0s
 => CACHED [2/5] COPY ./primer_archivo.bash /                                                                                             0.0s
 => CACHED [3/5] RUN apt -y update                                                                                                        0.0s
 => CACHED [4/5] RUN apt -y install curl bash                                                                                             0.0s
 => CACHED [5/5] RUN chmod 755 /primer_archivo.bash                                                                                       0.0s
 => exporting to image                                                                                                                    0.0s
 => => exporting layers                                                                                                                   0.0s
 => => writing image sha256:ea88c13fe6d7ac18e8032717deaaf4ed18f049c4b887dcf21312c14874018151                                              0.0s
 => => naming to docker.io/library/primer_imagen

Esta es la forma mas simple de construir una imagen. Si tuvieramos un archivo con un nombre diferente a Dockerfile tendriamos que usar la opción -f seguida del nombre del archivo. Usamos un punto al final para especificar que usaremos el repositorio local.

[tusysadmin@local contenedores]$ docker images
REPOSITORY      TAG       IMAGE ID       CREATED             SIZE
primer_imagen   latest    ea88c13fe6d7   About an hour ago   116MB

[tusysadmin@local contenedores]$ docker run primer_imagen
Este es tu primer contenedor construido con Dockerfile
[tusysadmin@local contenedores]$

Como puede observarse la imagen ha sido creada y cuando se ejecuta hace lo único para lo cual ha sido construida, es decir ejecutar nuestro primer_archivo.bash.

Redes con docker

Al igual que en las maquinas virtuales, los contenedores pueden conectarse entre ellos y a través del host anfitrión para crear redes internas y/o publicar servicios.

Para ilustrar como funcionan los puertos, creemos un contender de ubuntu con los puertos 55678 y 55679 abiertos.

docker run --rm -ti -p 55678:55678 -p 55679:55679 --name echo-server ubuntu:14.04 bash

Este comando abre los mencionados puertos tanto de entrada como de salida, para ilustrar lo que estamos haciendo usemos el comando Netcat.

La terminal de la derecha es el contenedor que es quien inicia Netcat. Mientras tanto, lo escrito en la parte superior izquierda aparece en la terminal inferior por la conexión que se hace a través del contenedor.

Este escaneo es estático ya que establecimos los puertos de entrada y de salida, es posible establecer unicamente los de entrada y los de salida serán dinámicos.

[tusysadmin@local ~]$ docker run --rm -ti -p 55678 -p 55679 --name echo-server ubuntu:14.04 bash

Para saber los puertos utilizados usamos la opción port.

[tusysadmin@local ~]$ docker port echo-server
55679/tcp -> 0.0.0.0:49153
55679/tcp -> :::49153
55678/tcp -> 0.0.0.0:49154
55678/tcp -> :::49154

En este caso los puertos a los que tenemos que hacer la conexión son 49153 y 49154.

Para saber las redes con las que contamos.

[tusysadmin@local ~]$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
2acddd4abdcd   bridge    bridge    local
8e60720c5590   host      host      local
b6c7de3fbd09   none      null      local

Estas tres redes son creadas al momento por default al momento de iniciar el servicio docker; sino se especifica lo contrario la red bridge es usada por todos los contenedores, host es para aislar contenedores a una red y none es para especificar que los contenedores no tienen red.

Crearemos un nueva red para conectar algunos contenedores.

[tusysadmin@local ~]$ docker network create taller
51ba550801cff8cf879630bb1925266d9ea45da375d6336c73f2b6e9a779926b

Creamos dos contenedores conectados a esa red.

[tusysadmin@local ~]$ docker run --rm -ti --network taller --name front ubuntu:14.04 bash
[tusysadmin@local ~]$ docker run --rm -ti --network taller --name back ubuntu:14.04 bash

Ping entre contenedores

Image 1 De 2

Como se observa en estas imágenes, existe una conexión entre contenedores solo con usar la misma red al momento de la declaración y es a través del nombre que pueden conectarse. Hagamos la cosas mas interesantes agregando un nueva red que solo pueda conectarse al back.

[tusysadmin@local ~]$ docker network create backsonly
a8f856b310666d071249bef328df3bbfbd2fa3e183923320cbb2425713f12720

[tusysadmin@local ~]$ docker network connect backsonly back

Crearemos un tercer contenedor que solo esté conectado a esta red el cual podrá hacer ping a back pero no a front.

Red separada

Image 1 De 1

El contenedor back por estar en ambas redes puede conectarse a ambos contenedores, pero entre ellos no es posible la conexión.

Usando contenedores

Una vez que tenemos instalado docker en nuestro sistema operativo, comenzamos con los comandos básicos de administración. En nuestra interfaz; al igual que otras utilidades de Linux, docker tiene una opción de ayuda.

[tusysadmin@local ~]$ docker --help

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Common Commands:
  run         Create and run a new container from an image
  exec        Execute a command in a running container
  ps          List containers
  build       Build an image from a Dockerfile
  pull        Download an image from a registry
  push        Upload an image to a registry
  images      List images
  login       Log in to a registry
  logout      Log out from a registry
  search      Search Docker Hub for images
  version     Show the Docker version information
  info        Display system-wide information

Buscar una imagen.

[tusysadmin@local ~]$ docker search hello-world | head -5
NAME                                       DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
hello-world                                Hello World! (an example of minimal Dockeriz…   2081      [OK]
rancher/hello-world                                                                        4
okteto/hello-world                                                                         0
golift/hello-world                         Hello World Go-App built by Go Lift Applicat…   0

Descargar una imagen.

[tusysadmin@local ~]$ docker image pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
db76c1f8aa17: Pull complete
Digest: sha256:ec050c32e4a6085b423d36ecd025c0d3ff00c38ab93a3d71a460ff1c44fa6d77
Status: Downloaded newer image for ubuntu:latest

Listar imágenes.

[tusysadmin@local ~]$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       latest    a2f229f811bf   12 days ago   69.2MB

Recordemos que las imágenes de los contenedores se encuentran en un repositorio, al usar image pull estamos descargando la última versión de la imagen de ubuntu, cuando queramos iniciar un contenedor con esta imagen usamos el comando run y algunos parámetros extras en caso de ser necesario.

[tusysadmin@local ~]$ docker run -d -ti ubuntu bash
bc31db28981c73f1c112e2e23f35d843730aac35f6e46620de80d2f9953562fb

[tusysadmin@local ~]$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
bc31db28981c   ubuntu    "bash"    32 minutes ago   Up 32 minutes             eloquent_goldberg

Lo que hicimos con este comando es lanzar un contenedor con la imagen de ubuntu. El contenedor está corriendo y así seguirá hasta que sea detenido con el comando run o entrando al contenedor internamente lo terminemos. Para entrar al contenedor podemos usar attach.

[tusysadmin@local ~]$ docker attach eloquent_goldberg

root@bc31db28981c:/# cat /etc/issue
Ubuntu 22.04 LTS \n \l

root@bc31db28981c:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

Estando dentro del contenedor y escribir exit termina con el contenedor. Si quisiera salir del contenedor sin terminarlo tendría que usar las teclas Ctrl +p seguidas de Ctrl +q.

root@bc31db28981c:/# exit
exit
[tusysadmin@local ~]$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Otra forma para ingresar a un contenedor es usando la opción exec, en este caso; al escribir exit el contenedor no dejara de ejecutarse.

[tusysadmin@local ~]$ docker run -d -ti ubuntu bash
0681487d52deaa363911203bb8094646d4c55d08cb2a095a4d56e759e4f07125

[tusysadmin@local ~]$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
0681487d52de   ubuntu    "bash"    7 seconds ago   Up 5 seconds             determined_wescoff

[tusysadmin@local ~]$ docker exec -ti  determined_wescoff bash

root@0681487d52de:/# ls 
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

root@0681487d52de:/# exit
exit
[tusysadmin@local ~]$ docker ps 
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
0681487d52de   ubuntu    "bash"    16 minutes ago   Up 16 minutes             determined_wescoff

Para terminar el contenedor de forma definitiva usamos el comando kill.

[tusysadmin@local ~]$ docker kill determined_wescoff
determined_wescoff

[tusysadmin@local ~]$ docker ps -l
CONTAINER ID   IMAGE     COMMAND   CREATED        STATUS                        PORTS     NAMES
0681487d52de   ubuntu    "bash"    12 hours ago   Exited (137) 14 seconds ago             determined_wescoff

Instalar Docker en Fedora 36

Docker es un proyecto de código abierto que permite desplegar aplicaciones dentro de contenedores. Al hacerlo de esta manera y no por maquinas virtuales se evita la sobrecarga de recursos.

Comencemos con la instalación y configuración del repositorio.

[tusysadmin@local ~]$ sudo dnf -y install dnf-plugins-core
[tusysadmin@local ~]$ sudo dnf config-manager \
    --add-repo \
    https://download.docker.com/linux/fedora/docker-ce.repo

tusysadmin@local ~]$ sudo dnf config-manager --set-enabled docker-ce-nightly

Instalamos los paquetes e iniciamos el servicio .

~]$ sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

[tusysadmin@local ~]$ sudo systemctl start docker

[tusysadmin@local ~]$ sudo docker version 
Client: Docker Engine - Community
 Version:           20.10.16
 API version:       1.41
 Go version:        go1.17.10
 Git commit:        aa7e414
 Built:             Thu May 12 09:16:46 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Probemos que docker está funcionando.

[tusysadmin@local ~]$ sudo docker run hello-world

Para una administración gráfica y practica podemos instalar docker-desktop, bastará con descargar el paquete rpm de la pagina. Una vez descargado, procedemos a instalar.

]$ sudo dnf install -y docker-desktop-*.rpm

El paquete funciona igual que otro servicio, así que bastará con iniciarse y si así se desea habilitarse.

]$ systemctl --user start docker-desktop

Y con estos sencillos pasos ya tenemos docker instalado en nuestro Fedora 36, listo para empezar a desplegar contenedores.

Pool iSCSI para KVM

KVM puede utilizar iSCSI como backend de almacenamiento, si se cuenta con una SAN (Storage Area Network) pueden asignarse LUN’s (Logical Unit Numbers) y presentarlas a las máquinas virtuales. El pool es creado en el almacenamiento pero libvirt no puede crearlo o eliminarlo.

Instalación Servidor iSCSI


Hostname: target.local
IP Address: 192.168.100.127

Comenzamos con la instalación.

]$ sudo yum install -y targetd targetcli
]$ sudo systemctl enable --now target

Habilitamos el servicio en el cortafuegos.

]$ sudo firewall-cmd --add-service=iscsi-target --permanent
]$ sudo firewall-cmd --reload
success

En este punto ya contamos con un lvm de 30 GB sin montar, en este caso /dev/vg1/lv1.

[tusysadmin@target ~]$ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0          11:0    1 1024M  0 rom
vda         252:0    0    6G  0 disk
├─vda1      252:1    0    5G  0 part
│ ├─rl-root 253:0    0  4.4G  0 lvm  /
│ └─rl-swap 253:1    0  616M  0 lvm  [SWAP]
└─vda2      252:2    0    1G  0 part /boot
vdb         252:16   0   30G  0 disk
└─vdb1      252:17   0   30G  0 part
  └─vg1-lv1 253:2    0   30G  0 lvm

Lanzamos la utilidad targetcli.

[root@target ~]# targetcli
targetcli shell version 2.1.53
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.

/> ls
o- / ............................................................... [...]
  o- backstores .................................................... [...]
  | o- block ........................................ [Storage Objects: 0]
  | o- fileio ....................................... [Storage Objects: 0]
  | o- pscsi ........................................ [Storage Objects: 0]
  | o- ramdisk ...................................... [Storage Objects: 0]
  o- iscsi .................................................. [Targets: 0]
  o- loopback ............................................... [Targets: 0]
/>

Crearemos un dispositivo de bloques, esto lo hacemos dentro de backstores/block.

/> backstores/block create vms_store /dev/vg1/lv1
Created block storage object vms_store using /dev/vg1/lv1.
/>

Creamos el IQN (iSCSI Qualified Name).

/> cd iscsi
/iscsi> create iqn.2022-05.com.target:vms
Created target iqn.2022-05.com.target:vms.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.
/iscsi>

Creamos el LUN asociado al bloque vms_store.

/iscsi> cd iqn.2022-05.com.target:vms/tpg1
/iscsi/iqn.20...rget:vms/tpg1> luns/ create /backstores/block/vms_store
Created LUN 0.
/iscsi/iqn.20...rget:vms/tpg1>

Ahora creamos una ACL (Access Control List) en el que indicamos el IQN del cliente al que presentaremos la LUN.

/iscsi/iqn.20...rget:vms/tpg1> acls/ create iqn.2022-05.com.iniciator:vms
Created Node ACL for iqn.2022-05.com.iniciator:vms
Created mapped LUN 0.
/iscsi/iqn.20...rget:vms/tpg1>

Salimos de targetcli y verificamos que el puerto este abierto.

[tusysadmin@target ~]$ ss -an | grep 3260
tcp    LISTEN     0      256       *:3260                  *:*

Configurar iniciador

Ahora toca configurar el iniciador iSCSI en nuestro servidor de máquinas virtuales para posteriormente presentarlo a KVM.

[tusysadmin@localhost ~]$ sudo yum install iscsi-initiator-utils -y

Editamos el archivo initiatorname.iscsi

~]$ sudo vi /etc/iscsi/initiatorname.iscsi

En este archivo ponemos el nombre que anteriormente agregamos en la ACL.

InitiatorName=iqn.2022-05.com.iniciator:vms

Probamos la configuración.

[tusysadmin@localhost ~]$ sudo iscsiadm -m discovery -t st -p target.local
192.168.100.127:3260,1 iqn.2022-05.com.target:vms

Hacemos el login al target.

~]$ sudo iscsiadm --mode node --targetname iqn.2022-05.com.target:vms --portal target.local --login
Logging in to [iface: default, target: iqn.2022-05.com.target:vms, portal: 192.168.100.127,3260]
Login to [iface: default, target: iqn.2022-05.com.target:vms, portal: 192.168.100.127,3260] successful.

Crear el pool

Con la conexión establecida a nuestra servidor de maquina virtuales ya podemos crear el pool iSCSI y usarlo en nuestras maquinas virtuales. Creamos el archivo iscsipool.xml con el siguiente contenido.

<pool type='iscsi'>
    <name>iscsipool</name>
    <source>
        <host name='192.168.100.127'/>
        <device path='iqn.2022-05.com.target:vms'/>
    </source>
    <initiator>
	    <iqn name='iqn.2022-05.com.iniciator:vms' />
    </initiator>
    <target>
        <path>/dev/disk/by-path</path>
    </target>
</pool>

Básicamente es la información del target y del iniciador lista para ser agregada a KVM. Ahora definimos, iniciamos y auto iniciamos el pool.

[tusysadmin@localhost ~]$ sudo virsh pool-define --file iscsipool.xml
El grupo iscsipool ha sido definido desde iscsipool.xml

[tusysadmin@localhost ~]$ sudo virsh pool-start --pool iscsipool 
Se ha iniciado el grupo iscsipool

[tusysadmin@localhost ~]$ sudo virsh pool-autostart --pool iscsipool
El grupo iscsipool ha sido marcado como iniciable automáticamente

Listamos el pool la información de el mismo.

[tusysadmin@localhost ~]$ sudo virsh pool-info iscsipool
Nombre:         iscsipool
UUID:           80ba818f-14da-4c77-aee4-55f82dcefc34
Estado:         ejecutando
Persistente:    si
Autoinicio:     si
Capacidad:      30.00 GiB
Ubicación:      30.00 GiB
Disponible:     0.00 B

Con esto, el pool ya puede ser usado en KVM como otro pool para presentarse a las maquinas virtuales.

Web de alta disponibilidad con GlusterFS

En posts anteriores creamos un servidor web de alta disponibilidad usando Pacemaker y un servidor de archivos distribuidos con GlusterFS. En está ocasión uniremos un ambos proyectos para que tengan un mayor sentido.

En cada uno de los servidores involucrados usamos el siguiente archivo /etc/hosts:

192.168.100.117 www1.cluster www1
192.168.100.114 www2.cluster www2
192.168.100.122 nodo1.cluster nodo1
192.168.100.127 nodo2.cluster nodo2

Para hacerlos funcionar, instalamos el cliente glusterfs en los servidores web. Recordemos que estos servidores están funcionando en una distribución Rocky Linux por lo que hay que crear el repo /etc/yum.repos.d/CentOS-Gluster-9.repo.

[centos-gluster9]
name=CentOS-$releasever - Gluster 9
baseurl=https://dl.rockylinux.org/vault/centos/8.5.2111/storage/x86_64/gluster-9/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Storage

Para posteriormente instalar los paquetes que nos permitirán montar el servidor de archivos.

sudo yum install glusterfs glusterfs-libs glusterfs-client-xlators

En ambos servidores web montamos el sistema

~]$ sudo mount -t glusterfs nodo1.cluster:/volume_mirror /var/www/
[tusysadmin@www1 ~]$ df -h
S.ficheros                   Tamaño Usados  Disp Uso% Montado en
devtmpfs                       388M      0  388M   0% /dev
tmpfs                          405M    47M  358M  12% /dev/shm
tmpfs                          405M   5.7M  399M   2% /run
tmpfs                          405M      0  405M   0% /sys/fs/cgroup
/dev/mapper/rl-root            4.3G   2.2G  1.9G  54% /
/dev/vda2                      976M   274M  636M  31% /boot
tmpfs                           81M      0   81M   0% /run/user/0
nodo1.cluster:/volume_mirror    20G   238M   20G   2% /var/www

Para montar el sistema de archivos de forma automática al iniciar el servidor.

sudo echo "nodo1.cluster:/volume_mirror /var/www glusterfs defaults,_netdev 1 2" >> /etc/fstab

De esta forma contamos con alta disponibilidad a nivel sistema de archivos y servicios web ya que hemos se han integrado ambos proyectos.

Instalar servidor web con alta disponibilidad

Contar con un sitio web con un alto porcentaje de disponibilidad es alcanzable cuando el sitio no se encuentra en un solo servidor. Al evitar un único punto de falla el sitio puede permanecer visible para los usuarios.

En este post aprenderemos como implementar Pacemaker en Rocky Linux con un servidor web Apache. Estos son los servidores que usaremos en nuestro ambiente.

192.168.100.117 www1.cluster www1
192.168.100.114 www2.cluster www2

Comenzamos la instalación de paquetes en ambos servidores y habilitamos el servicio.

~]$ sudo yum install -y pacemaker pcs resource-agents
~]$ sudo systemctl enable pcsd.service
~]$ sudo systemctl start pcsd.service

Habilitamos la aplicación en el firewall.

]$ sudo firewall-cmd --permanent --add-service=high-availability
]$ sudo firewall-cmd --reload

Con la instalación de los paquetes se creó el usuario hacluster, es necesario establecer la contraseña a este usuario ya que la necesitaremos para crear la conexión entre los servidores.

~]$ sudo passwd hacluster

Con todo lo anterior terminado ya podemos crear el cluster.

[tusysadmin@www1 ~]$ sudo pcs host auth www1 www2 -u hacluster
Password: 
www2: Authorized
www1: Authorized
[tusysadmin@www1 ~]$ sudo pcs cluster setup web www1 www2
No addresses specified for host 'www1', using 'www1'
No addresses specified for host 'www2', using 'www2'
Destroying cluster on hosts: 'www1', 'www2'...
www1: Successfully destroyed cluster
www2: Successfully destroyed cluster
Requesting remove 'pcsd settings' from 'www1', 'www2'
www1: successful removal of the file 'pcsd settings'
www2: successful removal of the file 'pcsd settings'
Sending 'corosync authkey', 'pacemaker authkey' to 'www1', 'www2'
www1: successful distribution of the file 'corosync authkey'
www1: successful distribution of the file 'pacemaker authkey'
www2: successful distribution of the file 'corosync authkey'
www2: successful distribution of the file 'pacemaker authkey'
Sending 'corosync.conf' to 'www1', 'www2'
www1: successful distribution of the file 'corosync.conf'
www2: successful distribution of the file 'corosync.conf'
Cluster has been successfully set up

Habilitamos e iniciamos el cluster.

[tusysadmin@www1 ~]$ sudo pcs cluster start --all
www2: Starting Cluster...
www1: Starting Cluster...
[tusysadmin@www1 ~]$ sudo pcs cluster enable --all
www1: Cluster Enabled
www2: Cluster Enabled
[tusysadmin@www1 ~]$ sudo pcs cluster status
Cluster Status:
 Cluster Summary:
   * Stack: corosync
   * Current DC: www2 (version 2.1.0-8.el8-7c3f660707) - partition with quorum
   * Last updated: Wed Jan 26 21:01:54 2022
   * Last change:  Wed Jan 26 16:44:48 2022 by hacluster via crmd on www2
   * 2 nodes configured
   * 0 resource instances configured
 Node List:
   * Online: [ www1 www2 ]

PCSD Status:
  www1: Online
  www2: Online

El cluster cuenta con dos nodos pero lo correcto sería que contara con 3 para poder tener Quorum y «tomar decisiones» con respecto a la disponibilidad del cluster. Si se tienen 3 nodos y uno no se encuentra disponible se conservan la mayoría de los nodos. Como no contamos con un tercer nodo no es necesario tener habilitado el STONITH (Shoot The Other Node In The Head).

[tusysadmin@www1 ~]$ sudo pcs property set no-quorum-policy=ignore
[tusysadmin@www1 ~]$ sudo pcs property set stonith-enabled=false

La disponibilidad del servicio web se hace a través de una IP flotante; esta IP estará asignada a uno de los nodos pero cuando éste no se encuentre disponible la IP pasará (flotará) al otro nodo. Al no afectar la visibilidad del sitio esta falla pasa desapercibida por los usuarios.

sudo pcs resource create virtual_ip ocf:heartbeat:IPaddr2 ip=192.168.100.110 cidr_netmask=24 op monitor interval=30s

La IP 192.168.100.110 es el recurso asignado en nuestro cluster y de momento se encuentra en el servidor www1, al detenerse el servicio o estar fuera de linea este servidor dicha IP cambiara a www2.

www1 con la IP

Image 1 De 3

En ambos servidores instalamos, habilitamos y permitimos el tráfico en el firewall.

~]$ sudo yum install httpd -y
~]$ sudo systemctl enable --now httpd
~]$ sudo firewall-cmd --permanent --add-service http
~]$ sudo firewall-cmd --reload

Editamos el Logrotate para denegar el uso de systemd en el cluster

/var/log/httpd/*log {
    missingok
    notifempty
    sharedscripts
    delaycompress
    postrotate
#        /bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true

    /usr/sbin/httpd -f /etc/httpd/conf/httpd.conf -c "PidFile /var/run/httpd/httpd.pid" -k graceful > /dev/null 2>/dev/null || true

    endscript
}

Al archivo de configuración de Apache agregamos la ruta del identificador del proceso.

PidFile /var/run/httpd/httpd.pid

Agregamos un nuevo recurso llamado webserver

~]$ sudo pcs resource create webserver apache configfile="/etc/httpd/conf/httpd.conf" 

[tusysadmin@www1 ~]$ sudo pcs resource status
  * Resource Group: apache:
    * virtual_ip	(ocf::heartbeat:IPaddr2):	 Started www1
  * webserver	(ocf::heartbeat:apache):	 Started www2

La IP virtual se encuentra en el nodo www1 pero el servicio web estará respondiendo en el nodo www2

[tusysadmin@www2 ~]$ netstat -ant | grep :80
tcp6       0      0 :::80                   :::*                    LISTEN     
tcp6       0      0 ::1:54942               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:54940               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:54946               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:54938               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:54936               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:54944               ::1:80                  TIME_WAIT 

Si detenemos el nodo www2 el tráfico http pasará al nodo www1.

[tusysadmin@www1 ~]$ sudo pcs node standby www2

[tusysadmin@www1 ~]$ sudo pcs resource status
[sudo] password for tusysadmin: 
  * Resource Group: apache:
    * virtual_ip	(ocf::heartbeat:IPaddr2):	 Started www1
  * webserver	(ocf::heartbeat:apache):	 Started www1

[tusysadmin@www1 ~]$ netstat -ant | grep :80
tcp6       0      0 :::80                   :::*                    LISTEN     
tcp6       0      0 ::1:39616               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:39626               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:39624               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:39618               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:39620               ::1:80                  TIME_WAIT  
tcp6       0      0 ::1:39622               ::1:80                  TIME_WAIT 

Él ultimo detalle que faltaría a nuestro cluster sería el de integrar un sistema de archivos para que los archivos de nuestro sitio web fueran los mismos, para esto se pudiera usar GlusterFS, NFS o iSCSI.

« Entradas anteriores

© 2025

Tema por Anders NorenArriba ↑