Rotación de guardia para operaciones y soporte una necesidad para los equipos de datos.

Guard rotation is necessary for data teams' operations and support.

Un cronograma de turnos rotativos para el soporte operativo, tecnológico y departamentos afines libera al resto del equipo para realizar un gran desarrollo

Un desafío común para todos los equipos de ciencia de datos o de productos es alinear las tareas nuevas (desarrollo de productos) con las tareas antiguas (operativas, de soporte). Cuando se espera que el equipo completo maneje ambas, significa que, por un lado, se requiere que el equipo cumpla con una fecha límite del producto y lance una nueva característica del producto, mientras que, al mismo tiempo, se espera que el equipo trabaje operativamente, solucionando los problemas que existen y respondiendo preguntas y llamadas comerciales. Esta situación provoca cambios de contexto inesperados y, eventualmente, conduce a una menor eficiencia, incumplimiento de plazos y estrés.

En la práctica, esto a menudo lleva a una situación en la que ciertos miembros del equipo asumen esas tareas adicionales o están especializados para hacerlo. Pero eso es peligroso porque tan pronto como uno de estos miembros especializados del equipo se va de vacaciones, toda la empresa podría sentirlo y tener un problema.

Por lo tanto, un equipo de datos eficiente y escalable necesita apoyar tanto el trabajo operativo como el desarrollo de nuevos productos y crear un sistema que incluya:

  • Buena compartición de conocimientos entre los miembros del equipo sobre cómo hacer el trabajo operativo y de soporte de los productos/clientes
  • Trabajo de desarrollo ininterrumpido sin mucho cambio de contexto
  • Trabajo de mantenimiento bien definido y estimado para evitar plazos inesperados

El sistema de turnos rotativos

Un sistema que resultó funcionar muy bien para nosotros en el pasado es un sistema de turnos rotativos que maneja más que solo “alertas” en producción. En pocas palabras, este es un sistema rotativo donde uno (o más) miembros del equipo son los sobrevivientes designados por un tiempo específico y son puramente responsables del trabajo operativo.

La persona de guardia no solo está haciendo un trabajo, está protegiendo a todo el equipo de todo el caos que sucede fuera del trabajo de desarrollo

Para terminar ese punto, este sistema permite que solo la persona de guardia (el sobreviviente designado) maneje todo el trabajo que no cae bajo “nuevo desarrollo”. Durante ese tiempo, la persona de guardia no solo está haciendo un trabajo, está protegiendo a todo el equipo de todo el caos que sucede fuera del trabajo de desarrollo, incluyendo:

  • Corregir problemas en el canal de producción
  • Responder preguntas comerciales/clientes
  • Soportar llamadas de clientes
  • Reducir el departamento tecnológico (backlog)
Resumen de tareas específicas que forman parte de la rutina de guardia.

Como se puede ver en la figura anterior, manejar el sistema de guardia “clásico” y asegurarse de que el entorno de producción funciona es lo más importante. Sin embargo, si no hay problemas en la producción, esto libera para otras tareas como apoyar solicitudes comerciales, llamadas de clientes o reducir el backlog.

¿Cuáles son los beneficios?

Cambiar al sistema al principio puede no ser fácil. No todos los miembros del equipo pueden simplemente asumir la responsabilidad del canal de producción, el soporte comercial y el departamento tecnológico. Pero eso no debería ser un obstáculo. Es importante comunicar correctamente que la persona de guardia es dueña de esos elementos y es la primera línea de defensa, pero puede pedir ayuda en cualquier momento.

A largo plazo, esto traerá muchos beneficios al equipo y a toda la organización. Los beneficios más intuitivos son que es mucho más fácil estimar el trabajo de desarrollo y que el equipo se volverá más eficiente (menos cambio de contexto). Esto también se aplica al lado operativo, donde el número de personas que forman parte del sistema de guardia define cuánto trabajo operativo es posible. Esto hace que la comunicación con la empresa y las partes interesadas sea mucho más fácil porque un equipo de 5 personas con 1 persona en la rotación significa que 1 de cada 5 ETP está manteniendo todos los sistemas y trabajando en los productos existentes (20% operativo, 80% desarrollo). Eso es fácil de contabilizar y estimar.

Esquema de una distribución operativo-desarrollo del 20%-80% en un equipo que usa rotación de guardia.

Sin embargo, hay más beneficios que vienen con el tiempo, casi como efectos secundarios. Todos los miembros del equipo se convertirán en científicos de datos de pila completa. La razón es que cada miembro del equipo necesita entender un mínimo de los productos, clientes, sistemas, modelos/lógica e infraestructura de código involucrados. No necesitan ser expertos, pero eventualmente serán lo suficientemente buenos como para manejarlos solos durante al menos 1 semana. Esto también asegurará que no sea un problema cuando un valioso miembro del equipo se vaya de vacaciones, ya que la persona de guardia siempre tendrá la espalda del equipo.

Además, aunque este tiempo de guardia a veces puede ser un poco más estresante, le da al científico de datos la oportunidad de ver lo que está fuera del equipo y colaborar con el lado comercial y los clientes. Esta puede ser una experiencia muy valiosa y gratificante.

¿Cómo configurar un sistema así?

Aquí es donde se vuelve un poco técnico (para las personas a las que les gusta el código, simplemente desplácese hasta el final). Configurar un sistema así es bastante sencillo, pero puede implicar algo de codificación. La parte más importante es la comunicación con el equipo y las partes interesadas e informarles cómo va a funcionar esto.

Dado que todo el punto del sistema es apoyar al equipo, y no crear más sobrecarga, recomiendo encarecidamente automatizarlo completamente. Para hacerlo, necesitaría tener al menos 3 sistemas en su lugar:

  • Un sistema de paginación conectado a producción que alerta cuando falla la producción (por ejemplo, Opsgenie o Pagerduty)
  • Un sistema de programación que detecta quién está de guardia y puede comunicarlo a otro sistema (por ejemplo, Apache Airflow o Keboola)
  • Una plataforma de comunicación que se utiliza para comunicarse con su equipo y hacer tickets (por ejemplo, Slack o Teams)

Si tiene esos sistemas en su lugar y tiene acceso a la API del sistema de paginación y a la plataforma de comunicación, entonces casi ha terminado. Lo único que queda por hacer es configurar un trabajo en el sistema de programación que ejecute una llamada API primero para obtener quién está de guardia del sistema de paginación y un push de API después para comunicar o sobrescribir canales/grupos/etiquetas en la plataforma de comunicación.

A continuación se muestra un ejemplo de cómo puede verse una llamada API tan simple que le proporcionará la persona de guardia de Opsgenie:

curl -X GET \'https://api.opsgenie.com/v2/schedules/{schedule_name}/on-calls?scheduleIdentifierType=name&flat=true' \--header 'Authorization: GenieKey {token}'

Después de eso, querrá ejecutar un comando que haga algo en su sistema de comunicación. Por ejemplo, en Slack, sobrescribir un grupo de usuarios para que solo contenga al usuario que está de guardia:

curl -X POST \-F usergroup={usergroup} \-F users={user} \'https://slack.com/api/usergroups.users.update' \-H 'Authorization: Bearer {token}'

Al final de esta historia, encontrará una versión de código completo de cómo se puede programar automáticamente este código. Esto asegurará que cada vez que alguien etiquete a su grupo en Slack (como @team), solo se etiquete a la persona de guardia y puede decidir si es necesario notificar a más miembros del equipo. También le permite agregar rápidamente nuevas tareas a la dag. Por ejemplo, cuando desee notificar a la empresa o al equipo quién está de guardia ahora o si desea ajustar su sistema de tickets en consecuencia.

Resumen

Tener un horario rotativo para el trabajo operativo, comercial y de departamento técnico del equipo está haciendo que su equipo de datos sea más eficiente. Reducirá el cambio de contexto y permitirá una mejor estimación del tiempo. Además, educará a los científicos de datos de pila completa que están seguros de manejar una amplia gama de problemas para proteger al resto del equipo.

Todas las imágenes, a menos que se indique lo contrario, son del autor.

Apéndice de código:

Ejemplo de una dag de Airflow que obtiene a la persona que está de guardia de Opsgenie y sobrescribe un grupo de usuarios en Slack para contener solo a esa persona. La codificación ciertamente no es perfecta (científico de datos en acción), pero estoy seguro de que lo entenderá:

# Importfrom airflow import DAG, XComArgfrom typing import Dict, Listfrom airflow.operators.bash import BashOperatorfrom airflow.operators.python import PythonOperatorfrom airflow.models import Variableimport json# Fetch secret tokensslack_token = Variable.get("slack_token")opsgenie_token = Variable.get("opsgenie_token")# Setup DAGdag = DAG(    dag_id,    schedule_interval=schedule_interval,    default_args=default_args,    catchup=catchup,    max_active_runs=max_active_runs,)with dag:        # Run BashOperator fetching from Opsgenie who is on call    def fetch_who_is_on_call(**kwargs):        fetch_who_is_on_call_bash = BashOperator(            task_id="fetch_who_is_on_call_bash",            bash_command="""            curl -X GET \            'https://api.opsgenie.com/v2/schedules/{schedule_name}/on-calls?scheduleIdentifierType=name&flat=true' \             --header 'Authorization: GenieKey {token}'            """.format(                schedule_name="schedule_name",                 token=opsgenie_token             ),            dag=dag,        )        return_value = fetch_who_is_on_call_bash.execute(context=kwargs)        fetch_who_is_on_call_bash        return return_value    # run BashOperator in PythonOperator and provide context    opsgenie_pull = PythonOperator(        task_id="opsgenie_pull",        python_callable=fetch_who_is_on_call,        provide_context=True,        dag=dag,    )        # Overwrite slack group with the person on call    def overwrite_slack_group(**kwargs):                # First: get who is on call from PythonOperator        ti = kwargs.get("ti")        xcom_return = json.loads(ti.xcom_pull(task_ids="opsgenie_pull"))        user_email = xcom_return["data"]["onCallRecipients"][0]        user_dict = {            "data_scientist_a": "A03BU00KGK4",            "data_scientist_b": "B03BU00KGK4",        }        user_id = [            user_dict[k] for k in user_dict.keys() if k == user_email.split(".")[0]        ]                # Second: Run BashOperator to overwrite slack group        overwrite_slack_group_bash = BashOperator(            task_id="overwrite_slack_group_bash",            bash_command="""            curl -X POST \            -F usergroup={usergroup} \            -F users={user} \            https://slack.com/api/usergroups.users.update \            -H 'Authorization: Bearer {token}'            """.format(                usergroup="usergroup_id",                user=user_id,                token=slack_token,            ),            dag=dag,        )        overwrite_slack_group_bash.execute(context=kwargs)        overwrite_slack_group_bash    # Run BashOperator for slack overwrite in PythonOperator    overwrite_slack = PythonOperator(        task_id="overwrite_slack",        python_callable=overwrite_slack_group,        provide_context=True,        dag=dag,    )    opsgenie_pull >> overwrite_slack    return dag