Dimensionamiento del ARC de ZFS: cuando demasiada caché ralentiza todo lo demás

¿Te fue útil?

ZFS tiene un superpoder: convierte RAM en menos búsquedas en disco, menos viajes de ida y vuelta y menos arrepentimientos. El ARC (Adaptive Replacement Cache) es la razón por la que un subsistema de disco mediocre puede parecer que ha tomado espresso. También es la razón por la que un servidor perfectamente sano puede de repente sentirse como si funcionara en cemento húmedo: porque el ARC está “ganando” una pelea de memoria que no debería estar peleando.

Esta es la parte que la mayoría de las guías de afinado omiten: el ARC no vive solo. Compite con la caché de páginas del kernel, montones de aplicaciones, ballooning de VM, límites de contenedores, metadatos del sistema de archivos y el “material” que el SO necesita para seguir vivo. Cuando el ARC crece demasiado (o reduce su tamaño con demasiada reticencia), puede causar swapping, bloqueos por reclaim directo, picos de latencia y el tipo de fallos en cascada que te hacen pensar si tus gráficos de monitorización son arte performativo.

Qué es ARC (y qué no es)

El ARC es la caché en memoria de ZFS tanto para datos de archivos como para metadatos. No es “solo una caché de lectura” en el sentido simplista. Es una caché de múltiples listas (MRU/MFU más listas “fantasma”) diseñada para adaptarse a cargas que oscilan entre lecturas en streaming y relecturas, y entre accesos pesados en metadatos y en datos.

ARC también juega un papel en cómo ZFS evita golpear el disco por metadatos constantemente: piensa en bloques indirectos, dnodes, recorrido de directorios y la cadena general de búsquedas “¿dónde está realmente mi archivo?”. Si alguna vez has visto un pool con muchas IOPS crudas pero una carga que sigue siendo lenta, a menudo es latencia de metadatos, no el rendimiento de datos.

Lo que ARC no es: no es la caché de páginas de Linux (aunque compite con ella), no es un sustituto de la memoria de la aplicación y no es una palanca mágica de “dame toda la RAM” que haga cada carga más rápida. El trabajo del ARC es reducir I/O de disco. Si tu cuello de botella no es I/O de disco, ARC puede convertirse en el pisapapeles más caro del mundo.

Broma de una línea #1: ARC es como un becario con un archivador muy grande—útil hasta que lo rueda al único pasillo y bloquea la salida de incendios.

ARC, datos sucios y por qué las cargas de escritura complican la historia

El comportamiento de escritura en ZFS está gobernado más por el mecanismo de grupos de transacciones (TXG) y los límites de datos sucios que por el dimensionamiento del ARC, pero la RAM sigue siendo el campo de batalla compartido. Escritores intensivos pueden empujar páginas sucias, comportamiento de ZIL/SLOG y writeback asíncrono hacia la contención de memoria.

El ARC sobredimensionado no “come datos sucios” directamente, pero reduce el margen para todo lo demás, y eso cambia cómo se comporta el kernel bajo presión. Cuando la máquina está justa de memoria, el writeback puede volverse explosivo, la latencia se vuelve en picos y terminas depurando “almacenamiento” cuando la causa raíz es reclaim de memoria.

Por qué demasiada ARC perjudica: los mecanismos reales

Seamos claros: “más caché siempre es mejor” solo es cierto si tienes RAM infinita y ningún otro consumidor. Los sistemas de producción no son novelas de fantasía. Tienen presupuestos.

Mecanismo 1: ARC vs. la propia caché y comportamiento de reclaim del kernel

En Linux, el kernel también hace caching. Con ZFS, puedes acabar con dos cachés: ARC (dentro de ZFS) y la caché de páginas (para cosas como binarios, librerías, archivos mmap fuera del contexto de ZFS, y a veces incluso efectos adyacentes a ZFS dependiendo de cómo interaccione tu carga). Si ARC reclama demasiada RAM, el kernel puede reclamar agresivamente en otros sitios, provocando bloqueos.

Síntomas: tiempo de CPU en reclaim del kernel, mayor carga del sistema sin utilización real de CPU y procesos atascados en sueño no interrumpible (D state). Los usuarios interpretan esto como “el disco está lento” porque todo espera a la reclamación de memoria que se parece a I/O wait.

Mecanismo 2: Thrashing de swap: el impuesto de rendimiento que sigues pagando

El swap no es malo; el swapping descontrolado sí lo es. Una máquina que comienza a hacer swap porque ARC es demasiado grande puede experimentar un bucle de retroalimentación:

  • La presión de memoria sube → el kernel intercambia páginas frías de aplicaciones.
  • La latencia sube → las aplicaciones se bloquean y agotan tiempos.
  • El trabajo reintentado aumenta → más asignaciones de memoria, más presión.
  • ARC puede reducirse, pero no siempre lo hace lo suficientemente rápido ni de forma predecible para tus SLO.

Si nunca has visto thrashing de swap en producción, no has vivido. Es como ver una carretilla elevadora intentar hacer ballet: técnicamente posible, emocionalmente perturbador.

Mecanismo 3: VMs y contenedores: ARC puede dejar sin memoria a tus invitados

En hosts de virtualización (Proxmox, bhyve, KVM en ZoL), ARC no es “gratis”. El hipervisor y los invitados también necesitan memoria. El ballooning y el overcommit empeoran esto, porque el host puede parecer bien hasta que de repente no lo está, momento en el que el host empieza a reclamar y a hacer swap mientras los invitados también gritan por memoria. Un ARC sobredimensionado convierte un overcommit manejable en un incidente a nivel host.

Mecanismo 4: Dominio de metadatos: ARC crece con lo que tocas

ARC no es uniformemente “datos”. Algunas cargas son pesadas en metadatos: millones de archivos pequeños, contenedores desenpaquetando capas, sistemas CI, gestores de paquetes, patrones tipo maildir, copias de seguridad que recorren árboles. ARC se llenará encantado de metadatos que aceleran esos recorridos—hasta que desplace la memoria que tu base de datos o JVM necesitaban para evitar tormentas de recolección de basura.

Mecanismo 5: Leer mal la “memoria libre” conduce a malas decisiones

A ZFS le gusta la memoria. Linux también le gusta usar memoria. Que la memoria “libre” sea pequeña es normal. La pregunta es si el sistema puede reclamar memoria rápidamente bajo demanda sin swapping ni bloqueos. ARC se puede afinar para ser un buen ciudadano—o puede actuar como si pagara el alquiler y todos los demás fueran subarrendatarios.

Hechos y contexto histórico que cambian cómo afinas

  1. ARC fue diseñado para superar al LRU clásico adaptándose entre “usado recientemente” y “usado frecuentemente”; no es una caché tonta que puedas razonar con una sola proporción.
  2. El ecosistema original de ZFS esperaba máquinas con mucha RAM. Los primeros despliegues de ZFS vivían en sistemas donde “mucha memoria” era el valor por defecto, y las guías de afinado reflejaban esa cultura.
  3. En Linux, ZFS vive fuera del modelo de caché VFS nativo en formas importantes; por eso las interacciones ARC/page-cache y el comportamiento de reclaim son centrales para el rendimiento.
  4. L2ARC existe porque los discos eran lentos y la RAM cara. Hoy, NVMe cambió las cuentas: a veces “añadir RAM” gana a “añadir L2ARC”, y a veces ninguno importa si estás limitado por CPU.
  5. ARC contiene tanto datos como metadatos; en cargas pesadas en metadatos, un ARC moderado puede superar a un ARC enorme que causa swapping.
  6. Históricamente ARC ha tenido dolores de ajuste sobre el comportamiento de shrink bajo presión. Se han hecho mejoras con el tiempo, pero aún no debes asumir que siempre devolverá memoria exactamente cuando la necesites.
  7. La deduplicación en ZFS es famosa por su hambre de memoria porque la DDT (tabla de dedup) quiere RAM; la gente confunde “ZFS necesita RAM” con “dale todo a ARC”, que es la lección equivocada.
  8. La virtualización cambió la conversación por defecto sobre ARC. En 2010, un “servidor de almacenamiento” era a menudo solo eso. En 2025, a menudo es un servidor de almacenamiento que además ejecuta una pequeña ciudad de VMs.
  9. La compresión hizo que cachear sea más valioso porque los bloques comprimidos significan más datos lógicos por byte de ARC—pero también significa que la CPU puede convertirse en el factor limitante primero.

Tres historias del mundo corporativo desde la trinchera

Mini-historia #1: El incidente causado por una suposición equivocada

El ticket empezó inocentemente: “picos de latencia en la API cada día alrededor de las 10:00”. Era un host VM con volúmenes respaldados por ZFS para varios servicios. El on-call vio discos al 20% de utilización y asumió “no es almacenamiento”. Los gráficos mostraban la memoria “mayormente usada”, pero eso es normal en Linux, ¿verdad?

Luego alguien notó el gráfico de swap: una pendiente lenta hacia arriba comenzando a las 09:40, alcanzando un precipicio alrededor de las 10:05. A las 10:10, los pods de la API se estaban reiniciando por timeouts. El load average del host era alto, pero la CPU no lo estaba. Ese es el olor de las tormentas de reclaim: tareas esperando por memoria y I/O, sin hacer trabajo.

La suposición equivocada fue sutil: “ARC se reducirá cuando sea necesario”. Se redujo—eventualmente. Pero “eventualmente” se midió en minutos, y los minutos son una eternidad para APIs orientadas al cliente. El disparador inmediato fue un trabajo programado que recorrió un árbol muy grande de archivos pequeños (buffet de metadatos), inflando ARC con metadatos justo cuando las JVM necesitaban crecer el heap.

La solución no fue heroica: limitar ARC y dejar margen para invitados y el host. El cambio importante fue cultural: dejaron de tratar el ARC como “rendimiento gratis” y empezaron a tratarlo como una partida presupuestaria con dueño.

Mini-historia #2: La optimización que salió mal

Otro equipo tenía una iniciativa para “acelerar builds”. Los runners CI eran lentos desempaquetando contenedores y dependencias desde un dataset ZFS. Alguien leyó que “ZFS ama la RAM”, así que aumentaron el límite de ARC hasta la luna y vieron mejorar las tasas de acierto en un benchmark.

En producción fue un desastre. Los builds fueron más rápidos por un día y luego progresivamente más erráticos. ¿Por qué? Porque los runners también hacían mucho trabajo efímero: procesos de corta vida, caches de compilador y archivos temporales. El ARC agrandado empujó al host a presión de memoria, y el kernel empezó a reclamar y a hacer swap justo con las páginas que el sistema de build necesitaba. La tasa de acierto se veía bien, pero el tiempo de trabajo de extremo a extremo empeoró. La tasa de aciertos es una métrica de vanidad cuando tu scheduler está paginando.

La parte realmente dolorosa: la desaceleración no correlacionaba limpiamente con “tamaño de ARC”. Correlacionaba con la concurrencia. Con un build, la máquina estaba bien. Con diez, colapsó. Eso es lo que hace a los incidentes por presión de memoria tan buenos para hacer perder tiempo a ingenieros sénior: no puedes reproducirlos en tu portátil y tus dashboards no gritan “ARC hizo esto”.

Revirtieron el aumento de ARC y luego hicieron un cambio aburrido: separaron la carga CI para que desempaquetado y compilación no compitieran en los mismos hosts que ejecutaban otros servicios sensibles a la latencia. La lección no fue “nunca aumentes ARC”. Fue: no optimices una etapa mientras desestabilizas la plataforma donde se ejecuta.

Mini-historia #3: La práctica aburrida pero correcta que salvó el día

Esta es la opuesta al drama. Una empresa del área financiera (del tipo que tiene ventanas de cambio y sentimientos sobre el riesgo) ejecutaba ZFS en un conjunto de hosts de base de datos. El equipo tenía una práctica: cada construcción de host incluía topes explícitos de ARC, revisión de la política de swap y un “SLO de margen de memoria”. No era glamuroso. Estaba documentado y aplicado por la gestión de configuración.

Un trimestre, el equipo de BD lanzó una nueva función que aumentó el tamaño del working set. En hosts sin disciplina, eso habría significado swapping sorpresa. Aquí, el impacto fue modesto: las cachés de la BD se expandieron hasta el límite de margen, la latencia subió ligeramente y saltaron alertas de “aproximándose al presupuesto de memoria”.

Puesto que ARC ya estaba limitado, el sistema no entró en una espiral de muerte. El equipo de BD vio la alerta, ajustó el dimensionamiento de sus cachés internos y planificó una ampliación de RAM como parte del siguiente ciclo de capacidad. No hubo llamada de incidente, ni pánico, ni “¿por qué el load es 200?” misterioso.

Ésa es la verdad poco sexy: la mayoría de los buenos resultados SRE son aburridos. El mejor afinado de ARC es el que hiciste hace meses, silenciosamente, y olvidaste hasta que evitó una caída a las 3 a.m.

Un modelo mental: qué medir, no qué creer

Cuando la gente discute sobre dimensionamiento del ARC, normalmente discuten desde la ideología:

  • Gente de almacenamiento: “¡Usad RAM para caché!”
  • Gente de aplicaciones: “¡Dejad de robar mi memoria!”
  • SREs: “No me importa quién gane, me importa que la latencia deje de dispararse.”

Aquí hay un modelo que termina la discusión: ARC es valioso cuando reduce I/O costoso sin desencadenar un comportamiento de memoria más costoso. I/O costoso puede ser lecturas aleatorias en HDDs, lecturas síncronas a través de la red o búsquedas de metadatos que paralizan tu carga. El comportamiento de memoria más costoso es swapping, bloqueos por reclaim y churn de caché que incrementa la sobrecarga de CPU.

Señales de que ARC ayuda

  • Alta tasa de aciertos de ARC y latencia estable.
  • Menos IOPS de lectura y menor latencia de lectura comparado con la línea base.
  • No hay swapping ni presión sostenida de reclaim.
  • Las apps tienen suficiente memoria para mantener sus propias cachés/conjuntos calientes residentes.

Señales de que ARC perjudica

  • Actividad de swap in/out durante carga normal.
  • Incremento de fallos de página mayores sin mejora correspondiente en el rendimiento.
  • Load average sube mientras la CPU permanece mayormente inactiva.
  • Aumenta el I/O wait y los discos no están saturados.
  • Evicciones frecuentes del ARC con poco beneficio de acierto (churn de caché).

Guion rápido de diagnóstico

Esta es la “tienes 15 minutos antes de que la llamada de incidente se convierta en gritos interpretativos”. Hazlo en orden.

1) Confirma que es presión de memoria, no saturación de disco

Revisa swap, reclaim y tareas bloqueadas. Si el swap está activo y ves indicadores de reclaim, trata al ARC como sospechoso inmediatamente.

2) Comprueba tamaño del ARC frente al margen del host

Mira el uso actual del ARC, los límites del ARC y la memoria disponible total. En hosts VM, también revisa la asignación de memoria de invitados y el ballooning.

3) Correlaciona el comportamiento del ARC con el tipo de carga

¿Esto es pesado en metadatos (muchos archivos, muchos stat, desempaquetado de contenedores) o pesado en datos (lecturas secuenciales grandes)? La estrategia de dimensionamiento del ARC difiere.

4) Busca churn de caché

Las tasas de acierto por sí solas no son suficientes. Si ARC está constantemente evictando y recargando, estás pagando CPU y contención de locks por poco beneficio.

5) Solo entonces toca los controles

No afines a ciegas. Recopila un pequeño paquete: estadísticas del ARC, vmstat, iostat, top y una ventana de comportamiento de 5 minutos. Luego ajusta zfs_arc_max con prudencia y observa.

Tareas prácticas: comandos, salidas, interpretación (12+)

Estos son comandos reales que puedes ejecutar en Linux con OpenZFS o en FreeBSD (con pequeñas diferencias de ruta/sysctl). Señalaré donde importa. Trata las salidas como ilustrativas; tus números serán diferentes.

Task 1: Check current ARC size and limits (Linux)

cr0x@server:~$ grep -E "c_max|c_min|size" /proc/spl/kstat/zfs/arcstats
13 c_max                            4    34359738368
14 c_min                            4    4294967296
 7 size                             4    28776239104

Interpretación: ARC max es 32 GiB, min 4 GiB, tamaño actual ~26.8 GiB. Si esto es un sistema con 32 GiB de RAM que ejecuta bases de datos y VMs, esto no es “caché”, es una toma hostil.

Task 2: Check ARC efficiency quickly (arcstat)

cr0x@server:~$ arcstat 1 5
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:00:01   920    40      4     2   0    38   4     0   0   26.9G  32.0G
12:00:02   880    55      6     1   0    54   6     0   0   27.0G  32.0G
12:00:03   910    48      5     2   0    46   5     0   0   27.1G  32.0G
12:00:04   940    60      6     3   0    57   6     0   0   27.1G  32.0G
12:00:05   905    42      5     1   0    41   5     0   0   27.2G  32.0G

Interpretación: La tasa de misses es baja. Eso es bueno. Pero si el host está haciendo swap, “buena tasa de acierto” no es excusa. Una caché puede ser eficaz y aun así ser demasiado grande.

Task 3: Check system memory headroom (Linux)

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:            64Gi        55Gi       1.2Gi       2.0Gi       7.8Gi       3.5Gi
Swap:           16Gi       2.6Gi        13Gi

Interpretación: “available” es 3.5 GiB con swap ya usado. En un sistema ocupado esto es una señal de advertencia. ARC puede estar ocupando memoria que el SO y las apps necesitan para estabilidad.

Task 4: Detect swap thrash and reclaim pressure (vmstat)

cr0x@server:~$ vmstat 1 10
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 4  1 2684352 120000  80000 900000   20   80   200   150  900 1400 12 18 58 12  0
 6  2 2684800 110000  78000 880000  120  260   400   300 1100 2100 10 22 49 19  0
 7  3 2686000  90000  76000 860000  300  600   800   500 1300 2600  9 25 40 26  0

Interpretación: si/so sostenidos distintos de cero significa swapping activo. El aumento del b (procesos bloqueados) con mayor wa a menudo significa que el sistema está atascado esperando. Si esto se correlaciona con ARC cerca del máximo, has encontrado un culpable probable.

Task 5: Confirm disk isn’t the real bottleneck (iostat)

cr0x@server:~$ iostat -x 1 3
Device            r/s     w/s   rkB/s   wkB/s  avgrq-sz avgqu-sz   await  %util
nvme0n1          12.0    30.0    900    2200      80.0     0.20    2.10   12.5
nvme1n1          10.0    28.0    850    2100      78.5     0.18    2.00   11.0

Interpretación: Bajo %util y bajo await sugiere que los discos no están saturados. Si la latencia es mala de todos modos, sospecha presión de memoria o contención de locks, no el throughput bruto de disco.

Task 6: Check ARC breakdown (data vs metadata)

cr0x@server:~$ grep -E "demand_data_bytes|demand_metadata_bytes|prefetch_data_bytes|prefetch_metadata_bytes" /proc/spl/kstat/zfs/arcstats
96 demand_data_bytes                4    12884901888
97 demand_metadata_bytes            4    13743895347
98 prefetch_data_bytes              4    1073741824
99 prefetch_metadata_bytes          4    268435456

Interpretación: Aquí los metadatos son enormes—más que los datos demandados. Eso no es “malo”, pero apunta a una carga como recorridos de árbol, archivos pequeños o imágenes de virtualización con mucha actividad de metadatos. Si estás dejando a las apps con hambre, considera limitar ARC y/o reducir las fuentes de churn de metadatos.

Task 7: Check for ARC shrink behavior and throttling

cr0x@server:~$ grep -E "arc_shrink|arc_no_grow|memory_throttle_count" /proc/spl/kstat/zfs/arcstats
171 arc_no_grow                     4    4821
198 memory_throttle_count           4    129

Interpretación: memory_throttle_count indica que ZFS tuvo que throttlear debido a presión de memoria. Si esto sube durante incidentes, ARC puede estar contribuyendo a la contención a nivel sistema.

Task 8: Find your current ARC tunables (Linux module parameters)

cr0x@server:~$ sudo cat /sys/module/zfs/parameters/zfs_arc_max
34359738368
cr0x@server:~$ sudo cat /sys/module/zfs/parameters/zfs_arc_min
4294967296

Interpretación: Los valores están en bytes. Si no los configuraste, pueden ser valores por defecto derivados de la RAM total. Los valores por defecto no son dogma.

Task 9: Temporarily lower ARC max (Linux) to stop a fire

cr0x@server:~$ sudo sh -c 'echo 17179869184 > /sys/module/zfs/parameters/zfs_arc_max'
cr0x@server:~$ sudo cat /sys/module/zfs/parameters/zfs_arc_max
17179869184

Interpretación: Esto limita el crecimiento futuro; ARC no cae instantáneamente al nuevo tope, pero tenderá a reducirse a medida que haga evicciones. Vigila la actividad de swap y la latencia. Si necesitas alivio inmediato, estás en territorio de respuesta a incidentes—reduce carga, reinicia al peor culpable o mueve cargas.

Task 10: Persist ARC limits (Linux, modprobe.d)

cr0x@server:~$ sudo tee /etc/modprobe.d/zfs.conf >/dev/null <<'EOF'
options zfs zfs_arc_max=17179869184
options zfs zfs_arc_min=2147483648
EOF
cr0x@server:~$ sudo update-initramfs -u

Interpretación: Esto hace que los límites sobrevivan reinicios. La mecánica exacta de persistencia varía por distro; la idea es: no confíes en que “alguien recordará el echo a sysfs durante el próximo outage”.

Task 11: FreeBSD: check and set ARC limits (sysctl)

cr0x@server:~$ sysctl kstat.zfs.misc.arcstats.size
kstat.zfs.misc.arcstats.size: 28776239104
cr0x@server:~$ sysctl vfs.zfs.arc_max
vfs.zfs.arc_max: 34359738368
cr0x@server:~$ sudo sysctl vfs.zfs.arc_max=17179869184
vfs.zfs.arc_max: 34359738368 -> 17179869184

Interpretación: FreeBSD usa perillas diferentes, pero aplica la misma verdad operativa: limita ARC para proteger la salud general del sistema.

Task 12: Check ZFS dataset recordsize and workload fit (because ARC isn’t magic)

cr0x@server:~$ zfs get recordsize,compression,primarycache tank/vmstore
NAME          PROPERTY      VALUE     SOURCE
tank/vmstore  recordsize    128K      default
tank/vmstore  compression   lz4       local
tank/vmstore  primarycache  all       default

Interpretación: El recordsize afecta qué se cachea y con qué eficiencia. Para imágenes VM o bases de datos, un recordsize incorrecto puede inflar la huella de caché y aumentar la amplificación de lectura. El dimensionamiento del ARC no es un sustituto de una higiene básica del dataset.

Task 13: Check primarycache/secondarycache policy (targeted relief)

cr0x@server:~$ zfs get primarycache,secondarycache tank/backup
NAME         PROPERTY        VALUE     SOURCE
tank/backup  primarycache    all       default
tank/backup  secondarycache  all       default
cr0x@server:~$ sudo zfs set primarycache=metadata tank/backup
cr0x@server:~$ zfs get primarycache tank/backup
NAME         PROPERTY      VALUE     SOURCE
tank/backup  primarycache  metadata  local

Interpretación: Si un dataset es mayormente backups secuenciales que nunca volverás a leer en caliente, cachear los datos de archivo suele ser RAM desperdiciada. Mantener solo metadatos puede preservar la velocidad de recorrido de directorios sin fijar datos voluminosos en ARC.

Task 14: Check for ZFS prefetch effects (useful or harmful)

cr0x@server:~$ sudo cat /sys/module/zfs/parameters/zfs_prefetch_disable
0
cr0x@server:~$ grep -E "prefetch_data_hits|prefetch_data_misses" /proc/spl/kstat/zfs/arcstats
68 prefetch_data_hits               4    105230
69 prefetch_data_misses             4    98210

Interpretación: El prefetch puede ayudar lecturas secuenciales pero malgastar caché en cargas aleatorias. Si las misses de prefetch son enormes y los bytes de prefetch son grandes, podrías estar cacheando conjeturas en lugar de hechos.

Task 15: Detect “everything is slow” due to blocked tasks

cr0x@server:~$ ps -eo state,pid,comm,wchan:32 --sort=state | head
D   2314  postgres         io_schedule
D   9881  java             balance_pgdat
D  11202  python3          zio_wait
R  21011  top              -

Interpretación: El estado D con balance_pgdat apunta hacia presión de reclaim de memoria. Si ves esto durante incidentes junto con ARC cerca del máximo, estás mirando el móvil y el arma.

Listas de verificación / plan paso a paso

Plan paso a paso: dimensionar ARC correctamente sin conjeturas

  1. Clasifica el host: appliance de almacenamiento, host VM, servidor BD, propósito general. Los presupuestos de ARC difieren.
  2. Define un objetivo de margen: decide cuánta RAM debe quedar disponible para OS + apps en pico. Escríbelo.
  3. Mide la línea base: recopila 30 minutos de estadísticas ARC, actividad de swap, iostat y latencia de apps durante carga típica.
  4. Elige una tapa inicial de ARC: conservadora al principio. Para hosts VM y cargas mixtas, dejar margen sustancial suele ser correcto.
  5. Aplica la tapa temporalmente: cambia zfs_arc_max en caliente, observa mejoras en swap/reclaim y cualquier caída en la tasa de acierto.
  6. Valida el impacto en la carga: revisa latencias p95/p99, no solo el throughput. Afinar ARC trata sobre la latencia de cola.
  7. Hazlo persistente: gestión de configuración, ajustes en el arranque y un plan de rollback.
  8. Reevalúa tras cambios: nuevas versiones de apps, nuevos datasets, nueva densidad de VM—el dimensionamiento del ARC no es “pónlo y olvídalo”.

Lista operativa: antes de cambiar ARC en producción

  • ¿El swap está activo ahora? Si sí, reduce el riesgo primero: baja carga o escala horizontalmente.
  • ¿Tienes acceso remoto fuera de banda? Los incidentes de memoria pueden hacer que SSH sea “arte interactivo”.
  • ¿Sabes revertir rápidamente el cambio?
  • ¿Tienes una ventana de observación de 10 minutos con carga estable?
  • ¿Has capturado métricas “antes” (tamaño ARC, vmstat, iostat, latencia)?

Errores comunes: síntomas y soluciones

Mistake 1: “ARC debe ser lo más grande posible.”

Síntomas: Uso de swap que se incrementa a lo largo de días; p99 con picos durante trabajos cron; load average sube mientras la CPU no está ocupada; kills OOM aleatorios.

Solución: Limita zfs_arc_max para dejar margen real. En hosts VM, sé más estricto que en cajas de almacenamiento dedicadas. Valida con vmstat y latencia de aplicaciones.

Mistake 2: Afinar basado solo en tasa de aciertos

Síntomas: La tasa de aciertos mejora pero el rendimiento global empeora; más cambios de contexto; más tiempo en kernel; bloqueos visibles por usuarios.

Solución: Trata la tasa de aciertos como métrica de soporte. Prioriza actividad de swap, presión de reclaim, tareas bloqueadas y latencia de cola.

Mistake 3: Ignorar cargas pesadas en metadatos

Síntomas: ARC se llena rápidamente durante escaneos de backups, extracción de capas de contenedor o indexado de archivos; presión de memoria se correlaciona con “muchas operaciones de archivos”, no con throughput.

Solución: Considera controles a nivel de dataset como primarycache=metadata para datasets masivos, y limita ARC. También examina patrones de carga: ¿puedes programar recorridos de árbol en horario valle?

Mistake 4: Sobrecommit en hosts VM sin presupuestar ARC

Síntomas: El host hace swap mientras los invitados también balloon; incidentes de vecinos ruidosos; pausas impredecibles.

Solución: Trata ARC como una reserva fija. Pon un tope y mantenlo estable. Monitoriza la memoria “available” del host, no solo “used”.

Mistake 5: Hacer cambios que no persisten

Síntomas: El sistema está bien después del afinado, luego tras el reinicio el incidente vuelve; nadie recuerda por qué.

Solución: Persiste vía opciones de módulo (Linux) o loader/sysctl (FreeBSD), bajo gestión de configuración con historial de cambios.

Mistake 6: Culpar a los discos cuando el problema real es reclaim

Síntomas: Informes de “almacenamiento lento”, pero iostat muestra baja utilización y latencia decente. El load está alto. Muchas tareas están bloqueadas.

Solución: Mira vmstat, swap y tareas en estado D. Si el reclaim es el problema, dimensionar ARC forma parte de la solución.

Mistake 7: Poner zfs_arc_min demasiado alto

Síntomas: Incluso bajo presión, ARC se niega a reducirse lo suficiente; aumenta el riesgo de OOM; el swap persiste.

Solución: Mantén zfs_arc_min moderado a menos que tengas una appliance de almacenamiento dedicada con necesidades previsibles.

Broma de una línea #2: Fijar zfs_arc_min a “nunca reducir” es como atornillar tu silla de oficina al suelo—estable, claro, pero ahora haces reuniones desde el pasillo.

Preguntas frecuentes

1) ¿Cuánta RAM debo dar al ARC?

No hay un número universal. Empieza reservando suficiente para el SO y tus cargas principales en pico (VMs, bases de datos, JVMs). Luego asigna lo que quede al ARC con una tapa conservadora. Las cajas de almacenamiento dedicadas pueden permitirse ARC más grandes; los hosts de uso mixto normalmente no.

2) ¿Por qué mi servidor muestra casi nada de memoria libre? ¿Es malo?

No necesariamente. Linux usa RAM agresivamente para caches. La señal de peligro no es “libre es bajo”, es “available es bajo” más actividad de swap, bloqueos por reclaim o picos de latencia.

3) ¿Debería desactivar el swap en sistemas ZFS?

Normalmente no. Un swap pequeño y controlado puede prevenir OOM abruptos. La meta es evitar el thrashing activo. Si el swap se usa intensamente durante carga normal, arregla el presupuesto de memoria (incluyendo topes de ARC) en lugar de jugar al whack-a-mole con swap.

4) ¿Añadir L2ARC me permite reducir ARC de forma segura?

L2ARC puede ayudar en cargas de solo lectura con working set mayor que la RAM, pero no es un reemplazo gratis para ARC. L2ARC aún consume memoria para metadatos y puede añadir tráfico de escritura a los SSD. Reduce ARC para proteger la estabilidad; añade L2ARC solo cuando hayas probado que las misses de lectura son tu cuello de botella.

5) ¿Por qué ARC no se reduce inmediatamente después de bajar zfs_arc_max?

La evicción de ARC está impulsada por actividad y presión. Bajar el tope cambia el objetivo, pero ARC aún necesita evictar buffers con el tiempo. Si necesitas alivio inmediato, reduce la carga, detén la carga que está inflando la caché o planifica un reinicio controlado del consumidor de memoria pesado—porque ya estás en modo incidente.

6) ¿El dimensionamiento del ARC es diferente para pools HDD vs NVMe?

Sí, porque el valor de cachear depende del coste de un miss. Las lecturas aleatorias en HDD son caras; ARC ayuda mucho. Los misses en NVMe son más baratos; ARC aún ayuda (especialmente en metadatos), pero puedes chocar primero con CPU o contención de memoria antes de que el almacenamiento sea el limitador. No dejes al sistema sin recursos solo para evitar una lectura NVMe de 200 microsegundos.

7) ¿Cómo sé si mi carga es pesada en metadatos?

Mira la descomposición del ARC (demand metadata bytes vs demand data bytes) y observa patrones de carga: muchos stat(), recorridos de directorio, apertura de archivos pequeños, capas de contenedor, instalaciones de paquetes. Las cargas pesadas en metadatos se benefician de cachear metadatos, pero también pueden inflar ARC rápidamente.

8) ¿Debo poner primarycache=metadata para datasets VM?

No por defecto. Las imágenes VM a menudo se benefician de cachear datos porque re-lecturan bloques. Sin embargo, para datasets de backup, archivado o de “escribir-una-vez/leer-rara-vez”, primarycache=metadata puede recuperar RAM sin pérdida de rendimiento significativa.

9) ¿Cuál es la manera más segura de cambiar límites ARC en producción?

Cambia zfs_arc_max incrementalmente, durante carga estable, con rollback claro. Observa swap, vmstat y latencia durante al menos varios minutos. Luego persiste el ajuste vía gestión de configuración y programa una revisión post-cambio.

10) Limité ARC y el rendimiento empeoró. ¿Hice algo mal?

Quizá, o quizá expusiste el cuello de botella real (disco, red, CPU). Si la latencia de lectura subió y los discos ahora están más ocupados, ARC estaba enmascarando almacenamiento lento. Si el rendimiento empeoró pero el swap paró, cambiaste rapidez por estabilidad—lo cual aún puede ser correcto. El siguiente paso correcto es abordar la nueva restricción visible en lugar de inflar ARC a ciegas.

Conclusión

El ARC es una herramienta de rendimiento, no un derecho adquirido. Debe competir por memoria, pero no debería ganar dejando inconsciente al resto del sistema. Un ARC sobredimensionado no falla ruidosamente; falla lateralmente—a través de swap, bloqueos por reclaim, tareas bloqueadas y latencia en la cola que hace que discos perfectamente sanos parezcan culpables.

Dimensiona ARC como dimensionarías cualquier otra cosa en producción: define margen, mide cuellos de botella reales, haz cambios pequeños y persiste los ajustes aburridos que te mantienen fuera de las llamadas de emergencia. La mejor caché es la que acelera tu carga sin convertir tu sistema operativo en un tribunal de arbitraje de memoria.

← Anterior
WordPress hackeado: respuesta a incidentes paso a paso que no lo empeora
Siguiente →
Una página 404 sin vergüenza: enlaces útiles, búsqueda rápida y humor ligero

Deja un comentario