Optimizar I/O scheduler en Linux + hardware RAID

Desde que un proceso hace un write() hasta que el dato se almacena en el medio físico este atraviesa varias capas (sistema de ficheros, gestor de volúmenes, controladora RAID + BBU, caches de disco, etc.) donde se realizan una serie de optimizaciones para mejorar el acceso a disco, en entornos virtuales estas capas pueden llegar a duplicarse:

Hoy en día es común encontrarnos escenarios con 3-4 capas de I/O scheduling y a priori podríamos pensar que sumarlas va a mejorar el rendimiento. En la práctica y aunque parezca increíble, en conexiones a sistemas RAID -ya sea por iSCSI, Fiber Channel o vía DAS- deshabilitar estas optimizaciones pueden darnos mejores resultados.

En Linux la optimización más importante se realiza en el planificador de E/S de los dispositivos de bloques (en inglés, I/O scheduler), una capa inteligente entre el sistema operativo y el hardware donde se aplican diferentes algoritmos (CFQ, deadline, anticipatory, noop, etc) para ordenar operaciones de E/S y hacer así un uso más eficiente de los discos: agrupar escrituras, reducir seeks, priorizar ciertas operaciones de I/O, etc. Este comportamiento tiene mayor impacto en sistemas con I/O aleatorias, por ejemplo en grandes bases de datos MySQL.

En estas dos gráficas vemos el %iowait y la carga de una máquina Linux con CentOS conectada vía iSCSI a una cabina NetApp, tras deshabilitar el I/O scheduler CFQ (planificador por defecto en RHEL) la carga baja de 10 a 1 y el iowait del %20 a %4:

En Linux podemos cambiar este comportamiento en caliente y por cada dispositivo vía SysFS (entre corchetes aparece el planificador de E/S activo):

# cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]

# echo noop > /sys/block/sda/queue/scheduler

# cat /sys/block/sda/queue/scheduler
[noop] anticipatory deadline cfq

Para hacer estos cambios persistentes a reinicios podemos utilizar udev y aplicar un planificador de forma selectiva, en este ejemplo establecemos “noop” solo en conexiones del tipo iSCSI o FC (podríamos afinar la regla y aplicarla únicamente a cabinas de un determinado fabricante, por ejemplo con vendor=”NETAPP” y model=”LUN”):

ACTION=="add", SUBSYSTEM=="scsi", ENV{ID_FS_USAGE}!="filesystem", \
        ENV{ID_PATH}=="*-iscsi-*|-fc-*", \
        RUN+="/bin/sh -c 'echo noop > /sys$DEVPATH/queue/scheduler'"

Un I/O scheduler da su máximo rendimiento cuando tiene una cola por cada disco y si los discos están bajo un RAID el kernel los verá como un único dispositivo y utilizará una única cola (aunque tengamos 10 discos).

En un sistema RAID el kernel entrega ordenado el I/O a la controladora a través de una cola única y esta a su vez lo distribuye entre los discos, este mecanismo funciona bien hasta alcanzar el límite de una cola/disco (~250 ops para discos de 15K aprox.) y a partir de aquí empieza a degradarse. Al deshabilitar el planificador el tráfico I/O llegaría desordenado a la controladora RAID y esta podría hacer el reparto de forma más eficiente (para una explicación más detallada recomiendo la lectura del post “Optimizing Linux for random I/O on hardware RAID“), gráficamente:

Como alternativa menos cómoda a modificar el I/O scheduler en vez crear un RAID con todos los discos podemos crear grupos y posteriormente unirlos por software, así el kernel podrá trabajar con más de una cola; Ejemplo: si tenemos un RAID con 10 discos podemos crear 5 grupos de 2 discos en RAID-1 y unirlos en stripe vía LVM (a efectos un RAID 1+0), de este modo Linux vería 5 dispositivos y trabajaría más eficientemente al utilizar 5 colas.

Finalmente, todo esto depende del tipo de cabina, tráfico I/O, discos, etc. pero en general si tienes un buen sistema RAID + BBU deshabilitar la reordenación de I/O en el kernel y delegar este trabajo al hardware especializado va a dar mejores resultados. Pero como siempre… lo mejor es realizar benchmarks con diferentes schedulers y comparar resultados :)

This entry was posted in Linux, Storage and tagged , , , , , , , . Bookmark the permalink.
  • http://twitter.com/RubenDOB Ruben Ortiz

    Hola Santi

    después de leerte me ha asaltado una duda. ¿La máquina que modificas entiendo que es una máquina física y no una virtual? Lo digo porque leo a gente que recomienda lo mismo incluso en máquinas virtuales (en un artículo sobre Esxi)

    Gracias ;)