
Hola a todos Trabajo como administrador líder del sistema en OK y soy responsable del funcionamiento estable del portal. Quiero hablar sobre cómo construimos el proceso de reemplazo automático de discos, y luego, como administrador, fue excluido de este proceso y lo reemplazó con un bot.
Este artículo es una especie de transcripción del
rendimiento en HighLoad + 2018
Construyendo un proceso de reemplazo de disco
Primero unos pocos números
OK es un servicio gigantesco utilizado por millones de personas. Cuenta con aproximadamente 7 mil servidores, ubicados en 4 centros de datos diferentes. Los servidores cuestan más de 70 mil unidades. Si los apilas uno encima del otro, obtienes una torre con una altura de más de 1 km.
Los discos duros son un componente del servidor que se bloquea con mayor frecuencia. Con tales volúmenes, tenemos que cambiar unos 30 discos por semana, y este procedimiento se ha convertido en una rutina no muy agradable.

Incidentes
Hemos introducido una gestión completa de incidentes en nuestra empresa. Cada incidente que registramos en Jira, y luego lo resolvemos y lo desmontamos. Si el incidente tuvo un efecto para los usuarios, entonces definitivamente vamos a pensar en cómo responder más rápido en tales casos, cómo reducir el efecto y, por supuesto, cómo prevenir una recurrencia.
Las unidades no son la excepción. Su estado es monitoreado por Zabbix. Monitoreamos los mensajes en Syslog para errores de escritura / lectura, analizamos el estado de las redadas de HW / SW, monitoreamos SMART y calculamos el desgaste de los SSD.
Cómo cambiaron los discos antes
Cuando se enciende un disparador en Zabbix, se crea un incidente en Jira y se envía automáticamente a los ingenieros apropiados en los centros de datos. Hacemos esto con todos los incidentes HW, es decir, aquellos que requieren algún tipo de trabajo físico con el equipo en el centro de datos.
Un ingeniero de un centro de datos es una persona que resuelve problemas relacionados con el hardware, es responsable de la instalación, mantenimiento y desmantelamiento de los servidores. Habiendo recibido un boleto, el ingeniero comienza a trabajar. En los estantes de discos, cambia los discos por su cuenta. Pero si no tiene acceso al dispositivo deseado, el ingeniero recurre a los administradores del sistema para que lo ayuden. En primer lugar, debe eliminar el disco de la rotación. Para hacer esto, debe realizar los cambios necesarios en el servidor, detener la aplicación y desmontar el disco.
El administrador del sistema de turno durante el turno es responsable de la operación de todo el portal. Investiga incidentes, reparaciones, ayuda a los desarrolladores a realizar pequeñas tareas. No solo trata con discos duros.
Anteriormente, los ingenieros del centro de datos conversaban con el administrador del sistema. Los ingenieros enviaron enlaces a los boletos de Jira, el administrador los revisó y mantuvo un registro de trabajo en un bloc de notas. Pero los chats son inconvenientes para tales tareas: la información allí no está estructurada y se pierde rápidamente. Y el administrador podía simplemente alejarse de la computadora y por algún tiempo no responder a las solicitudes, y el ingeniero se paró en el servidor con un montón de discos y esperó.
Pero lo peor fue que los administradores no vieron la imagen completa: qué incidentes de disco existen, dónde podría surgir el problema. Esto se debe al hecho de que damos todos los incidentes HW a los ingenieros. Sí, fue posible mostrar todos los incidentes en el panel de administración. Pero hay muchos, y el administrador solo estuvo involucrado en algunos de ellos.
Además, el ingeniero no pudo priorizar correctamente, porque no sabe nada sobre el propósito de servidores específicos, sobre la distribución de información entre unidades.
Nuevo procedimiento de reemplazo
Lo primero que hicimos fue tomar todos los incidentes de disco en un tipo separado de "disco HW" y agregarle los campos "bloquear nombre de dispositivo", "tamaño" y "tipo de disco" para que esta información se guarde en el ticket y no tenga que chateando constantemente.
También acordamos que, en el marco de un incidente, cambiaremos un solo disco. Esto simplificó enormemente el proceso de automatización, la recopilación de estadísticas y el trabajo.
Además, se agregó el campo "administrador responsable". El administrador del sistema se sustituye automáticamente allí. Esto es muy conveniente, porque ahora el ingeniero siempre ve quién es responsable. No es necesario ir al calendario y buscar. Fue este campo el que permitió colocar tickets en el tablero del administrador, en el cual, tal vez, su ayuda sería necesaria.
Para garantizar que todos los participantes reciban el máximo beneficio de las innovaciones, creamos filtros y paneles, les contamos a los muchachos sobre ellos. Cuando las personas entienden los cambios, no se distancian de ellos como de algo innecesario. Es importante que un ingeniero sepa el número de rack donde se encuentra el servidor, el tamaño y el tipo de disco. El administrador necesita, en primer lugar, comprender qué tipo de grupo de servidores es este, qué tipo de efecto puede tener al reemplazar un disco.
La presencia de campos y su visualización es conveniente, pero esto no nos salvó de la necesidad de usar chats. Para hacer esto, tuve que cambiar el flujo de trabajo.
Solía ser así:
Hoy, los ingenieros continúan trabajando así cuando no necesitan ayuda del administrador.
Lo primero que hicimos fue introducir un nuevo estado
Investigar . El ticket está en este estado cuando el ingeniero aún no ha decidido si necesitará un administrador o no. A través de este estado, el ingeniero puede pasar el ticket al administrador. Además, marcamos los tickets con este estado cuando se requiere un reemplazo del disco, pero no hay ningún disco en el sitio. Esto sucede con CDN y sitios remotos.
También agregamos el estado
Listo . El ticket se transfiere a él después de reemplazar el disco. Es decir, todo ya se ha hecho, pero RAID HW / SW está sincronizado en el servidor. Esto puede llevar bastante tiempo.
Si hay un administrador involucrado, el esquema es un poco más complicado.
Desde el estado
Abierto , un ticket puede ser transferido tanto por un administrador del sistema como por un ingeniero. En el estado
En progreso , el administrador elimina el disco de la rotación para que el ingeniero pueda simplemente eliminarlo: enciende la luz de fondo, desmonta el disco y detiene las aplicaciones, según el grupo de servidores específico.
Luego, el boleto se convierte en
Listo para cambiar : esta es una señal para el ingeniero de que el disco puede extraerse. Todos los campos en Jira ya están llenos, el ingeniero sabe qué tipo y tamaño del disco. Estos datos se colocan en el estado anterior automáticamente o por el administrador.
Después de reemplazar el disco, el ticket se transfiere al estado
Modificado . Se verifica que se ha insertado el disco correcto, se realiza el marcado, se inicia la aplicación y se realizan algunas tareas de recuperación de datos. Además, el ticket se puede transferir al estado
Listo , en cuyo caso el administrador seguirá siendo responsable, porque inició el disco en rotación. El esquema completo se ve así.
Agregar nuevos campos hizo nuestra vida mucho más fácil. Los chicos comenzaron a trabajar con información estructurada, quedó claro qué y en qué etapa hacer. Las prioridades se han vuelto mucho más relevantes ya que ahora las establece el administrador.
La necesidad de chats ha desaparecido. Por supuesto, el administrador puede escribirle al ingeniero "necesita reemplazar más rápido aquí" o "ya por la noche, ¿tendrá tiempo de reemplazar?". Pero ya no chateamos diariamente sobre estos temas.
Los discos comenzaron a cambiar en paquetes. Si el administrador vino a trabajar un poco antes, tiene tiempo libre y no ha pasado nada, puede preparar una serie de servidores para su reemplazo: colocar campos, eliminar discos de la rotación y transferir la tarea al ingeniero. Más tarde, un ingeniero llega al centro de datos, ve la tarea, toma las unidades necesarias del almacén y la cambia de inmediato. Como resultado, la velocidad de reemplazo ha aumentado.
Lecciones aprendidas en el flujo de trabajo del edificio
- Al crear un procedimiento, debe recopilar información de diferentes fuentes.
Algunos de nuestros administradores no sabían que el ingeniero cambió los discos por su cuenta. Algunos pensaban que los ingenieros supervisaban la sincronización RAID de MD, aunque algunos de ellos ni siquiera tenían acceso a esto. Algunos ingenieros líderes hicieron esto, pero no siempre, porque el proceso no se describió en ninguna parte. - El procedimiento debe ser simple y directo.
Es difícil para una persona mantener muchos pasos en su cabeza. Los estados vecinos más importantes en Jira deben mostrarse en la pantalla principal. Puede cambiarles el nombre, por ejemplo, en progreso llamamos Listo para cambiar. Y los estados restantes se pueden ocultar en el menú desplegable para que no tengan ojos callosos. Pero es mejor no limitar a las personas, dar la oportunidad de hacer la transición.
Explicar el valor de la innovación. Cuando las personas entienden, mejor aceptan el nuevo procedimiento. Para nosotros era muy importante que la gente no llamara todo el proceso, sino que lo siguiera. Luego construimos sobre esta automatización. - Espera, analiza, comprende.
Nos llevó alrededor de un mes construir el procedimiento, la implementación técnica, las reuniones y las discusiones. Y para la implementación: más de tres meses. Vi cómo la gente lentamente comienza a usar la innovación. En las primeras etapas, había mucha negatividad. Pero él era completamente independiente del procedimiento en sí, su implementación técnica. Por ejemplo, un administrador no usó Jira, sino el complemento Jira en Confluence, y algunas cosas no estaban disponibles para él. Le mostró a Jira, el administrador ha aumentado la productividad y las tareas generales, y para reemplazar discos.
Automatización de reemplazo de unidades
Pasamos a la automatización de reemplazar discos varias veces. Ya teníamos tiempo de operación, scripts, pero todos funcionaban de forma interactiva o en modo manual, requerían lanzamiento. Y solo después de la introducción del nuevo procedimiento, nos dimos cuenta de que solo faltaba.
Como ahora el proceso de reemplazo se divide en etapas, cada una de las cuales tiene un ejecutor y una lista de acciones, podemos activar la automatización en etapas, y no todas a la vez. Por ejemplo, el paso más simple: Listo (comprobación de RAID / sincronización de datos) se puede delegar fácilmente en el bot. Cuando el bot aprende un poco, puede asignarle una tarea más responsable: poner el disco en rotación, etc.
Configuraciones de zoológico
Antes de hablar sobre el bot, haremos una pequeña excursión a nuestro zoológico de instalación. En primer lugar, se debe al tamaño gigantesco de nuestra infraestructura. En segundo lugar, para cada servicio intentamos elegir la configuración óptima del hierro. Tenemos alrededor de 20 modelos RAID de hardware, principalmente LSI y Adaptec, pero hay HP y DELL de diferentes versiones. Cada controlador RAID tiene su propia utilidad de administración. El conjunto de comandos y su emisión pueden diferir de una versión a otra de cada controlador RAID. Donde no se utiliza HW-RAID, puede ser mdraid.
Casi todas las instalaciones nuevas que hacemos sin copia de seguridad de disco. Intentamos dejar de usar RAID de hardware y software, ya que reservamos nuestros sistemas a nivel de centros de datos, no de servidores. Pero, por supuesto, hay muchos servidores heredados que deben ser compatibles.
En algún lugar, los discos en los controladores RAID lanzan dispositivos sin formato; en algún lugar, usan JBOD. Hay configuraciones con una unidad de sistema en el servidor, y si necesita reemplazarlo, debe volver a formatear el servidor con la instalación del sistema operativo y las aplicaciones, con las mismas versiones, luego agregar archivos de configuración, iniciar aplicaciones. También hay muchos grupos de servidores donde la redundancia se lleva a cabo no a nivel del subsistema de disco, sino directamente en las propias aplicaciones.
En total, tenemos más de 400 grupos únicos de servidores que ejecutan alrededor de 100 aplicaciones diferentes. Para cubrir tantas opciones, necesitábamos una herramienta de automatización multifuncional. Es aconsejable con un DSL simple, de modo que no solo la persona que escribió esto pueda soportarlo.
Elegimos Ansible porque no tiene agentes: no había necesidad de preparar la infraestructura, inicio rápido. Además, está escrito en Python, que es aceptado como estándar en el equipo.
Esquema general
Veamos un esquema de automatización general usando un incidente como ejemplo. Zabbix detecta que la unidad sdb está fuera de servicio, el gatillo se enciende y se crea un ticket en Jira. El administrador lo miró, se dio cuenta de que esto no es un duplicado ni un falso positivo, es decir, que necesita cambiar el disco y traduce el ticket en curso.

La aplicación DiskoBot escrita en Python sondea periódicamente Jira en busca de nuevos boletos. Se da cuenta de que ha aparecido un nuevo ticket En progreso, se activa el hilo correspondiente, que inicia el libro de jugadas en Ansible (esto se hace para cada estado en Jira). En este caso, se inicia Prepare2change.
Ansible va al host, elimina el disco de la rotación e informa el estado a la aplicación a través de Callbacks.

Según los resultados, el bot transfiere automáticamente el ticket a Listo para cambiar. El ingeniero recibe una notificación y va a cambiar el disco, luego de lo cual transfiere el ticket a Cambiado.

De acuerdo con el esquema anterior, el ticket vuelve al bot, lanza otro libro de jugadas, va al host y entra al disco en rotación. El bot cierra el boleto. ¡Hurra!

Ahora hablemos sobre algunos de los componentes del sistema.
Diskobot
Esta aplicación está escrita en Python. Selecciona entradas de Jira de acuerdo con
JQL . Dependiendo del estado del ticket, este último llega al controlador correspondiente, que a su vez inicia el estado del libro de jugadas Ansible correspondiente.
JQL y los intervalos de sondeo se definen en el archivo de configuración de la aplicación.
jira_states: investigate: jql: '… status = Open and "Disk Size" is EMPTY' interval: 180 inprogress: jql: '… and "Disk Size" is not EMPTY and "Device Name" is not EMPTY' ready: jql: '… and (labels not in ("dbot_ignore") or labels is EMPTY)' interval: 7200
Por ejemplo, entre los tickets en estado En progreso, solo se completan aquellos con los campos Tamaño del disco y Nombre del dispositivo. Nombre del dispositivo es el nombre del dispositivo de bloque necesario para ejecutar el libro de jugadas. Se necesita el tamaño del disco para que el ingeniero sepa qué tamaño de disco se necesita.
Y entre los tickets con el estado Listo, los tickets con la etiqueta dbot_ignore se filtran. Por cierto, utilizamos etiquetas de Jira tanto para dicho filtrado, como para marcar tickets duplicados y para recopilar estadísticas.
Si el libro de jugadas falla, Jira asigna la etiqueta dbot_failed para que puedas resolverlo más tarde.
Interacción con Ansible
La aplicación interactúa con Ansible a través de la
API Ansible Python . En playbook_executor, pasamos el nombre del archivo y el conjunto de variables. Esto le permite mantener el proyecto Ansible en forma de archivos yml regulares, en lugar de describirlo en código Python.
También en Ansible a través de * extra_vars * se usa el nombre del dispositivo de bloqueo, el estado del ticket, así como callback_url, en el que se conecta la clave de emisión, se usa para la devolución de llamada en HTTP.
Para cada lanzamiento, se genera un inventario temporal, que consta de un host y el grupo al que pertenece este host para que se aplique group_vars.
Aquí hay un ejemplo de una tarea en la que se implementa la devolución de llamada HTTP.
El resultado de los libros de jugadas que obtenemos usando callaback (s). Son de dos tipos:
- Complemento de devolución de llamada , proporciona datos sobre los resultados de un libro de jugadas. Describe las tareas que se iniciaron, que se realizaron con éxito o sin éxito. Esta devolución de llamada se llama al final del libro de jugadas.
- Devolución de llamada HTTP para obtener información mientras juega un libro de jugadas. En Ansible, realizamos una solicitud POST / GET al lado de nuestra aplicación.
Mediante las devoluciones de llamada HTTP, se transmiten las variables que se definieron durante la ejecución del libro de jugadas y que queremos guardar y usar en ejecuciones posteriores. Escribimos estos datos en sqlite.
También a través de la devolución de llamada HTTP dejamos comentarios y cambiamos el estado del ticket.
Devolución de llamada HTTP # Make callback to Diskobot App # Variables: # callback_post_body: # A dict with follow keys. All keys are optional # msg: If exist it would be posted to Jira as comment # data: If exist it would be saved in Incident.variables # desire_state: Set desire_state for incident # status: If exist Proceed issue to that status - name: Callback to Diskobot app (jira comment/status) uri: url: "{{ callback_url }}/{{ devname }}" user: "{{ diskobot_user }}" password: "{{ diskobot_pass }}" force_basic_auth: True method: POST body: "{{ callback_post_body | to_json }}" body_format: json delegate_to: 127.0.0.1
Al igual que muchas de las mismas tareas, lo colocamos en un archivo común separado y lo incluimos si es necesario, para que no se repita constantemente en los libros de jugadas. Callback_ url aparece aquí, en el que la clave de problema y el nombre de host están protegidos. Cuando Ansible ejecuta esta solicitud POST, el bot se da cuenta de que vino como parte de dicho incidente.
Y aquí hay un ejemplo de un libro de jugadas, en el que mostramos un disco de un dispositivo MD:
# Save mdadm configuration - include: common/callback.yml vars: callback_post_body: status: 'Ready to change' msg: "Removed disk from mdraid {{ mdadm_remove_disk.msg | comment_jira }}" data: mdadm_data: "{{ mdadm_remove_disk.removed }}" parted_info: "{{ parted_info | default() }}" when: - mdadm_remove_disk | changed - mdadm_remove_disk.removed
Esta tarea coloca el ticket Jira en el estado "Listo para cambiar" y agrega un comentario. Además, la variable mdam_data almacena la lista de dispositivos md de los que se eliminó el disco, y el volcado dividido de parted en parted_info.
Cuando el ingeniero inserta un nuevo disco, podremos utilizar estas variables para restaurar el volcado de la partición, así como insertar el disco en los dispositivos md de los que se eliminó.
Modo de verificación ansible
Encender la automatización daba miedo. Por lo tanto, decidimos ejecutar todos los libros de jugadas en modo
ejecución en
seco , en la que Ansible no realiza ninguna acción en los servidores, sino que solo los emula.
Tal lanzamiento se ejecuta a través de un módulo de devolución de llamada separado, y el resultado del libro de jugadas se guarda en Jira como un comentario.

En primer lugar, permitió validar el trabajo del bot y los libros de jugadas. En segundo lugar, aumentó la confianza de los administradores en el bot.
Cuando realizamos la validación y nos dimos cuenta de que puede ejecutar Ansible no solo en modo de ejecución en seco, creamos el botón Ejecutar Diskobot en Jira para iniciar el mismo libro de jugadas con las mismas variables en el mismo host, pero en modo normal.
Además, el botón se usa para reiniciar el libro de jugadas en caso de falla.
Estructura de Playbooks
Ya mencioné que, dependiendo del estado del boleto de Jira, el bot lanza diferentes libros de jugadas.
En primer lugar, es mucho más fácil organizar la entrada.
En segundo lugar, en algunos casos es simplemente necesario.
Por ejemplo, cuando reemplace un disco del sistema, primero debe ir al sistema de implementación, crear una tarea y, después de la implementación correcta, se podrá acceder al servidor a través de ssh, y puede colocar la aplicación en él. Si hiciéramos todo esto en un libro de jugadas, Ansible no podría ejecutarlo debido a la inaccesibilidad del host.
Utilizamos roles Ansible para cada grupo de servidores. Aquí puede ver cómo se organizan los libros de jugadas en uno de ellos.

Esto es conveniente, porque está claro de inmediato dónde se ubican las tareas. En main.yml, que es la entrada para el rol Ansible, podemos incluir por estado del ticket o tareas generales necesarias para todos, por ejemplo, pasar la identificación o recibir un token.
Investigation.yml
Corre por entradas en el estado de Investigación y Abierto. Lo más importante para este libro de jugadas es el nombre del dispositivo de bloque. Esta información no siempre está disponible.
Para obtenerlo, analizamos el resumen de Jira, el último valor del activador de Zabbix. Puede contener el nombre del dispositivo de bloqueo, por suerte. O puede contener un punto de montaje, entonces debe ir al servidor, analizar y calcular la unidad deseada. Además, un disparador puede transmitir una dirección scsi o alguna otra información. Pero también sucede que no hay pistas, y hay que analizar.
Después de descubrir el nombre del dispositivo de bloque, recopilamos información sobre el tipo y el tamaño del disco para completar los campos en Jira. También eliminamos información sobre el proveedor, modelo, firmware, ID, SMART e insertamos todo esto en un comentario en el ticket de Jira. El administrador y el ingeniero ya no necesitan buscar estos datos. :)
prepare2change.yml
La salida del disco de rotación, preparación para el reemplazo. La etapa más difícil y crucial. Aquí es donde puede detener la aplicación cuando no se puede detener. O extraiga un disco que no tenía suficientes réplicas y, por lo tanto, tiene un efecto en los usuarios, pierde algunos datos. Aquí tenemos la mayoría de los controles y notificaciones en el chat.
En el caso más simple, estamos hablando de quitar una unidad de RAID HW / MD.
En situaciones más complejas (en nuestros sistemas de almacenamiento), cuando la copia de seguridad se realiza a nivel de aplicación, debe ir a la aplicación utilizando la API, informar la salida del disco, desactivarla e iniciar la recuperación.
Ahora estamos migrando masivamente a la
nube , y si el servidor está nublado, entonces Diskobot accede a la API de la nube, dice que funcionará con este minion, el servidor en el que se ejecutan los contenedores, y pregunta "migrar todos los contenedores de este minion". Y al mismo tiempo enciende la luz de fondo para que el ingeniero vea de inmediato cuál sacar.
cambian.yml
Después de reemplazar un disco, primero verificamos su disponibilidad.
Los ingenieros no siempre colocan discos nuevos, por lo que agregamos una verificación de los valores SMART que nos satisfacen.
¿Qué atributos estamos viendo?Recuento de sectores reasignados (5) <100
Recuento actual del sector pendiente (107) == 0
Si la unidad falla la prueba, el ingeniero es notificado de un reemplazo. Si todo está en orden, la luz de fondo se apaga, se aplica el marcado y el disco se inserta en rotación.
ready.yml
El caso más simple: verificar la sincronización de banda HW / SW o finalizar la sincronización de datos en la aplicación.
API de aplicación
Mencioné varias veces que el bot a menudo accede a las API de la aplicación. Por supuesto, no todas las aplicaciones tenían los métodos necesarios, así que tuve que refinarlas. Estos son los métodos más importantes que utilizamos:
- Estado El estado de un clúster o disco para comprender si es posible trabajar con él;
- Iniciar / detener Activación-desactivación del disco;
- Migrar / restaurar. Migración y recuperación de datos durante y después del reemplazo.
Lecciones aprendidas por Ansible
Realmente amo a Ansible. Pero a menudo, cuando miro diferentes proyectos de código abierto y veo cómo la gente escribe libros de jugadas, me asusto un poco. Tejido lógico complejo de when / loop, falta de flexibilidad e idempotencia debido al uso frecuente de shell / command.
Decidimos simplificar todo lo más posible, aprovechando Ansible: modularidad. En el nivel más alto están los libros de jugadas, pueden ser escritos por cualquier administrador, un desarrollador externo que conozca un poco a Ansible.
- name: Blink disk become: True register: locate_action disk_locate: locate: '{{ locate }}' devname: '{{ devname }}' ids: '{{ locate_ids | default(pd_id) | default(omit) }}'
Si alguna lógica es difícil de implementar en libros de jugadas, la colocamos en un módulo o filtro Ansible. Las secuencias de comandos se pueden escribir tanto en Python como en cualquier otro idioma.
Son fáciles y rápidos de escribir. Por ejemplo, el módulo de resaltado de disco, un ejemplo del uso que se da arriba, consta de 265 líneas.

En el nivel más bajo está la biblioteca. Para este proyecto, escribimos una aplicación separada, una especie de abstracción sobre los RAID de hardware y software que realizan las solicitudes correspondientes.

Las mayores fortalezas de Ansible son su simplicidad y sus comprensibles libros de jugadas. Creo que debe usar esto y no generar archivos yaml de miedo y una gran cantidad de condiciones, código de shell y bucles.
Si desea repetir nuestra experiencia con la API de Ansible, tenga en cuenta dos cosas:
- Playbook_executor y, en general, el libro de jugadas no se puede agotar. Hay un tiempo de espera en la sesión ssh, pero no hay tiempo de espera en el libro de jugadas. Si tratamos de desmontar una unidad que aún no existe en el sistema, el libro de jugadas se ejecutará indefinidamente, por lo que tuvimos que envolverlo en un contenedor separado y matarlo por tiempo de espera.
- Ansible está bifurcado, por lo que su API no es segura para subprocesos. Lanzamos todos nuestros libros de jugadas y de un solo hilo.
Como resultado, pudimos automatizar el reemplazo de aproximadamente el 80% de las unidades. En general, la tasa de reemplazo se ha duplicado. Hoy, el administrador solo mira el incidente y decide si cambia el disco o no, y luego hace un clic.
Pero ahora estamos comenzando a enfrentar otro problema: algunos administradores nuevos no saben cómo cambiar las unidades. :)