NVIDIA BlueField 2: emulación NVMe

Fuente de la imagen: los

principales proveedores de nube de NVIDIA conectan unidades virtuales a servidores físicos dedicados. Pero si observa el sistema operativo del servidor, habrá un disco físico con el nombre del proveedor en el campo "fabricante". Hoy analizaremos cómo esto es posible.



¿Qué es Smart NIC?



En el corazón de esta "magia" se encuentran las tarjetas de red inteligentes (NIC inteligentes). Estas tarjetas de red tienen su propio procesador, RAM y almacenamiento. De hecho, se trata de un miniservidor en forma de tarjeta PCIe. La tarea principal de las tarjetas inteligentes es descargar la CPU de las operaciones de E / S.



En este artículo hablaremos sobre un dispositivo específico: NVIDIA BlueField 2. NVIDIA llama a dichos dispositivos DPU (Unidad de procesamiento de datos), cuyo propósito el fabricante ve es "liberar" al procesador central de una variedad de tareas de infraestructura: almacenamiento, redes, seguridad de la información e incluso gestión de host.



Tenemos a nuestra disposición un dispositivo que parece una tarjeta de red 25GE normal, pero tiene un procesador ARM Cortex-A72 de ocho núcleos con 16 GB de RAM y 64 GB de memoria eMMC permanente.



Además, los conectores Mini-USB, NC-SI y RJ-45 son visibles. El primer conector está destinado únicamente a la depuración y no se utiliza en soluciones de productos. NC-SI y RJ-45 le permiten conectarse al módulo BMC del servidor a través de los puertos de la tarjeta.



Basta de teoría, es hora de lanzarse.



Primer comienzo



Después de instalar la tarjeta de red, el primer inicio del servidor será inusualmente largo. El caso es que el firmware UEFI del servidor sondea los dispositivos PCIe conectados y la tarjeta de red inteligente bloquea este proceso hasta que se inicia. En nuestro caso, el proceso de arranque del servidor tomó aproximadamente dos minutos.



Después de iniciar el sistema operativo del servidor, puede ver dos puertos de la tarjeta de red inteligente.



root@host:~# lspci
98:00.0 Ethernet controller: Mellanox Technologies MT42822 BlueField-2 integrated ConnectX-6 Dx network controller (rev 01)
98:00.1 Ethernet controller: Mellanox Technologies MT42822 BlueField-2 integrated ConnectX-6 Dx network controller (rev 01)
98:00.2 DMA controller: Mellanox Technologies MT42822 BlueField-2 SoC Management Interface (rev 01)
      
      





En este punto, la tarjeta de red inteligente se comporta como una normal. Para interactuar con la tarjeta, debe descargar e instalar los controladores BlueField desde la página NVIDIA DOCA SDK . Al final del proceso, el instalador le pedirá que reinicie el servicio openibd para que se carguen los controladores instalados. Reiniciar:



/etc/init.d/openibd restart
      
      





Si todo se hizo correctamente, aparecerá una nueva interfaz de red tmfifo_net0 en el sistema operativo .



root@host:~# ifconfig tmfifo_net0
tmfifo_net0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::21a:caff:feff:ff02  prefixlen 64  scopeid 0x20<link>
        ether 00:1a:ca:ff:ff:02  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 13  bytes 1006 (1.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
      
      





De forma predeterminada, BlueField es 192.168.100.2/24, por lo que asignamos 192.168.100.1/24 a la interfaz tmfifo_net0. Luego iniciamos el servicio rshim y lo ponemos en carga automática.



systemctl enable rshim
systemctl start rshim
      
      





Después de eso, el acceso al sistema operativo de la tarjeta desde el servidor es posible de dos maneras:



  • a través de la interfaz SSH y tmfifo_net0 ;
  • a través de la consola: el dispositivo de caracteres / dev / rshim0 / console .


El segundo método funciona independientemente del estado del sistema operativo de la tarjeta.



También son posibles otros métodos de conexión remota al sistema operativo de la tarjeta, que no requieren acceso al servidor en el que está instalada la tarjeta:



  • a través de SSH a través del puerto mgmt fuera de banda de 1 GbE o mediante interfaces de enlace ascendente (incluidas aquellas con soporte de arranque PXE);
  • acceso a la consola a través de un puerto RS232 dedicado;
  • Interfaz RSHIM a través de un puerto USB dedicado.


Vista interior



Ahora que hemos obtenido acceso al sistema operativo de la tarjeta, es posible que se sorprenda por el hecho de que hay un servidor más pequeño dentro de nuestro servidor. La imagen del sistema operativo preinstalada en la tarjeta contiene todo el software que necesita para administrar la tarjeta y, al parecer, aún más. La tarjeta de red contiene una distribución Linux completa, en nuestro caso, Ubuntu 20.04.



Si es necesario, es posible instalar cualquier kit de distribución de Linux en la tarjeta de red que admita la arquitectura aarch64 (ARMv8) y UEFI. Si está conectado a través de la consola, presionar ESC mientras carga la tarjeta lo llevará a su propia utilidad de configuración UEFI. Aquí hay pocas configuraciones inusualmente, en comparación con la contraparte del servidor.

El sistema operativo en BlueField 2 se puede cargar usando PXE, y la utilidad de configuración UEFI le permite personalizar el orden de inicio. Imagínense: la tarjeta de red PXE se inicia primero y luego el servidor.
Utilidad de configuración UEFI en BlueField 2

Por lo tanto, se descubrió que la ventana acoplable predeterminada está disponible en el sistema operativo, aunque parece que esto es redundante para una tarjeta de red. Aunque, si hablamos de redundancia, entonces instalamos la JVM desde el administrador de paquetes y lanzamos el servidor de Minecraft en la tarjeta de red. Aunque no se han realizado pruebas serias, resulta bastante cómodo jugar en el servidor con una empresa pequeña.

Para mostrar información sobre el servidor, tuve que instalar un par de complementos.

El sistema operativo de la tarjeta de red muestra muchas interfaces de red:



ubuntu@bluefield:~$ ifconfig | grep -E '^[^ ]'
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
oob_net0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
p0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
p1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
p0m0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
p1m0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
pf0hpf: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
pf0sf0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
pf1hpf: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
pf1sf0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
tmfifo_net0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
      
      





Las interfaces tmfifo_net0 , lo y docker0 ya las conocemos. La interfaz oob_net0 corresponde al puerto de administración fuera de banda RJ-45. El resto de interfaces están conectadas a puertos ópticos:



  • pX - dispositivo representador del puerto físico de la tarjeta;
  • pfXhpf es una función física del host, una interfaz a la que puede acceder el host;
  • pfXvfY : representación de la función virtual del host (función virtual del host), interfaces virtuales utilizadas para virtualizar SR-IOV en el host;
  • pXm0 es una interfaz de subfunción PCIe especial que se utiliza para comunicarse entre la tarjeta y el puerto. Esta interfaz se puede utilizar para acceder a la tarjeta a la red;
  • pfXsf0 : representación de la subfunción PCIe de la interfaz pXm0.


La forma más sencilla de comprender el propósito de las interfaces es a partir del diagrama:



Interfaz BlueField 2 y mapeo de host (fuente NVIDIA)

Las interfaces están conectadas directamente al conmutador virtual, que se implementa en BlueField 2. Pero hablaremos de eso en otro artículo. En el mismo artículo, queremos ver la emulación NVMe, que le permite conectar almacenamiento definido por software (SDS) a servidores dedicados como discos físicos. Esto le permitirá utilizar todas las ventajas de SDS sobre el metal desnudo.



Configurar la emulación NVMe



De forma predeterminada, el modo de emulación NVMe está desactivado. Lo habilitamos con el comando mlxconfig .



mst start

#  
mlxconfig -d 03:00.0 s INTERNAL_CPU_MODEL=1 PF_BAR2_ENABLE=0 PER_PF_NUM_SF=1
mlxconfig -d 03:00.0 s PF_SF_BAR_SIZE=8 PF_TOTAL_SF=2
mlxconfig -d 03:00.1 s PF_SF_BAR_SIZE=8 PF_TOTAL_SF=2

#   NVMe
mlxconfig -d 03:00.0 s NVME_EMULATION_ENABLE=1 NVME_EMULATION_NUM_PF=1
      
      





Después de habilitar el modo de emulación NVMe, debe reiniciar la tarjeta. La configuración de la emulación NVMe se reduce a dos pasos:



  1. Configuración de SPDK.
  2. Configurando snap_mlnx.


Por el momento, solo se han anunciado oficialmente dos métodos para acceder al almacenamiento remoto: NVMe-oF e iSCSI. Y solo NVMe-oF tiene aceleración de hardware. Sin embargo, también es posible utilizar otros protocolos. Nuestro interés es conectar el repositorio ceph.



Desafortunadamente, no hay soporte listo para usar para rbd. Por lo tanto, para conectarse al almacenamiento ceph, debe usar el módulo del kernel rbd, que creará el dispositivo de bloque / dev / rbdX . Y la pila para la emulación de NVMe, a su vez, funcionará con un dispositivo de bloque.



En primer lugar, debe indicar dónde se encuentra el almacenamiento, que representaremos como NVMe. Esto se hace a través de los argumentos del script spdk_rpc.py... Para la persistencia en los reinicios del mapa, los comandos se escriben en /etc/mlnx_snap/spdk_rpc_init.conf .



Para conectar un dispositivo de bloque, use el comando bdev_aio_create <ruta al dispositivo de bloque> <nombre> <tamaño de bloque en bytes> . El parámetro <nombre> se usa más adelante en la configuración y no tiene que ser el mismo que el nombre del dispositivo de bloque. Por ejemplo:



bdev_aio_create /dev/rbd0 rbd0 4096
      
      





Para la conexión directa del dispositivo rbd es necesario recompilar SPDK y mlnx_snap con soporte rbd. Obtuvimos los ejecutables compilados con soporte rbd del soporte técnico. Para conectar, usamos el comando bdev_rbd_create <nombre de grupo> <nombre de rbd> <tamaño de bloque en bytes> . Este comando no le permite establecer el nombre del dispositivo, pero lo crea él mismo y lo muestra al finalizar. En nuestro caso, Ceph0. Debe recordarse el nombre del dispositivo, lo necesitaremos en más configuraciones.

Aunque la decisión de conectar rbd a través de un módulo del kernel y usar un dispositivo de bloque en lugar de usar directamente rbd parece ser una decisión algo incorrecta, resultó que este es el caso cuando las "muletas" funcionan mejor que la solución "inteligente". En las pruebas de rendimiento, resultó que la solución "correcta" era más lenta.
A continuación, debe configurar la vista que verá el host. La configuración se realiza a través de snap_rpc.py y los comandos se guardan en /etc/mlnx_snap/snap_rpc_init.conf . Primero, creamos una unidad con el siguiente comando.



subsystem_nvme_create <NVMe Qualified Name (NQN)> < > <>
      
      





A continuación, creamos un controlador.



controller_nvme_create <NQN> < > -c < > --pf_id 0
      
      





El administrador de emulación se suele llamar mlx5_x . Si no está utilizando la aceleración de hardware, puede utilizar el primero que se encuentre, es decir, mlx5_0 . Después de ejecutar este comando, se mostrará el nombre del controlador. En nuestro caso, NvmeEmu0pf0 .



Finalmente, agregue un espacio de nombres (espacio de nombres NVMe) al controlador creado.



controller_nvme_namespace_attach < > < > -c < >
      
      





Siempre tenemos el tipo de dispositivo spdk , obtuvimos el ID del dispositivo en la etapa de configuración de spdk y el nombre del controlador en el paso anterior. Como resultado, el archivo /etc/mlnx_snap/snap_rpc_init.conf tiene este aspecto:



subsystem_nvme_create nqn.2020-12.mlnx.snap SSD123456789 "Selectel ceph storage"
controller_nvme_create nqn.2020-12.mlnx.snap mlx5_0 --pf_id 0 -c /etc/mlnx_snap/mlnx_snap.json
controller_nvme_namespace_attach -c NvmeEmu0pf0 spdk Nvme0n10 1
      
      





Reinicie el servicio mlnx_snap :



sudo service mlnx_snap restart
      
      





Si todo está configurado correctamente, se iniciará el servicio. En el host NVMe, el disco no aparecerá por sí solo. Necesita recargar el módulo del kernel nvme.



sudo rmmod nvme
      
      





sudo modprobe nvme
      
      





Y así, nuestro disco físico virtual apareció en el host.



root@host:~# nvme list
Node             SN                   Model                                    Namespace Usage                      Format           FW Rev  
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1     SSD123456789         Selectel ceph storage                    1         515.40  GB / 515.40  GB      4 KiB +  0 B   1.0    

      
      





Ahora tenemos un disco virtual presentado al sistema como uno físico. Comprobémoslo en las tareas habituales de los discos físicos.



Pruebas



En primer lugar, decidimos instalar el sistema operativo en un disco virtual. Se utilizó el instalador de CentOS 8. Vio el disco sin problemas.



Instalación de CentOS 8 La

instalación se llevó a cabo como de costumbre. Verificamos el cargador de arranque CentOS en la utilidad de configuración UEFI.



La utilidad de configuración UEFI ve el disco virtual

. Arrancamos en el CentOS instalado y nos aseguramos de que la raíz FS esté en el disco NVMe.



[root@localhost ~]# lsblk
NAME         MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda            8:0    0 447.1G  0 disk 
|-sda1         8:1    0     1M  0 part 
|-sda2         8:2    0   244M  0 part 
|-sda3         8:3    0   977M  0 part 
`-sda4         8:4    0   446G  0 part 
  `-vg0-root 253:3    0   446G  0 lvm  
sdb            8:16   0 447.1G  0 disk 
sr0           11:0    1   597M  0 rom  
nvme0n1      259:0    0   480G  0 disk 
|-nvme0n1p1  259:1    0   600M  0 part /boot/efi
|-nvme0n1p2  259:2    0     1G  0 part /boot
`-nvme0n1p3  259:3    0 478.4G  0 part 
  |-cl-root  253:0    0    50G  0 lvm  /
  |-cl-swap  253:1    0     4G  0 lvm  [SWAP]
  `-cl-home  253:2    0 424.4G  0 lvm  /home
      
      





[root@localhost ~]# uname -a
Linux localhost.localdomain 4.18.0-305.3.1.el8.x86_64 #1 SMP Tue Jun 1 16:14:33 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
      
      





También probamos el disco emulado con la utilidad fio. Esto es lo que sucedió.

Prueba AIO bdev, IOPS Ceph RBD bdev, IOPS
randread, 4k, 1 1.329 849
escritura aleatoria, 4k, 1 349 326
randread, 4k, 32 15 100 15.000
escritura aleatoria, 4k, 32 9445 9 712
Resulta que el rendimiento de una unidad remota conectada a la prueba y no el clúster ceph más rápido es aproximadamente igual al rendimiento de los discos rápidos en nuestra plataforma en la nube . Por supuesto, el resultado obtenido no se compara con el acceso a discos locales, pero los discos locales también tienen sus limitaciones.



Conclusión



Las tarjetas de red "inteligentes" son una verdadera magia técnica que permite no solo descargar el procesador central de las operaciones de E / S, sino también "engañarlo" presentando una unidad remota como local.



Este enfoque le permite aprovechar el almacenamiento definido por software en servidores dedicados: con un clic de sus dedos, transfiera discos entre servidores, cambie el tamaño, tome instantáneas e implemente imágenes listas para usar de sistemas operativos en segundos.






All Articles