La historia personal sobre el inicio de la organización SRE en Uber.

LEE EL ARTÍCULO COMPLETO

A continuación te queda la traducción a sucio del artículo:

Esta es mi historia personal sobre el inicio de la organización SRE en Uber. Si desea consejos en lugar de reminiscencias, eche un vistazo a Trunk and Branches Model and Productivity in the age of hypergrowth .

Después de dejar SocialCode en 2014, pasé un mes entrevistando a un puñado de empresas tratando de averiguar qué hacer a continuación. Estaba dividido entre dos caminos diferentes: (1) liderar la ingeniería en una startup muy pequeña, o (2) asumir un papel mucho más pequeño en una empresa de rápido crecimiento, con la expectativa de que el crecimiento generaría oportunidades. Después de considerarlo un poco, tomé el último camino y me uní a Uber.

Olvidé el cronograma exacto de mi entrevista en Uber, pero fue en la línea de “entrevista el martes, oferta el miércoles y comienzo el lunes siguiente”. (¡Este no fue el cambio más rápido que vi en Uber! Una vez di un ofrecí a alguien un viernes alrededor de las 5:00 p. m., quien notificó de inmediato y comenzó dos días después, el lunes). seguro de lo que significaba DevOps.Esperando durante el fin de semana para comenzar, leí ansiosamente The Phoenix Project en un intento de aplicar ingeniería inversa a lo que acababa de ser contratado para hacer.

Había cinco equipos haciendo lo que podría describirse clásicamente como “infraestructura” cuando comencé. Los equipos de ingeniería de datos y mapas también se agruparon en la organización de infraestructura, pero estaban bastante concentrados en otro trabajo, por lo que los voy a eludir por una cuestión de conveniencia narrativa. Los equipos de infraestructura eran (1) herramientas de desarrollo, (2) láser de ingeniería de infraestructura enfocado en superar el apetito de los índices de PostgreSQL por espacio en disco, (3) un equipo en Dinamarca enfocado principalmente en herramientas de implementación, (4) TechOps que era responsable de ordenar y instalar servidores y equipos de red, y (5) el equipo de InfraOps que hizo todo lo demás. Combinados, estos equipos eran unas veinte personas dentro de una organización de ingeniería de doscientos ingenieros (cuya plantilla se duplicaba cada seis meses).

Me uní al último equipo de esa lista, InfraOps. Éramos cinco personas y responsables de mantener la mayoría de los servidores de la empresa (Uber no usaba ningún proveedor de nube en ese momento), la infraestructura de enrutamiento de solicitudes (principalmente HAProxy), Kafka, la mayoría de las bases de datos, el aprovisionamiento de servicios (en el “servicio orientado a “arquitectura” en el sentido de la palabra), algunas cosas de seguridad (solo había un ingeniero de seguridad dedicado en ese momento, Alex, que se había unido unas semanas antes que yo), títere, Clusto y los diversos nudos de software que cayeron entre los cojines organizativos.

Cuando comencé, hice un balance de los desafíos del equipo y los reduje a un puñado de áreas en las que concentrarse con urgencia: mantener el sitio en funcionamiento (las cosas solían salir mal la mayoría de los viernes por la tarde debido a la aceleración de la carga, y se sabía que los teléfonos de la gente funcionaban sin energía durante su turno de guardia de 12 horas debido a repetidos pings de Pagerduty), escalando Kafka, preparándonos para migrar fuera de nuestro primer centro de datos antes del pico de tráfico de Halloween de Uber (decidimos no comprar ninguna capacidad adicional en nuestro centro de datos actual , por lo que este era un plazo difícil) y respaldar las solicitudes entrantes para proporcionar servicios. En mi segunda y tercera semana, escribí una estrategia para cada uno, y por un momento sentí que teníamos un camino claro a seguir.

Esos planes eran, a lo mejor de mi memoria extremadamente objetiva y de ninguna manera egoísta, los planes más excelentes. Planes tan buenos, que mi gerente me confió más tarde que al principio le preocupaba que yo entrara y solucionara de inmediato los problemas con los que había estado luchando. Por supuesto, pronto quedaría claro que esos excelentes planes funcionaban mejor sobre el papel.

Nuestro primer paso fue configurar un libro de recetas de servicios : un archivo YAML que describía el trabajo que hicimos para otros equipos, y una aplicación Python Flask que compiló ese archivo en una interfaz de usuario que automatizó esas solicitudes cuando fue posible y generó tickets bien estructurados que incluían lo necesario. información para completar la tarea. Nuestro sistema de tickets en ese momento, Phabricator, no admitía agregar campos obligatorios para diferentes tipos de solicitudes, por lo que el libro de recetas del servicio proporcionó mucho valor simplemente asegurando que se incluyera la información correcta con cada solicitud. Aún más importante, el libro de recetas del servicio nos dio algo que nos faltaba: datos sobre las solicitudes entrantes.

A medida que se acumularon los datos de uso, pronto se hizo evidente que estábamos dedicando la mayor parte de nuestro tiempo a responder a incendios de producción críticos, algo que no podíamos ignorar, oa proporcionar nuevos servicios.

Provisión de servicios

Trabajar en el monolito de Uber se había vuelto difícil: las migraciones eran riesgosas, las implementaciones eran lentas, la depuración de incidentes era un desafío porque cada implementación incluía compromisos de muchos equipos, etc. Se había tomado la decisión de desaprobar el monolito, y los equipos huían tan rápido como podían hacia nuevos servicios.

El aprovisionamiento de servicios fue un proceso desordenado, que siguió a un libro de ejecución largo y requirió la implementación secuencial de actualizaciones de marionetas en al menos tres niveles diferentes de hosts, además de manipular una serie de partes propensas a errores en Clusto (similar a Cónsul de Hashicorp pero anterior a él por algunos años; gran parte de la pila de tecnología de infraestructura inicial de Uber fue transferida desde Digg por uno de los primeros ingenieros, Jeremy). Después de esos pasos, inevitablemente comenzaría a depurar lo que usted o el equipo que solicitó el nuevo servicio hicieron mal. En total, podría pasar fácilmente medio día aprovisionando un nuevo servicio y luego otra semana yendo y viniendo con el equipo propietario del servicio para que las piezas finales funcionen correctamente.

Cada semana nos retrasábamos un poco más en nuestro atraso en el aprovisionamiento de servicios, y no podíamos agregar más personas a los esfuerzos de aprovisionamiento sin sacarlos de nuestras otras iniciativas urgentes. Así que nos enfocamos en nuestra mejor herramienta restante, la automatización.

No teníamos mucha gente para dedicarnos al aprovisionamiento de servicios, por lo que inicialmente solo yo lo hacía a tiempo parcial y un ingeniero que se unió el mismo día que yo, Xiaojian. Eso no fue suficiente, así que pronto contratamos a un segundo ingeniero para que trabajara en esto a tiempo completo, Woody. Woody dedicó tanto tiempo al aprovisionamiento de servicios que una vez alguien se confundió al saber que Woody era una persona y no un bot de Hipchat.

Nuestro libro de recetas de servicio nos brindó una interfaz para interceptar las solicitudes de aprovisionamiento de servicios entrantes, y seguimos ampliando las herramientas hasta que la gente pudo aprovisionar por completo sin ningún apoyo del equipo. ¡Algunos de los pasos intermedios fueron bastante incómodos! En particular, recuerdo una etapa en la que generamos automáticamente la configuración de Puppet para cada nuevo servicio, pero aún necesitábamos que el ingeniero solicitante fusionara el cambio en sí mismo. La gente estaba bastante confundida de que la solicitud de un nuevo servicio terminara con ellos pegando los cambios en nuestro repositorio de Puppet y esperando que no se rompiera nada.

Otro sub-desafío interesante fue el descubrimiento y enrutamiento de servicios. Hicimos descubrimiento de servicios a través de HAProxy, donde enrutaría a un servicio dentro de su entorno actual conectándose en localhost al puerto asignado estáticamente del servicio, que HAProxy luego enrutaría a una instancia que se ejecuta en algún lugar de ese entorno. HAProxy se configuró en cada servidor individualmente cuando se ejecutó Puppet, generalmente una vez cada hora en cada servidor. (Las ejecuciones de títeres por hora se extendieron durante veinte minutos, por lo que tenía unos cinco minutos entre un cambio de títeres no válido que comenzaba a propagarse y toda la flota colapsaba. Nos volvimos buenos para pausar los lanzamientos bajo presión, pero también colapsamos muchas cosas). Para aprovisionar un nuevo servicio, necesitaba reservar un puerto único a nivel mundial. Si reutilizara un puerto, inevitablemente provocaría una interrupción. Los puertos se registraron inicialmente en una página wiki en algún lugar, aunque muchos no se registraron en ninguna parte. Para automatizar este paso del aprovisionamiento de servicios, pasamos de la asignación manual a la asignación automatizada (y luego nos alejamos de los horrores de la asignación de puertos estáticos). Es un buen ejemplo de las muchas opciones iniciales que tuvimos que deshacer con urgencia para automatizar todo el proceso.

Estos problemas no fueron de ninguna manera la consecuencia de “malas elecciones” en la configuración de la infraestructura original. En cambio, como la mayoría de las decisiones técnicas, los enfoques simplemente no sobrevivieron intactos a través de varios órdenes de magnitud de crecimiento. Muchos de los desafíos que enfrentamos son casi desconocidos hoy en día, pero la mayoría de las herramientas que abordan estos problemas hoy en día simplemente no existían como opciones comprobadas cuando se configuró la infraestructura de Uber por primera vez. (Como ejemplo posterior, Uber luego terminaría ejecutando Mesos en lugar de Kubernetes, ya que Kubernetes en ese momento era un proyecto inicial sin mucho uso en la carga).

A medida que resolvimos cada uno de estos problemas, el aprovisionamiento de servicios se volvió más rápido y menos propenso a errores. En 18 meses escalamos de 15 servicios a más de 2000, con cada uno de esos servicios provistos por este equipo o la plataforma que construyeron. Como el equipo alcanzó su punto máximo con aproximadamente cuatro personas trabajando en este problema en particular, la gran mayoría se hizo a través de la plataforma. Lejos del trabajo inicial de una semana entre equipos cruzados, el aprovisionamiento de servicios se volvió lo suficientemente fácil como para que, en un momento dado, cada ingeniero incorporado aprovisionara un nuevo servicio en su primer día.

Número de empleados

Además de nuestro trabajo en automatización, aumentamos la contratación. El primer desafío que encontré fue que el equipo rechazó a todos los candidatos . En mi entrevista con el gerente, terminé haciendo el problema del vendedor ambulante en Python en una pizarra, y eso fue básicamente parte del proceso de la entrevista. No había preguntas estandarizadas, ni rúbricas para evaluar a los candidatos, y la estructura general variaba para cada gerente de contratación.

Hoy, comenzaría implementando esas prácticas comunes, pero en ese momento de mi carrera, nunca había visto ni oído hablar de esas mejores prácticas. Entonces, en lugar de eso, me sentaría con mi socio de reclutamiento y depuraría por qué cada bucle no pudo generar una oferta. Para los candidatos que pensé que podrían ayudarnos a sobrevivir la avalancha de trabajo entrante, discutiría con el equipo sobre por qué necesitábamos contratarlos. Eventualmente se molestaron por tener la misma discusión conmigo y comenzaron a estar de acuerdo con contratar a algunos de los candidatos.

Como alguien que había contratado a unos seis ingenieros antes de unirse a Uber, este fue un verdadero bautismo de fuego. En mi primer año en Uber, cada semana solía hacer diez pantallas telefónicas junto con cuatro o cinco entrevistas. Puedo recordar vívidamente estar en estas salas de vidrio después de hacer tres pantallas telefónicas consecutivas un día y luchar por distinguir entre los candidatos en mis notas. Hicimos tantas entrevistas que desarrollamos un proceso de rotación proactiva de los buenos entrevistadores cuando empezaban a agotarse.

También tuvimos experiencias de contratación divertidas y horribles como resultado de la poca supervisión o estandarización. Rechazamos a un candidato, cuyo referente nos convenció de entrevistarlo nuevamente seis meses después, donde lo rechazamos de inmediato. Sin desanimarse, otro equipo insistió en entrevistar al candidato por tercera vez. Me acerqué al gerente de ese equipo para disuadirlos, pero insistieron y me extendieron una oferta. El candidato aceptó, comenzó en Uber, luego, unas horas después de su primer día, aceptó una segunda oferta en Twitter (convenientemente, a una cuadra de distancia). Al final, se entrevistaron más veces en Uber que las horas que pasaron trabajando allí.

Contratar a este ritmo, junto con frecuentes despidos de producción y un flujo frecuente de equipos de socios frustrados fue sin duda lo más difícil en lo que he trabajado. Todo estaba consumiendo. En el lado positivo, funcionó. Contratamos a bastantes personas, y en un año habíamos crecido de cinco a unas cuarenta personas impulsadas completamente por la contratación externa.

Fundación de la SRE

A medida que nuestro equipo crecía y nuestra automatización mejoraba, nuestro plan indicaba que las circunstancias mejorarían. Pero no lo hicieron. Permanecimos profundamente bajo el agua. Nuestro enfoque estaba funcionando, pero no lo suficientemente rápido. La organización de ingeniería se duplicaba a nuestro alrededor cada seis meses, y cada pocos meses traía un proyecto nuevo y urgente a la escala de, por ejemplo, el aprovisionamiento de dos nuevos centros de datos en China.

¿Qué más podríamos hacer para salir de debajo de esta carga de trabajo? Si aumentar la capacidad humana y de software no fuera suficiente, entonces la única opción que podríamos encontrar era hacer menos trabajo. ¡Tan obvio! Cualquier enfoque para hacer menos tenía que satisfacer dos requisitos específicos. En primer lugar, necesitábamos conservar nuestra capacidad para atender los problemas de producción impredecibles pero inevitables que surgen al duplicar la carga cada seis meses. En segundo lugar, teníamos que brindar apoyo suficiente a otros equipos de ingeniería para que pudieran avanzar en sus objetivos críticos e independientes.

Existe una creencia memética de que la solución para hacer menos es simplemente obligar a su gerente a priorizar su carga de trabajo, pero solo he visto que esta estrategia funciona en organizaciones de arriba hacia abajo. También es una forma segura de degradarse de líder a gerente. Es cierto que estaba demasiado obsesionado con que nuestro equipo superara este desafío por nosotros mismos como para pensar en pedir ayuda. Finalmente, se nos ocurrió otro enfoque: ¿podríamos resolver estas limitaciones cambiando la forma de nuestra organización?

Fue esa pregunta la que provocó la creación de la organización SRE de Uber.

Teníamos el personal para escalar nuestra infraestructura si pudiéramos protegerlos de las solicitudes de trabajo entrantes, por lo que nos enfocamos en cómo proteger a esos equipos de las interrupciones y, al mismo tiempo, brindamos a los equipos solicitantes suficiente apoyo para avanzar. La estructura fue efectivamente:

  1. Nuestros tres o cuatro principales socios organizacionales recibirían apoyo exclusivo de SRE. Los equipos asociados priorizarían explícitamente la carga de trabajo de los SRE que los respaldan. Definimos “superior” por número de solicitudes, no por impacto
  2. Todos los demás recibirían apoyo del equipo que construye la plataforma de autoservicio. Priorizarían el trabajo según el principio de acelerar la automatización
  3. El resto de la infraestructura admitiría áreas específicas de escalabilidad y operación, por ejemplo, redes, Kafka. En su mayoría priorizarían la escalabilidad, la usabilidad y la eficiencia.

Cuando comenzamos a implementar esto, tuvimos un problema típico de Uber: no teníamos a nadie para el equipo de SRE. Sin embargo, no pasó mucho tiempo hasta que contratamos al primer SRE de Uber, Rick , el primer gerente de SRE de Uber, Eamon, y la contratación aumentó a partir de ahí.

Mi discurso de motivación para Rick cuando se unió no fue muy bueno, algo así como: “Eres muy inteligente y experimentado. Debe ayudar a este equipo de socios a realizar su trabajo sin realizar ninguna solicitud al equipo de infraestructura más amplio. No esperes a que te den permiso, solo ve a hacer cosas. ¡Buena suerte!” Todo para el crédito de Rick, de alguna manera esto funcionó.

Poco después, se contrató a otro ingeniero para que se uniera a Rick y trabajara con el mismo equipo asociado. Luego, se contrataron dos ingenieros más para apoyar al siguiente equipo asociado de la lista. Los dos después de eso apoyaron a un tercer equipo, y el plan comenzó a concretarse. Continuamos con este modelo, agregando más SRE para integrarlos directamente en los mejores equipos de socios hasta que nos quedamos sin equipos de socios lo suficientemente grandes para respaldar.

Los equipos de socios, que finalmente tenían la capacidad de alinear las solicitudes de infraestructura con su trabajo, en su mayoría dejaron de escalar. Aunque no les habíamos dado el nivel de soporte que querían, les habíamos dado control explícito y exposición a las compensaciones creadas por las solicitudes de sus equipos, muchas de las cuales desconocían en el modelo anterior.

A medida que nuestra implementación de SRE se estabilizó, sentimos que finalmente habíamos resuelto el problema.

Este modelo SRE no era perfecto. Prosperó con equipos colaborativos de socios y tuvo problemas con otros, pero resolvió el problema para el que fue diseñado: nuestros equipos de socios estaban logrando un progreso predecible y pudimos priorizar simultáneamente el trabajo de escalabilidad. Lo que es más importante, resolvió este problema sin ninguna dirección global de arriba hacia abajo sobre las prioridades, sino que confió en los equipos de socios para resolver localmente sus prioridades.

SRE v2

La organización de infraestructura más amplia de Uber tenía un enfoque orgánico para la resolución de problemas. Era fundamentalmente una organización de abajo hacia arriba que tenía estrategias locales sin una estrategia general común, lo que creó bastantes puntos de fricción. Eventualmente, a medida que crecía, comenzó una búsqueda para el puesto de mi gerente directo y, finalmente, contratamos al próximo jefe de infraestructura de Uber.

El nuevo jefe de infraestructura tenía una forma muy específica de estructurar las organizaciones de arquitectura e infraestructura en base a su experiencia previa. En unas pocas semanas, iniciaron un proyecto para rediseñar la tecnología y la infraestructura de Uber. También tenía una visión específica de cómo debería funcionar SRE y, en un par de meses, contrató a un colega anterior para que asumiera la dirección del equipo de SRE.

Como suele ser el caso después de que un nuevo líder se une para volver a implementar su configuración anterior , se pasó por alto el contexto importante sobre cómo funcionaban las cosas. También hice un mal trabajo al explicar el problema específico que habíamos resuelto con la organización SRE de Uber. Hasta el día de hoy, creo que estos nuevos líderes tenían un malentendido fundamental sobre qué problema estaba resolviendo la organización SRE de Uber (permitiendo una organización de abajo hacia arriba con prioridades muy fluidas que no se resolvieron en una sola lista de prioridades), viéndolo en cambio desde la lente de su experiencia anterior. Como resultado, SRE pasó rápidamente de un modelo integrado a un modelo muy diferente.

El nombre no cambió, pero pronto fue un equipo muy diferente. La continuidad del nombre ocultó el comienzo de un cambio cultural y de liderazgo significativo, que culminaría en Reflexiones sobre un año muy, muy extraño en Uber de Susan Rigetti . Unos meses más tarde, mi quinto jefe en dos años salió y yo lo seguí poco después. (Algo confuso, este jefe en particular no era el nuevo jefe de infraestructura. En cambio, era otro nuevo líder que se unió casi al mismo tiempo que el nuevo jefe de infraestructura y se fue dentro de los seis meses posteriores a su incorporación).

La organización de la SRE se mantuvo. La organización SRE que habíamos construido se había ido.

Reflexión

Al contar historias como esta o el lanzamiento de Digg V4 , siempre hay una tendencia a presentarse de la mejor manera posible, pero trato de contar estas cosas con cierta fidelidad. Es absolutamente cierto que si pudiera rehacer mi tiempo, haría muchas cosas de manera diferente. Dicho esto, Uber fue un papel destacado para mí y no habría tenido éxito en mi trabajo posterior sin todo lo que aprendí primero en Uber. También hay pocas cosas de las que estoy más orgulloso que lo que logramos juntos. A las personas con las que trabajé y de las que aprendí en Uber: gracias, cambiaron mi vida para mejor.

Eso no quiere decir que la experiencia fuera del todo buena. Trabajar en esa era de Uber extraía un peaje. Muchos otros pagaron un precio mucho peor; Yo también pagué uno. Estaba muy por encima de mi cabeza como líder, y luché con eso. En un viaje de trabajo para ampliar la oficina de Uber en Lituania, mi pareja de siete años me llamó para decirme que se habían mudado. Escribir había sido mi pasatiempo favorito, pero dejé de escribir durante el tiempo que estuve allí. Algunos capítulos nos enriquecen la vida sin ser algo que repetiríamos, y Uber es sin duda uno de esos capítulos para mí.