6. Eliminando el trabajo pesado (Toil)

Por David Challoner, Joanna Wijntjes, David Huska,
Matthew Sartwell, Chris Coykendall, Chris Schrier, John Looney y Vivek Rau
con Betsy Beyer, Max Luebbe, Alex Perry y Murali Suriar.

Los SRE de Google dedican gran parte de su tiempo a la optimización, es decir, a extraer el máximo rendimiento de un sistema mediante el trabajo en proyectos y la colaboración de los desarrolladores. Pero el alcance de la optimización no se limita a los recursos informáticos: también es importante que los SRE optimicen cómo emplean su tiempo. Principalmente, queremos evitar realizar tareas clasificadas como pesadas. Para un análisis exhaustivo del trabajo, consulte el Capítulo 5 de Site Reliability Engineering. Para los propósitos de este capítulo, definiremos el trabajo pesado como el flujo repetitivo, predecible y constante de tareas relacionadas con el mantenimiento de un servicio.

El trabajo pesado es aparentemente inevitable para cualquier equipo que gestione un servicio de producción. El mantenimiento del sistema exige inevitablemente una cierta cantidad de despliegues, actualizaciones, reinicios, triaje de alertas, etcétera. Estas actividades pueden consumir rápidamente a un equipo si no se controlan y contabilizan. Google limita al 50% el tiempo que los equipos de SRE dedican al trabajo operativo (incluyendo tanto el trabajo pesado como el que no lo es) (para saber por qué, consulte el capítulo 5 de nuestro primer libro). Aunque este objetivo puede no ser apropiado para su organización, sigue siendo ventajoso establecer un límite superior para el trabajo pesado, ya que identificar y cuantificar el trabajo pesado es el primer paso hacia la optimización del tiempo de su equipo.

El trabajo pesado tiende a situarse en un espectro que se mide por las siguientes características, descritas en nuestro primer libro. A continuación, presentamos un ejemplo concreto de cada característica del trabajo pesado:

  • Manual: Cuando el directorio tmp de un servidor web alcanza el 95% de utilización, la ingeniera Anne se conecta al servidor y recorre el sistema de archivos en busca de archivos de registro superfluos para eliminarlos.
  • Repetitivo: Es poco probable que un directorio tmp lleno se produzca una sola vez, por lo que la tarea de solucionarlo es repetitiva.
  • Automatizable1): Si su equipo tiene documentos de corrección con contenidos como “inicie sesión en X, ejecute este comando, compruebe la salida, reinicie Y si ve…”, estas instrucciones son esencialmente pseudocódigo para alguien con conocimientos de desarrollo de software. En el ejemplo del directorio tmp, la solución se ha automatizado parcialmente. Sería aún mejor automatizar completamente la detección y corrección del problema, sin necesidad de que un humano ejecute el script. Mejor aún, enviar un parche para que el software ya no se rompa de esta manera.
  • No tácticas/reactivas: Cuando se reciben demasiadas alertas del tipo “disco lleno” o “servidor caído”, los ingenieros se distraen de tareas de ingeniería de mayor valor y pueden enmascarar otras alertas de mayor gravedad. Como resultado, la salud del servicio se resiente.
  • Carece de valor duradero: Completar una tarea a menudo aporta una satisfactoria sensación de logro, pero esta satisfacción repetitiva no es positiva a largo plazo. Por ejemplo, cerrar ese ticket generado por una alerta garantizó que las consultas de los usuarios siguieran fluyendo y que las peticiones HTTP siguieran sirviendo con códigos de estado < 400, lo cual es bueno. Sin embargo, resolver el ticket hoy no evitará el problema en el futuro, por lo que la amortización tiene una duración corta.
  • Crece al menos tan rápido como su origen: Muchas clases de trabajo operativo crecen tan rápido (o más) que el tamaño de la infraestructura subyacente. Por ejemplo, se puede esperar que el tiempo dedicado a realizar reparaciones de hardware aumente de forma paralela al tamaño de una flota de servidores. El trabajo de reparación física puede escalar inevitablemente con el número de máquinas, pero las tareas auxiliares (por ejemplo, realizar cambios de software/configuración) no tienen por qué hacerlo.

Las fuentes de trabajo pesado no siempre cumplen todos estos criterios, pero recuerde que el trabajo pesado puede adoptar muchas formas. Además de los rasgos anteriores, considere el efecto que un determinado trabajo tiene en la moral del equipo. ¿La gente disfruta haciendo una tarea y la encuentra gratificante, o es el tipo de trabajo que a menudo se descuida porque se considera aburrido o poco gratificante?2) El trabajo pesado puede desinflar lentamente la moral del equipo. El tiempo que se dedica a las tareas pesadas suele ser tiempo que no se dedica a pensar de forma crítica o a expresar la creatividad; reducir las tareas pesadas es reconocer que el esfuerzo de un ingeniero se aprovecha mejor en áreas en las que son posibles el juicio y la expresión humanos.

Ejemplo: Respuesta manual al trabajo pesado

Por John Looney, Director de Ingeniería de Producción en Facebook, y por siempre un SRE de corazón

No siempre está claro que una determinada parte del trabajo sea pesado. A veces, una solución “creativa” -escribir una solución alternativa- no es lo más adecuado. Lo ideal sería que su organización premiara las soluciones que solucionan la causa raíz frente a las que simplemente enmascaran un problema.

Mi primera tarea tras incorporarme a Google (abril de 2005) fue iniciar sesión en máquinas averiadas, investigar por qué estaban averiadas y, a continuación, arreglarlas o enviarlas a un técnico de hardware. Esta tarea parecía sencilla hasta que me di cuenta de que había más de 20,000 máquinas averiadas en un momento dado.

La primera máquina averiada que investigué tenía un sistema de archivos raíz completamente lleno de gigabytes de registros sin sentido de un controlador de red parcheado por Google. Encontré otras mil máquinas averiadas con el mismo problema. Compartí mi plan para solucionar el problema con mi compañero de equipo: Escribiría un script para entrar por ssh en todas las máquinas averiadas y comprobar si el sistema de archivos raíz estaba lleno. Si el sistema de archivos estaba lleno, el script truncaría cualquier registro de más de un megabyte en /var/log y reiniciaría syslog.

La reacción poco entusiasta de mi compañero ante mi plan me hizo reflexionar. Señaló que es mejor solucionar las causas de raíz siempre que sea posible. A medio y largo plazo, escribir un script que ocultara la gravedad del problema supondría una pérdida de tiempo (al no solucionar el problema real) y podría causar más problemas más adelante.

El análisis demostró que cada servidor costaba probablemente 1 dólar por hora. Según mi línea de pensamiento, ¿no debería ser el costo el parámetro más importante? No había tenido en cuenta que si arreglaba el síntoma, no habría incentivo para arreglar la causa de fondo: el conjunto de pruebas de lanzamiento del equipo del kernel no comprobaba el volumen de registros que producían estas máquinas.

El ingeniero jefe me dirigió al código fuente del kernel para que encontrara la línea de código ofensiva y registrara un error contra el equipo del kernel para mejorar su conjunto de pruebas. Mi análisis objetivo de costo/ beneficio, que mostraba que el problema le costaba a Google 1,000 dólares por hora, convenció a los desarrolladores de que lo solucionaran con mi parche.

Mi parche se convirtió en una nueva versión del kernel esa misma tarde, y al día siguiente lo distribuí a las máquinas afectadas. El equipo del núcleo actualizó su conjunto de pruebas a finales de la semana siguiente. En lugar del golpe de endorfina a corto plazo de arreglar esas máquinas cada mañana, ahora tenía el placer más cerebral de saber que había arreglado el problema correctamente.

¿Cómo sabe qué parte de su trabajo operativo es pesado? Y una vez que ha decidido tomar medidas para reducir el trabajo pesado, ¿cómo sabe si sus esfuerzos han tenido éxito o están justificados? Muchos equipos de SRE responden a estas preguntas con una combinación de experiencia e intuición. Aunque estas tácticas pueden producir resultados, podemos mejorarlas.

La experiencia y la intuición no son repetibles, objetivas ni transferibles. Los miembros de un mismo equipo u organización suelen llegar a conclusiones diferentes sobre la magnitud del esfuerzo de ingeniería perdido por el trabajo pesado y, por tanto, priorizan los esfuerzos de corrección de forma diferente. Además, los esfuerzos de reducción del trabajo pesado pueden abarcar trimestres o incluso años (como demuestran algunos de los estudios de casos de este capítulo), durante los cuales pueden cambiar las prioridades y el personal del equipo. Para mantener la concentración y justificar los costos a largo plazo, se necesita una medida objetiva del progreso. Normalmente, los equipos deben elegir un proyecto de reducción del trabajo pesado entre varios candidatos. Una medida objetiva del trabajo pesado permite al equipo evaluar la gravedad de los problemas y priorizarlos para obtener el máximo rendimiento de la inversión en ingeniería.

Antes de iniciar un proyecto de reducción del trabajo pesado, es importante analizar el costo frente al beneficio y confirmar que el tiempo ahorrado gracias a la eliminación del trabajo pesado será (como mínimo) proporcional al tiempo invertido en desarrollar y mantener una solución automatizada (Figura 6-1). Los proyectos que parecen “poco rentables” si se comparan de forma simplista las horas ahorradas con las invertidas pueden merecer la pena debido a los numerosos beneficios indirectos o intangibles de la automatización. Entre las posibles ventajas se incluyen:

  • Aumento del número de proyectos de ingeniería, algunos de los cuales reducirán aún más el trabajo pesado.
  • Aumento de la moral del equipo y disminución de su desgaste y agotamiento.
  • Menos cambios de contexto por interrupciones, lo que aumenta la productividad del equipo
  • Mayor claridad y estandarización de los procesos
  • Mejora de las habilidades técnicas y del desarrollo profesional de los miembros del equipo.
  • Reducción del tiempo de formación
  • Menos interrupciones atribuibles a errores humanos
  • Mayor seguridad
  • Menores tiempos de respuesta a las peticiones de los usuarios

Figura 6-1. Calcula el tiempo que vas a dedicar a reducir el trabajo pesado y asegúrate de que los beneficios compensan los costos (fuente: xkcd.com/1319/).

Entonces, ¿cómo le recomendamos que mida el trabajo pesado?

  1. Identifíquelo. El capítulo 5 del primer libro de SRE ofrece directrices para identificar el trabajo pesado en sus operaciones. Las personas mejor situadas para identificar el trabajo pesado dependen de su organización. Lo ideal es que sean las partes interesadas, incluidas las que realizarán el trabajo real.

  2. Seleccione una unidad de medida adecuada que exprese la cantidad de esfuerzo humano aplicado a este trabajo pesado. Los minutos y las horas son una opción natural porque son objetivos y universalmente comprensibles. Asegúrese de tener en cuenta el costo del cambio de contexto. En el caso de los esfuerzos distribuidos o fragmentados, puede resultar más apropiado otro tipo de unidad de medida del esfuerzo humano. Algunos ejemplos de unidades de medida son un parche aplicado, un ticket completado, un cambio de producción manual, un intercambio de correo electrónico predecible o una operación de hardware. Siempre que la unidad sea objetiva, coherente y bien comprendida, puede servir para medir el trabajo pesado.

  3. Realice un seguimiento continuo de estas mediciones antes, durante y después de los esfuerzos de reducción del trabajo pesado. Racionalice el proceso de medición utilizando herramientas o guiones para que la recopilación de estas mediciones no suponga un trabajo pesado adicional.

El trabajo pesado, como un puente que se derrumba o una presa que gotea, se esconde en lo banal del día a día. Las categorías de esta sección no son exhaustivas, pero representan algunas categorías comunes de trabajo pesado. Muchas de estas categorías parecen trabajos de ingeniería “normales”, y lo son. Resulta útil considerar el trabajo pesado como un espectro y no como una clasificación binaria.

Esta es probablemente la fuente más común de trabajo pesado. Puede que su equipo gestione algún recurso informático -computación, almacenamiento, red, equilibradores de carga, bases de datos, etc.- junto con el hardware que suministra ese recurso. Usted se ocupa de dar de alta a los usuarios, configurar y proteger sus máquinas, realizar actualizaciones de software y añadir y quitar servidores para moderar la capacidad. También trabaja para minimizar el costo o el despilfarro de ese recurso. Su equipo es la interfaz humana con la máquina, normalmente interactuando con clientes internos que presentan tickets para sus necesidades. Su organización puede incluso tener múltiples sistemas de tickets y sistemas de admisión de trabajo.

El trabajo pesado de los tickets es un poco insidioso porque los procesos empresariales basados en tickets suelen cumplir su objetivo. Los usuarios obtienen lo que quieren y, dado que el trabajo pesado suele estar repartido uniformemente por todo el equipo, el trabajo pesado no exige una corrección en voz alta y evidente. Siempre que exista un proceso basado en tickets, existe la posibilidad de que el trabajo pesado se esté acumulando silenciosamente en las proximidades. Incluso si no está planeando explícitamente automatizar un proceso, puede llevar a cabo tareas de mejora de procesos como la simplificación y la racionalización: los procesos serán más fáciles de automatizar más adelante y más fáciles de gestionar mientras tanto.

Las interrupciones son una clase general de tareas de limpieza sensibles al tiempo que mantienen los sistemas en funcionamiento. Por ejemplo, puede que necesite solucionar una escasez aguda de algún recurso (disco, memoria, I/O) liberando manualmente espacio en disco o reiniciando aplicaciones que están perdiendo memoria. Puede que tenga que solicitar la sustitución de discos duros, “patear” sistemas que no responden o ajustar manualmente la capacidad para satisfacer las cargas actuales o previstas. En general, las interrupciones restan atención a tareas más importantes.

En muchas organizaciones, las herramientas de despliegue guían automáticamente las versiones de desarrollo a producción. Incluso con la automatización, la cobertura exhaustiva del código, las revisiones del código y numerosas formas de pruebas automatizadas, este proceso no siempre va bien. Dependiendo de las herramientas y de la cadencia de publicación, las solicitudes de publicación, las reversiones, los parches de emergencia y los cambios de configuración manuales o repetitivos, las publicaciones pueden seguir generando trabajo pesado.

Puede que te encuentres frecuentemente migrando de una tecnología a otra. Realizas este trabajo manualmente o con scripts limitados porque, con suerte, sólo vas a pasar de X a Y una vez. Las migraciones adoptan muchas formas, pero algunos ejemplos incluyen cambios de almacenes de datos, proveedores de nube, sistemas de control de código fuente, bibliotecas de aplicaciones y herramientas.

Si aborda una migración a gran escala de forma manual, es muy probable que la migración implique trabajo pesado. Es posible que se sienta inclinado a ejecutar la migración manualmente porque se trata de un esfuerzo único. Aunque puede que incluso tenga la tentación de considerarlo “trabajo de proyecto” en lugar de “trabajo pesado”, el trabajo de migración también puede cumplir muchos de los criterios de trabajo pesado. Técnicamente, modificar las herramientas de copia de seguridad de una base de datos para que funcionen con otra es desarrollo de software, pero este trabajo consiste básicamente en refactorizar código para sustituir una interfaz por otra. Este trabajo es repetitivo y, en gran medida, el valor empresarial de las herramientas de copia de seguridad es el mismo que antes.

Tanto si se dispone de hardware propio como si se recurre a un proveedor de infraestructuras (nube), la ingeniería de costos y la planificación de la capacidad suelen conllevar cierto trabajo pesado. Por ejemplo:

  • Garantizar una línea de base rentable o una capacidad bursátil para necesidades futuras a través de recursos como la computación, la memoria o las IOPS (operaciones de input/output por segundo). Esto puede traducirse en órdenes de compra, instancias reservadas de AWS o negociación de contratos de nube/infraestructura como servicio.
  • Prepararse para (y recuperarse de) eventos críticos de alto tráfico como el lanzamiento de un producto o unas vacaciones.
  • Revisión de los niveles/límites de servicio descendentes y ascendentes.
  • Optimización de la carga de trabajo frente a diferentes configuraciones de huella. (¿Quiere comprar una caja grande o cuatro cajas más pequeñas?).
  • Optimización de las aplicaciones en función de las especificaciones de facturación de las ofertas de servicios en la nube propios (DynamoDB para AWS o Cloud Datastore para GCP).
  • Refactorización de las herramientas para hacer un mejor uso de los recursos “spot” o “preemptable” más baratos.
  • Gestión del exceso de recursos suscritos, ya sea con su proveedor de infraestructura o con sus clientes.

Las arquitecturas de microservicios distribuidos son ahora comunes, y a medida que los sistemas se vuelven más distribuidos, surgen nuevos modos de fallo. Es posible que una organización no disponga de los recursos necesarios para crear sofisticados sistemas de seguimiento distribuido, supervisión de alta fidelidad o tableros detallados. Incluso si la empresa dispone de estas herramientas, puede que no funcionen con todos los sistemas. La resolución de problemas puede incluso requerir iniciar sesión en sistemas individuales y escribir consultas de análisis de registros ad hoc con herramientas de scripting.

La resolución de problemas en sí no es intrínsecamente mala, pero debería centrar su energía en modos de fallo novedosos, no en el mismo tipo de fallo cada semana causado por una arquitectura de sistemas frágil. Con cada nueva dependencia crítica ascendente de disponibilidad P, la disponibilidad disminuye en 1 - P debido a la probabilidad combinada de fallo. Un servicio de cuatro 9s que añade nueve dependencias críticas de cuatro 9s es ahora un servicio de tres 9s.3)

Hemos comprobado que la gestión del trabajo pesado es fundamental en cualquier sistema de producción. Una vez identificado y cuantificado el trabajo pesado, se necesita un plan para eliminarlo. Estos esfuerzos pueden llevar semanas o trimestres, por lo que es importante contar con una estrategia global sólida.

Eliminar el trabajo pesado en su origen es la solución óptima, pero si no es posible, hay que gestionar el trabajo pesado por otros medios. Antes de entrar en los detalles de dos estudios de casos concretos, esta sección ofrece algunas estrategias generales que deben tenerse en cuenta a la hora de planificar la reducción del trabajo pesado. Como observará en los dos casos, los matices del trabajo pesado varían de un equipo a otro (y de una empresa a otra), pero independientemente de la especificidad, algunas tácticas comunes son válidas para organizaciones de cualquier tamaño o tipo. Cada uno de los siguientes patrones se ilustra de forma concreta en al menos uno de los estudios de caso siguientes.

Le recomendamos que adopte un enfoque basado en datos para identificar y comparar las fuentes de trabajo pesado, tomar decisiones correctivas objetivas y cuantificar el tiempo ahorrado (rendimiento de la inversión) gracias a los proyectos de reducción del trabajo pesado. Si su equipo experimenta una sobrecarga de trabajo pesado, trate la reducción del trabajo pesado como un proyecto propio. Los equipos de SRE de Google suelen realizar un seguimiento del trabajo pesado en los errores y lo clasifican en función del costo que supone solucionarlo y del tiempo que se ahorra al hacerlo. Consulta la sección “Medición del trabajo pesado” para obtener información sobre técnicas y orientación.

La estrategia óptima para gestionar el trabajo pesado es eliminarlo en su origen. Antes de invertir esfuerzos en gestionar el trabajo pesado generado por los sistemas y procesos existentes, examine si puede reducirlo o eliminarlo cambiando el sistema.

Un equipo que gestiona un sistema en producción tiene una experiencia inestimable sobre su funcionamiento. Conocen las peculiaridades y las partes tediosas que causan la mayor cantidad de trabajo pesado. Un equipo de SRE debe aplicar este conocimiento trabajando con los equipos de desarrollo de productos para desarrollar software operativo que no sólo sea menos pesado, sino también más escalable, seguro y resistente.

Un equipo cargado de trabajo pesado debe tomar decisiones basadas en datos sobre la mejor manera de emplear su tiempo y su esfuerzo de ingeniería. Según nuestra experiencia, aunque pueda parecer contraproducente, rechazar una tarea que requiera mucho trabajo debería ser la primera opción a considerar. Para un determinado conjunto de trabajo pesado, analice el costo de responder al trabajo pesado frente a no hacerlo. Otra táctica consiste en retrasar intencionadamente el trabajo pesado para que las tareas se acumulen y puedan procesarse por lotes o en paralelo. Trabajar con el trabajo pesado en agregados más grandes reduce las interrupciones y le ayuda a identificar patrones de trabajo pesado que puede eliminar.

Como se indica en el capítulo 2, los servicios deben tener un objetivo de nivel de servicio (SLO) documentado. Un SLO bien definido permite a los ingenieros tomar decisiones informadas. Por ejemplo, se podrían ignorar ciertas tareas operativas si al hacerlo no se consume o excede el presupuesto de errores del servicio. Un SLO que se centra en la salud general del servicio, en lugar de en los dispositivos individuales, es más flexible y sostenible a medida que el servicio crece. Consulte el Capítulo 2 para obtener orientación sobre cómo redactar SLO eficaces.

Si tiene un problema de negocio especialmente complejo con muchos casos o tipos de solicitudes, considere un enfoque parcialmente automatizado como paso intermedio hacia la automatización completa. En este enfoque, su servicio recibe datos estructurados, normalmente a través de una API definida, pero los ingenieros pueden seguir encargándose de algunas de las operaciones resultantes. Aunque siga habiendo cierto esfuerzo manual, este enfoque de “ingeniero detrás de la cortina” le permite avanzar gradualmente hacia la automatización total. Utilice las aportaciones de los clientes para avanzar hacia una forma más uniforme de recopilar estos datos; al disminuir las solicitudes de forma libre, puede acercarse a la gestión de todas las solicitudes mediante programación. Este enfoque puede ahorrarle las idas y venidas con los clientes (que ahora tienen indicadores claros de la información que usted necesita) y evitarle un exceso de ingeniería en una solución a gran escala antes de haber mapeado y entendido completamente el dominio.

Una vez que haya definido su oferta de servicios a través de una interfaz tipificada (consulte “Empezar con interfaces humanas”), pase a proporcionar métodos de autoservicio para los usuarios. Puede proporcionar un formulario web, un binario o script, una API o incluso simplemente documentación que indique a los usuarios cómo enviar solicitudes pull a los archivos de configuración de su servicio. Por ejemplo, en lugar de pedir a los ingenieros que presenten un ticket para aprovisionar una nueva máquina virtual para su trabajo de desarrollo, proporcióneles un sencillo formulario web o script que active el aprovisionamiento. Permita que el script se convierta en un ticket para solicitudes especializadas o si se produce un fallo.4 Las interfaces respaldadas por humanos son un buen comienzo en la guerra contra el trabajo pesado, pero los propietarios de los servicios siempre deben intentar que sus ofertas sean autoservicio en la medida de lo posible.

A corto plazo, los proyectos de reducción de trabajo pesado reducen el personal disponible para atender solicitudes de funciones, mejoras de rendimiento y otras tareas operativas. Pero si la reducción de trabajo pesado tiene éxito, a largo plazo el equipo estará más sano y contento, y tendrá más tiempo para mejoras de ingeniería.

Es importante que todos los miembros de la organización estén de acuerdo en que la reducción del trabajo pesado es un objetivo que merece la pena. El apoyo de los directivos es crucial para defender al personal de las nuevas exigencias. Utilice indicadores objetivos sobre el trabajo pesado para defender la reducción.

Para crear argumentos comerciales sólidos a favor de la reducción del trabajo pesado, busque oportunidades de combinar su estrategia con otras características u objetivos empresariales deseables. Si un objetivo complementario -por ejemplo, la seguridad, la escalabilidad o la fiabilidad- resulta convincente para sus clientes, estarán más dispuestos a renunciar a sus actuales sistemas generadores de trabajo pesado por otros nuevos y relucientes que no requieran tanto trabajo pesado. Además, la reducción del trabajo pesado es sólo un efecto secundario de la ayuda a los usuarios.

No intente diseñar el sistema perfecto que elimine todo el trabajo pesado. Automatice primero algunos elementos de alta prioridad y, a continuación, mejore su solución utilizando el tiempo ganado al eliminar ese trabajo pesado, aplicando las lecciones aprendidas por el camino. Elija parámetros claros, como el tiempo medio de reparación (MTTR), para medir su éxito.

A escala, un entorno de producción diverso se vuelve exponencialmente más difícil de gestionar. Los dispositivos especiales requieren una gestión continua y una respuesta a incidentes que requieren mucho tiempo y son propensos a errores. Puede utilizar el enfoque de “mascotas frente a ganado ”4) para añadir redundancia y reforzar la uniformidad de su entorno. La elección de lo que se considera ganado depende de las necesidades y la escala de una organización. Puede ser razonable evaluar enlaces de red, switches, máquinas, racks de máquinas o incluso clusters enteros como unidades intercambiables.

Cambiar los dispositivos a una filosofía de ganado puede tener un costo inicial elevado, pero puede reducir el costo de mantenimiento, recuperación ante desastres y utilización de recursos a medio y largo plazo. Equipar varios dispositivos con la misma interfaz implica que tienen una configuración coherente, son intercambiables y requieren menos mantenimiento. Una interfaz coherente (para desviar el tráfico, restablecerlo, realizar un apagado, etc.) para diversos dispositivos permite una automatización más flexible y escalable.

Google alinea los incentivos empresariales para animar a los equipos de ingeniería a unificarse a través de nuestro siempre cambiante conjunto de herramientas y tecnologías internas. Los equipos son libres de elegir sus propios enfoques, pero tienen que asumir el trabajo pesado que generan las herramientas no compatibles o los sistemas heredados.

La automatización puede ahorrar incontables horas de trabajo humano, pero en las circunstancias equivocadas, también puede desencadenar interrupciones. En general, el software defensivo es siempre una buena idea; cuando la automatización ejerce poderes a nivel de administrador, el software defensivo es crucial. Hay que evaluar la seguridad de cada acción antes de ejecutarla. Esto incluye los cambios que puedan reducir la capacidad de servicio o la redundancia. A la hora de implantar la automatización, recomendamos las siguientes prácticas:

  • Maneje las entradas de los usuarios de forma defensiva, incluso si esas entradas proceden de sistemas anteriores, es decir, asegúrese de validarlas cuidadosamente en su contexto.
  • Incorpora salvaguardas equivalentes a los tipos de alertas indirectas que podría recibir un operador humano. Las salvaguardas pueden ser tan simples como tiempos de espera de comandos, o pueden ser comprobaciones más sofisticadas de las métricas actuales del sistema o del número de interrupciones actuales. Por este motivo, los sistemas de supervisión, alerta e instrumentación deben poder ser utilizados tanto por operadores humanos como por máquinas.
  • Tenga en cuenta que incluso las operaciones de lectura, implementadas ingenuamente, pueden disparar la carga del dispositivo y provocar interrupciones. A medida que aumenta la automatización, estas comprobaciones de seguridad pueden acabar dominando la carga de trabajo.
  • Minimice el impacto de las interrupciones causadas por comprobaciones de seguridad incompletas de la automatización. La automatización debe recurrir por defecto a operadores humanos si se encuentra con una situación insegura.

Una vez identificado un trabajo pesado como automatizable, merece la pena plantearse cómo reflejar mejor el flujo de trabajo humano en el software. Rara vez querrá transcribir literalmente un flujo de trabajo humano en un flujo de trabajo automático. También hay que tener en cuenta que la automatización no debe eliminar la comprensión humana de lo que va mal.

Una vez que el proceso esté bien documentado, hay que intentar dividir el trabajo manual en componentes que puedan implementarse por separado y utilizarse para crear una biblioteca de software componible que otros proyectos de automatización puedan reutilizar más adelante. Como ilustra el próximo caso práctico de reparación de centros de datos, la automatización ofrece a menudo la oportunidad de reevaluar y simplificar los flujos de trabajo humanos.

A veces no es necesario hacer todo el trabajo para reducir el trabajo pesado. Muchos esfuerzos, como las migraciones puntuales, pueden no justificar la creación de herramientas propias a medida, pero probablemente no sea la primera organización que recorre este camino. Busque oportunidades de utilizar o ampliar bibliotecas de terceros o de código abierto para reducir los costos de desarrollo, o al menos para ayudarle en la transición hacia una automatización parcial.

Es importante buscar activamente la opinión de otras personas que interactúan con sus herramientas, flujos de trabajo y automatización. Sus usuarios harán diferentes suposiciones sobre sus herramientas dependiendo de su comprensión de los sistemas subyacentes. Cuanto menos familiarizados estén los usuarios con estos sistemas, más importante es buscar activamente la opinión de los usuarios. Aproveche las encuestas, los estudios de experiencia de usuario (UX) y otros mecanismos para comprender cómo se utilizan sus herramientas, e integre esta retroalimentación para producir una automatización más eficaz en el futuro.

Las opiniones de los usuarios son sólo una de las dimensiones que debe tener en cuenta. Mida también la eficacia de las tareas automatizadas según parámetros como la latencia, la tasa de error, la tasa de repetición de tareas y el tiempo humano ahorrado (en todos los grupos implicados en el proceso). Lo ideal es encontrar medidas de alto nivel que puedan compararse antes y después de cualquier esfuerzo de automatización o reducción del trabajo pesado.

Sistemas heredados

La mayoría de los ingenieros con responsabilidades de tipo SRE se han encontrado con al menos un sistema heredado en su trabajo. Estos sistemas antiguos suelen plantear problemas con respecto a la experiencia del usuario, la seguridad, la fiabilidad o la escalabilidad. Suelen funcionar como una caja negra mágica en la que “casi todo funciona”, pero pocas personas entienden cómo funcionan. Modificarlos da miedo y es caro, y mantenerlos en funcionamiento suele requerir una buena cantidad de laboriosos rituales operativos.

El proceso de abandono de un sistema heredado suele seguir este camino:

  1. Evitarlo: Hay muchas razones para no abordar este problema de frente: puede que no disponga de recursos para sustituir este sistema. Considera que el costo y el riesgo para su empresa no merecen la pena. Puede que no haya ninguna solución sustancialmente mejor disponible en el mercado. Evitar es optar por aceptar la deuda técnica y alejarse de los principios de la SRE para acercarse a la administración de sistemas.

  2. Encapsulación/aumentación: Puede incorporar SRE para construir un armazón de API abstractas, automatización, gestión de la configuración, supervisión y pruebas en torno a estos sistemas heredados que descargarán de trabajo a los SA. El sistema heredado sigue siendo frágil al cambio, pero ahora al menos puede identificar de forma fiable el mal comportamiento y revertirlo cuando proceda. Esta táctica sigue siendo evasiva, pero es un poco como refinanciar la deuda técnica de alto interés para convertirla en deuda técnica de bajo interés. Suele ser una medida provisional para preparar una sustitución gradual.

  3. Sustitución/refactorización: Sustituir un sistema heredado puede requerir mucha determinación, paciencia, comunicación y documentación. Lo mejor es hacerlo gradualmente. Un planteamiento consiste en definir una interfaz común que se sitúe delante del sistema heredado y lo abstraiga. Esta estrategia ayuda a migrar a los usuarios a las alternativas de forma lenta y segura, utilizando técnicas de ingeniería de lanzamiento como el canarying o las implantaciones blue-green. A menudo, la “especificación” de un sistema heredado sólo se define realmente por su uso histórico, por lo que resulta útil construir conjuntos de datos de tamaño de producción de entradas y salidas históricas esperadas para crear confianza en que los nuevos sistemas no se desvían del comportamiento esperado (o se desvían del modo esperado).

  4. Retirada/propiedad de custodia: Con el tiempo, la mayoría de los clientes o funcionalidades se migran a una o más alternativas. Para alinear los incentivos empresariales, los rezagados que no hayan migrado pueden asumir la propiedad custodial de los restos del sistema heredado.

Los siguientes casos de estudio ilustran las estrategias de reducción del trabajo pesado que acabamos de comentar. Cada uno de ellos describe un área importante de la infraestructura de Google que llegó a un punto en el que ya no podía escalarse de forma sublineal con el esfuerzo humano. Ahora reconocerás gran parte de ese esfuerzo como trabajo pesado. En cada caso de estudio, detallamos cómo los ingenieros identificaron, evaluaron y mitigaron ese trabajo pesado. También analizamos los resultados y las lecciones que aprendimos por el camino.

En el primer caso de estudio, la red del centro de datos de Google se enfrentaba a un problema de escalabilidad: teníamos que supervisar, mitigar y reparar un gran número de componentes y enlaces diseñados por Google. Necesitábamos una estrategia que minimizara la ardua tarea de los técnicos del centro de datos.

El segundo caso de estudio se centra en un equipo que ejecuta su propio hardware especializado “atípico” para dar soporte a procesos empresariales intensivos en trabajo pesado que se habían arraigado profundamente en Google. Este caso de estudio ilustra las ventajas de reevaluar y sustituir procesos empresariales costosos desde el punto de vista operativo. Demuestra que, con un poco de persistencia y perseverancia, es posible avanzar hacia alternativas incluso cuando se ven limitadas por la inercia institucional de una gran organización.

En conjunto, estos casos de estudio ofrecen un ejemplo concreto de cada una de las estrategias de reducción del trabajo pesado tratadas anteriormente. Cada caso de estudio comienza con una lista de estrategias de reducción del trabajo pesado.

Nota

Estrategias de reducción del trabajo pesado destacadas en el caso de estudio 1:

  • Reducir el trabajo pesado del sistema
  • Empezar poco a poco e ir mejorando
  • Aumentar la uniformidad
  • Utilizar los SLO para reducir el trabajo pesado
  • Evaluar los riesgos de la automatización
  • Utilice la retroalimentación para mejorar
  • Automatizar la respuesta al trabajo pesado

Antecedentes

Este caso de estudio tiene lugar en los centros de datos de Google. Como en todos los centros de datos, las máquinas de Google están conectadas a conmutadores, que a su vez están conectados a routers. El tráfico entra y sale de estos routers a través de enlaces que, a su vez, se conectan a otros routers de Internet. A medida que crecían las necesidades de Google para gestionar el tráfico de Internet, el número de máquinas necesarias para dar servicio a ese tráfico aumentaba drásticamente. Nuestros centros de datos crecieron en alcance y complejidad a medida que descubríamos cómo dar servicio a una gran cantidad de tráfico de forma eficiente y económica. Este crecimiento cambió la naturaleza de las reparaciones manuales de los centros de datos, que pasaron de ser ocasionales e interesantes a frecuentes y rutinarias, dos señales de trabajo pesado.

Cuando Google comenzó a gestionar sus propios centros de datos, la topología de red de cada uno de ellos contaba con un pequeño número de dispositivos de red que gestionaban el tráfico de un gran número de máquinas. El fallo de un solo dispositivo de red podía afectar significativamente al rendimiento de la red, pero un equipo relativamente pequeño de ingenieros podía encargarse de solucionar los problemas del reducido número de dispositivos. En esta fase inicial, los ingenieros depuraban los problemas y desviaban manualmente el tráfico de los componentes averiados.

Nuestro centro de datos de próxima generación tenía muchas más máquinas e introdujo redes definidas por software (SDN) con una topología Clos plegada, lo que aumentó enormemente el número de conmutadores. La Figura 6-2 muestra la complejidad del flujo de tráfico para una red de conmutadores Clos de un centro de datos pequeño. Este número proporcionalmente mayor de dispositivos significaba que ahora podía fallar un mayor número de componentes. Aunque cada fallo individual tenía menos impacto en el rendimiento de la red que antes, el gran volumen de problemas empezó a abrumar al personal de ingeniería.

Además de introducir una pesada carga de nuevos problemas que depurar, la compleja disposición resultaba confusa para los técnicos: ¿Qué enlaces había que comprobar exactamente? ¿Qué tarjeta de línea5) había que sustituir? ¿Qué era un conmutador de fase 2, frente a uno de fase 1 o 3? ¿Acaso apagar un conmutador crearía problemas a los usuarios?

Figura 6-2. Una pequeña red Clos, que soporta 480 máquinas conectadas por debajo de la Etapa 1

La reparación de las tarjetas de línea de los centros de datos que fallaban era uno de los trabajos pendientes más evidentes, por lo que nos centramos en esta tarea como primera fase de la creación de la automatización de la reparación de redes de centros de datos. Este caso de estudio describe cómo introdujimos la automatización de la reparación en nuestra primera generación de tarjetas de línea (denominada Saturn). A continuación, analizamos las mejoras que introdujimos con la siguiente generación de tarjetas de línea para los tejidos Jupiter.

Como se muestra en la Figura 6-3, antes del proyecto de automatización, cada reparación en el flujo de trabajo de reparación de tarjetas de línea del centro de datos requería que un ingeniero hiciera lo siguiente:

  1. Comprobar que era seguro mover el tráfico del conmutador afectado.

  2. Desplazar el tráfico fuera del dispositivo averiado (una operación de “drenaje”).

  3. Realizar un reinicio o reparación (como la sustitución de una tarjeta de línea).

  4. Desplazar el tráfico de vuelta al dispositivo (una operación de “drenaje”).

Este trabajo constante y repetitivo de vaciar, vaciar y reparar dispositivos es un ejemplo de libro de texto de trabajo pesado. La naturaleza repetitiva del trabajo introduce sus propios problemas: por ejemplo, los ingenieros pueden realizar varias tareas a la vez trabajando en una tarjeta de línea y depurando problemas más complejos. Como resultado, el ingeniero distraído podía introducir accidentalmente un conmutador no configurado en la red.

Figura 6-3. Flujo de trabajo de reparación de tarjetas de línea del centro de datos (Saturn) antes de la automatización: todos los pasos requieren trabajo manual.

Planteamiento del problema

El espacio problemático de las reparaciones del centro de datos tenía las siguientes dimensiones:

  • No podíamos hacer crecer el equipo lo suficientemente rápido como para seguir el ritmo del volumen de fallos, y no podíamos solucionar los problemas lo suficientemente rápido como para evitar un impacto negativo en el tejido.
  • Realizar los mismos pasos de forma repetida y frecuente introducía demasiados errores humanos.
  • No todos los fallos de las tarjetas de línea tenían el mismo impacto. No teníamos forma de priorizar los fallos más graves.
  • Algunos fallos eran transitorios. Queríamos tener la opción de reiniciar la tarjeta de línea o reinstalar el conmutador como primera opción de reparación. Lo ideal sería poder capturar el problema mediante programación si se repetía y marcar el dispositivo para su sustitución.
  • La nueva topología nos obligaba a evaluar manualmente el riesgo de aislar la capacidad antes de poder actuar. Cada evaluación manual del riesgo era una oportunidad para cometer un error humano que podía provocar una interrupción del servicio. Los ingenieros y técnicos de planta no disponían de un buen método para calcular cuántos dispositivos y enlaces se verían afectados por la reparación prevista.

Lo que decidimos hacer

En lugar de asignar cada problema a un ingeniero para la evaluación de riesgos, drenaje, drenaje y validación, decidimos crear un marco para la automatización que, cuando se combina con un técnico in situ en su caso, podría apoyar estas operaciones de forma programática.

Primer esfuerzo de diseño: Reparación de tarjetas de línea Saturn

Nuestro objetivo a alto nivel era construir un sistema que respondiera a los problemas detectados en los dispositivos de red, en lugar de depender de un ingeniero para clasificar y solucionar estos problemas. En lugar de enviar una alerta de “tarjeta de línea averiada” a un ingeniero, escribimos el software para solicitar un drenaje (para eliminar el tráfico) y crear un caso para un técnico. El nuevo sistema tenía algunas características notables:

  • En la medida de lo posible, aprovechamos las herramientas existentes. Como se muestra en la Figura 6-3, nuestras alertas ya podían detectar problemas en las tarjetas fabric; reutilizamos esas alertas para activar una reparación automatizada. El nuevo flujo de trabajo también reutilizó nuestro sistema de tickets para dar soporte a las reparaciones de red.
  • Incorporamos una evaluación de riesgos automatizada para evitar el aislamiento accidental de dispositivos durante un drenaje y activar mecanismos de seguridad cuando fuera necesario. Esto eliminó una enorme fuente de errores humanos.
  • Adoptamos una política de huelgas controlada por software: el primer fallo (o huelga) sólo reiniciaba la tarjeta y reinstalaba el software. Un segundo fallo provocaba la sustitución de la tarjeta y su devolución completa al proveedor.

Implementación

El nuevo flujo de trabajo automatizado (mostrado en la Figura 6-4) se desarrolló del siguiente modo:

  1. Se detecta la tarjeta de línea problemática y se añade un síntoma a un componente específico de la base de datos.

  2. El servicio de reparación detecta el problema y activa la reparación del conmutador. El servicio realiza una evaluación de riesgos para confirmar que la operación no aislará ninguna capacidad y, a continuación:
    1. Drena el tráfico de todo el conmutador.
    2. Apaga la tarjeta de línea.
    3. Si se trata de un primer fallo, reinicia la tarjeta y drena el conmutador, restaurando el servicio en el conmutador. En este punto, el flujo de trabajo está completo.
    4. Si se trata del segundo fallo, el flujo de trabajo procede al paso 3.

  3. El gestor del flujo de trabajo detecta el nuevo caso y lo envía a un grupo de casos de reparación para que un técnico lo reclame.

  4. El técnico reclama el caso, ve un “stop” rojo en la interfaz de usuario (que indica que hay que vaciar el interruptor antes de iniciar la reparación) y ejecuta la reparación en tres pasos:
    1. Inicia el vaciado del chasis mediante un botón “Preparar componente” en la interfaz de usuario del técnico.
    2. Espera a que desaparezca el “stop” rojo, lo que indica que el vaciado se ha completado y que la carcasa es procesable.
    3. Sustituye la tarjeta y cierra el caso.

  5. El sistema automatizado de reparación vuelve a subir la tarjeta de línea. Tras una pausa para dar tiempo a que la tarjeta se inicialice, el gestor de flujo de trabajo activa una operación para restablecer el tráfico al conmutador y cerrar el caso de reparación.

Figura 6-4. Flujo de trabajo de reparación de tarjetas de línea Saturn con automatización: sólo se requiere trabajo manual para pulsar un botón y sustituir la tarjeta de línea.

El nuevo sistema liberó al equipo de ingenieros de un gran volumen de trabajo pesado, lo que les dio más tiempo para dedicarse a otros proyectos productivos: trabajar en Júpiter, la topología Clos de nueva generación.

Diseño Segundo Esfuerzo: Reparación de tarjetas de línea Saturno frente a reparación de tarjetas de línea Júpiter

Los requisitos de capacidad del centro de datos seguían duplicándose casi cada 12 meses. Como resultado, nuestra estructura de centro de datos de próxima generación, Jupiter, era más de seis veces mayor que cualquier estructura anterior de Google. El volumen de problemas también era seis veces mayor. Jupiter presentaba retos de escalado para la automatización de las reparaciones porque miles de enlaces de fibra y cientos de tarjetas de línea podían fallar en cada capa. Afortunadamente, el aumento de los posibles puntos de fallo iba acompañado de una redundancia mucho mayor, lo que significaba que podíamos implementar una automatización más ambiciosa. Como se muestra en la Figura 6-5, conservamos parte del flujo de trabajo general de Saturn y añadimos algunas modificaciones importantes:

  • Después de que un ciclo automatizado de drenaje/reinicio determinara que queríamos sustituir el hardware, enviamos el hardware a un técnico. Sin embargo, en lugar de pedir al técnico que iniciara el vaciado con el botón “Pulsar el botón de preparación para vaciar el interruptor”, vaciábamos automáticamente todo el interruptor cuando fallaba.
  • Añadimos automatización para instalar y pulsar la configuración que se activa tras la sustitución de componentes.
  • Habilitamos la automatización para verificar que la reparación se había realizado correctamente antes de vaciar el interruptor.
  • Centramos la atención en recuperar el interruptor sin involucrar a un técnico a menos que fuera absolutamente necesario.

Figura 6-5. Automatización descendente de la tarjeta de línea Saturn (izquierda) frente a la automatización Júpiter (derecha)

Implementación

Adoptamos un flujo de trabajo sencillo y uniforme para cada problema de tarjeta de línea en los conmutadores Jupiter: declarar el conmutador fuera de servicio, vaciarlo e iniciar una reparación.

La automatización llevó a cabo lo siguiente:

  1. Se detecta el interruptor averiado y se añade un síntoma a la base de datos.

  2. El servicio de reparación detecta el problema y activa la reparación del interruptor: drena todo el interruptor y añade un motivo de drenaje.
    1. Si se trata del segundo fallo en el plazo de seis meses, siga con el paso 4.
    2. En caso contrario, vaya al paso 3.

  3. Intente (mediante dos métodos distintos) apagar el conmutador.
    1. Si el apagado y encendido se realiza correctamente, ejecute la verificación automática y, a continuación, instale y configure el conmutador. Elimine el motivo de reparación, borre el problema de la base de datos y desinstale el conmutador.
    2. Si fallan las operaciones de comprobación anteriores, envíe el caso a un técnico con un mensaje de instrucciones.
  4. Si se trata del segundo fallo, envíe el caso directamente al técnico, solicitando un nuevo hardware. Después de que se produzca el cambio de hardware, ejecute la verificación automatizada y, a continuación, instale y configure el conmutador. Elimine el motivo de reparación, borre el problema de la base de datos y desinstale el conmutador.

Esta nueva gestión del flujo de trabajo fue una reescritura completa del anterior sistema de reparaciones. Una vez más, aprovechamos las herramientas existentes siempre que fue posible:

  Las operaciones para configurar nuevos conmutadores (instalar y verificar) eran las mismas que necesitábamos para verificar un conmutador que había sido sustituido.
  El despliegue rápido de nuevos tejidos requería la capacidad de BERT((Prueba de tasa de error de bits: comprueba si hay enlaces no seguros antes de restablecer el servicio.)) y cable-audit((Compruebe si hay puertos mal habilitados.)) mediante programación. Antes de restablecer el tráfico, reutilizamos esa capacidad para ejecutar automáticamente patrones de prueba en los enlaces que se habían reparado. Estas pruebas mejoraron aún más el rendimiento al identificar los enlaces defectuosos.

La siguiente mejora lógica era automatizar la mitigación y reparación de errores de memoria en las tarjetas de línea de conmutación Jupiter. Como se muestra en la Figura 6-6, antes de la automatización, este flujo de trabajo dependía en gran medida de un ingeniero para determinar si el fallo estaba relacionado con el hardware o con el software y, a continuación, vaciar y reiniciar el conmutador u organizar una reparación si procedía.

Figura 6-6. Flujo de trabajo de reparación de errores de memoria de Jupiter antes de la automatización

Nuestra automatización simplificó el flujo de trabajo de reparación al dejar de intentar solucionar los errores de memoria (véase “A veces una automatización imperfecta es suficientemente buena” para saber por qué esto tenía sentido). En su lugar, tratamos los errores de memoria de la misma forma que tratamos los fallos de las tarjetas de línea. Para extender la automatización a los errores de memoria, simplemente tuvimos que añadir otro síntoma a un archivo de configuración para que actuara sobre el nuevo tipo de problema. La Figura 6-7 muestra el flujo de trabajo automatizado para los errores de memoria.

Figura 6-7. Flujo de trabajo de reparación de errores de memoria Jupiter con automatización

Lecciones aprendidas

Durante los varios años que trabajamos para automatizar la reparación de redes, aprendimos muchas lecciones generales sobre cómo reducir eficazmente el trabajo pesado.

Las interfaces de usuario no deben introducir sobrecarga ni complejidad.

En el caso de las tarjetas de línea basadas en Saturn, la sustitución de una tarjeta de línea requería vaciar todo el conmutador. Drenar todo el conmutador al principio del proceso de reparación significaba perder la capacidad de trabajo de todas las tarjetas de línea del conmutador mientras se esperaba a las piezas de repuesto y al técnico. Introdujimos un botón en la interfaz de usuario llamado “Componente de preparación” que permitía al técnico vaciar el tráfico de todo el conmutador justo antes de que estuviera listo para sustituir la tarjeta, eliminando así el tiempo de inactividad innecesario para el resto del conmutador (véase “Pulse el botón de preparación para vaciar el conmutador” en la Figura 6-5).

Este aspecto de la interfaz de usuario y del flujo de trabajo de reparación introdujo una serie de problemas inesperados:

  • Después de pulsar el botón, el técnico no recibía información sobre el progreso de la reparación, sino que simplemente tenía que esperar a que le dieran permiso para continuar.
  • El botón no se sincronizaba de forma fiable con el estado real del interruptor. Como resultado, a veces un interruptor vaciado no se reparaba, o un técnico interrumpía el tráfico al actuar sobre un interruptor no vaciado.
  • Los componentes que no tenían activada la automatización devolvían un mensaje genérico de “póngase en contacto con ingeniería” cuando surgía un problema. Los técnicos más recientes no sabían cuál era la mejor manera de ponerse en contacto con alguien que pudiera ayudarles. Los ingenieros con los que se contactaba no siempre estaban disponibles de inmediato.

En respuesta a los informes de los usuarios y a los problemas de regresión causados por la complejidad de la función, diseñamos futuros flujos de trabajo para garantizar que el interruptor fuera seguro y estuviera listo para su reparación antes de que el técnico llegara al interruptor.

No confíe en la experiencia humana

Nos apoyábamos demasiado en técnicos con experiencia en centros de datos para identificar errores en nuestro sistema (por ejemplo, cuando el software indicaba que era seguro proceder con las reparaciones, pero en realidad el conmutador estaba sin vaciar). Además, estos técnicos tenían que realizar varias tareas manualmente, sin que la automatización se lo pidiera.

La experiencia es difícil de reproducir. En un episodio especialmente impactante, un técnico decidió acelerar la experiencia de “pulsar el botón y esperar resultados” iniciando drenajes simultáneos en todas las tarjetas de línea que esperaban reparaciones en el centro de datos, lo que provocó una congestión de la red y una pérdida de paquetes visible para el usuario. Nuestro software no previó ni evitó esta acción porque no probamos la automatización con técnicos nuevos.

Diseñar componentes reutilizables

Siempre que sea posible, evite los diseños monolíticos. Construya flujos de trabajo de automatización complejos a partir de componentes separables, cada uno de los cuales gestione una tarea distinta y bien definida. Podíamos reutilizar o adaptar fácilmente los componentes clave de nuestra primera automatización de Jupiter para cada generación sucesiva de tejidos, y era más fácil añadir nuevas funciones cuando podíamos basarnos en la automatización que ya existía. Las sucesivas variaciones de los tejidos tipo Júpiter podían aprovechar el trabajo realizado en iteraciones anteriores.

No pienses demasiado en el problema

Analizamos en exceso el problema de los errores de memoria de las tarjetas de línea Jupiter. En nuestros intentos de realizar un diagnóstico preciso, tratamos de distinguir los errores de software (solucionables mediante reinicios) de los errores de hardware (que requerían la sustitución de la tarjeta), y también de identificar los errores que afectaban al tráfico frente a los errores que no lo hacían. Pasamos casi tres años (2012-2015) recopilando datos sobre más de 650 problemas discretos de errores de memoria antes de darnos cuenta de que este ejercicio era probablemente exagerado, o al menos no debería bloquear nuestro proyecto de automatización de reparaciones.

Una vez que decidimos actuar ante cualquier error que detectáramos, fue sencillo utilizar nuestra automatización de reparaciones existente para aplicar una sencilla política de vaciado, reinicio y reinstalación de interruptores en respuesta a los errores de memoria. Si el problema se repetía, llegábamos a la conclusión de que el fallo se debía probablemente al hardware y solicitábamos la sustitución de los componentes. Recopilamos datos a lo largo de un trimestre y descubrimos que la mayoría de los errores eran transitorios: la mayoría de los conmutadores se recuperaban tras ser reiniciados y reinstalados. No necesitábamos datos adicionales para realizar la reparación, por lo que el retraso de tres años en la implantación de la automatización era innecesario.

A veces basta con una automatización imperfecta

Aunque la posibilidad de verificar enlaces con BERT antes de deshacerlos resultaba práctica, las herramientas BERT no admitían enlaces de gestión de red. Añadimos estos enlaces a la automatización de reparación de enlaces existente con una comprobación que les permitía saltarse la verificación. Nos sentíamos cómodos omitiendo la verificación porque los enlaces no transportaban tráfico de clientes, y podíamos añadir esta funcionalidad más adelante si la verificación resultaba ser importante.

Reparar la automatización no es disparar y olvidar

La automatización puede tener una vida muy larga, así que asegúrese de planificar la continuidad del proyecto a medida que la gente se va y se une al equipo. Los nuevos ingenieros deben recibir formación sobre los sistemas heredados para que puedan corregir errores. Debido a la escasez de piezas para los tejidos de Júpiter, los tejidos basados en Saturn perduraron mucho después de la fecha prevista originalmente para el final de su vida útil, lo que nos obligó a introducir algunas mejoras bastante tarde en la vida útil total de Saturn.

Una vez adoptada, la automatización puede afianzarse durante mucho tiempo, con consecuencias positivas y negativas. Cuando sea posible, diseñe su automatización para que evolucione de forma flexible. Confiar en una automatización inflexible hace que los sistemas sean frágiles al cambio. La automatización basada en políticas puede ayudar al separar claramente la intención de un motor de implementación genérico, lo que permite que la automatización evolucione de forma más transparente.

Incorporar la evaluación de riesgos y la defensa en profundidad

Tras crear nuevas herramientas para Jupiter que determinaban el riesgo de una operación de drenaje antes de ejecutarla, la complejidad que encontramos nos llevó a introducir una comprobación secundaria para la defensa en profundidad. La segunda comprobación establecía un límite superior para el número de enlaces impactados, y otro límite para los dispositivos impactados. Si superábamos cualquiera de los dos umbrales, se abría automáticamente un error de rastreo para solicitar más investigación. Con el tiempo fuimos ajustando estos límites para reducir los falsos positivos. Aunque en un principio consideramos que se trataba de una medida temporal hasta que se estabilizara la evaluación de riesgos primaria, la comprobación secundaria ha resultado útil para identificar índices de reparación atípicos debidos a cortes de suministro eléctrico y errores de software (para ver un ejemplo, consulte “Automatización: Enabling Failure at Scale” en Site Reliability Engineering).

Obtenga un presupuesto de fallos y el apoyo del gestor

La automatización de las reparaciones puede fallar a veces, sobre todo cuando se introduce por primera vez. El apoyo de la dirección es crucial para preservar el proyecto y animar al equipo a perseverar. Le recomendamos que establezca un presupuesto de errores para la automatización contra los fallos. También debe explicar a las partes interesadas externas que la automatización es esencial a pesar del riesgo de fallos, y que permite mejorar continuamente la fiabilidad y la eficacia.

Pensar de forma holística

En última instancia, la complejidad de los escenarios que hay que automatizar es el verdadero obstáculo que hay que superar. Reexamine el sistema antes de trabajar en su automatización: ¿puede simplificar primero el sistema o el flujo de trabajo?

Preste atención a todos los aspectos del flujo de trabajo que está automatizando, no sólo a los que le suponen un trabajo pesado. Realice pruebas con las personas directamente implicadas en el trabajo y busque activamente su opinión y ayuda. Si cometen errores, averigua cómo podría ser más clara tu interfaz de usuario o qué comprobaciones de seguridad adicionales necesitas. Asegúrese de que su automatización no genere nuevo trabajo pesado, por ejemplo, abriendo tickets innecesarios que requieran atención humana. Crear problemas a otros equipos aumentará la resistencia a futuros intentos de automatización.


  • II Prácticas
    • 8. De Guardia
    • 9. Respuesta a Incidentes
    • 10. Cultura Postmortem: Aprender del Fracaso
    • 11. Gestionar la Carga
    • 12. Introducción al Diseño No Abstracto de Grandes Sistemas
    • 13. Proceso de Datos.
    • 14. Diseño de la Configuración y Mejores Prácticas
    • 15. Especificaciones de Configuración
    • 16. Lanzamientos Canary
  • III Procesos
    • 17. Identificar la Sobrecarga y Recuperarse de ella
    • 18. Modelo de Compromiso SRE
    • 19. SRE: Más allá de sus Límites
    • 20. Ciclos de Vida del Equipo SRE
    • 21. Gestión del Cambio Organizativo en la SRE
  • Conclusión
  • A. Ejemplo de Documento SLO
  • B. Ejemplo de Política Presupuestaria de Errores
  • C. Resultados del Análisis Postmortem
2023/11/27 01:26 · Fernando Leal

1)
Que algo sea automatizable es la característica más subjetiva de las enumeradas aquí; su perspectiva evolucionará a medida que adquiera experiencia automatizando tareas pesadas. Un espacio problemático que antes parecía intratable (o demasiado arriesgado) se volverá factible una vez que se sienta cómodo con “dejar que los robots hagan el trabajo”.
2)
A algunos ingenieros no les importa trabajar de forma pesada durante un periodo prolongado, pero el umbral de tolerancia al trabajo pesado no es el mismo para todos. A largo plazo, el trabajo pesado provoca el estancamiento profesional y favorece la rotación de personal por agotamiento. Cierto nivel de trabajo pesado es inevitable, pero recomendamos reducirlo siempre que sea posible, por la salud del equipo, del servicio y de las personas.
3)
En otras palabras, si un servicio y sus nueve dependencias tienen cada uno una disponibilidad del 99.99%, la disponibilidad agregada del servicio será de 0.999910 = 99.9%. Para más información sobre cómo influyen las dependencias en la disponibilidad del servicio, véase “El cálculo de la disponibilidad del servicio”.
4)
En resumen, pasar de dispositivos individuales especializados a una flota de dispositivos con una interfaz común. Véase “Caso de estudio 1: Reducir el trabajo pesado en el centro de datos con la automatización” para una explicación detallada de esta analogía.
5)
Una tarjeta de línea es un componente modular que suele proporcionar múltiples interfaces a la red. Se aloja en el backplane de un chasis junto con otras tarjetas de línea y componentes. Los conmutadores de red modulares constan de un chasis que incluye una placa base, módulos de entrada de alimentación, un módulo de tarjeta de control y una o varias tarjetas de línea. Cada tarjeta de línea admite conexiones de red a máquinas o a otras tarjetas de línea (en otros conmutadores). Al igual que con un adaptador de interfaz de red USB, puede sustituir cualquier tarjeta de línea sin apagar todo el conmutador, siempre que la tarjeta de línea se haya “vaciado”, es decir, que se haya ordenado a las demás interfaces que dejen de enviarle tráfico.