Press "Enter" to skip to content

运营和支持的轮值值班:数据团队必不可少

轮流值班的系统运维、支持和技术部门,释放了其余团队进行高效的开发

运营和支持的轮值值班:数据团队必不可少 数据科学 第1张

每个数据科学或产品团队都面临一个共同的挑战,就是如何协调新的(产品开发)和旧的(运维、支持)任务。当整个团队都需要同时处理这两个方面时,这就意味着,一方面团队需要保持产品的截止日期和推出新产品功能,同时,团队也需要在运营方面工作,修复现有产品并支持商业问题和电话。这种情况会导致意外的上下文切换,最终导致效率降低、截止日期失败和压力增加。

在实践中,这经常会导致某些团队成员承担这些额外任务或专门负责这些任务。但这是危险的,因为一旦这些专业团队成员中的任何一个人休假,整个公司可能会感到影响并出现问题。

因此,高效且可扩展的数据团队需要同时支持运营和新开发工作,并创建一个包括以下内容的系统:

  • 团队成员之间进行良好的知识共享,了解如何进行运营工作并支持产品/客户
  • 无需进行过多上下文切换即可进行不间断的开发工作
  • 定义良好并预估维护工作,以避免突发截止日期

轮流值班系统

过去,我们发现一个非常有效的系统是轮流值班系统,它不仅处理生产中的警报。简单地说,这是一个轮流系统,其中一个(或多个)团队成员在特定时间内是指定的幸存者,并纯粹负责运营工作。

值班人员不仅仅是在工作,他们也在保护整个团队免受开发工作外的混乱

为了完成这一点,这个系统允许只有值班人员(指定的幸存者)处理所有不属于“新开发”的工作。在那段时间里,值班人员不仅仅是在工作,他们也在保护整个团队免受开发工作外的混乱,包括:

  • 修复生产管道问题
  • 回答商业/客户问题
  • 支持客户电话
  • 减少技术部门(积压)
概述轮班例行任务的图表。

如上图所示,处理“经典”的轮班系统并确保生产环境正常运行仍然是最重要的。但是,如果生产中没有问题,这就可以释放其他任务,例如支持商业请求、客户电话或减少积压。

有哪些好处?

一开始转换到这个系统可能并不容易。并非每个团队成员都可以负责生产管道、商业支持和技术部门。但这不应该是一个障碍。重要的是要适当地沟通,告诉值班人员拥有这些项目并且是第一道防线,但可以随时寻求帮助。

从长远来看,这将给团队和整个组织带来许多好处。最直观的好处是更容易估计开发工作,团队将变得更加高效(上下文切换更少)。这也适用于运营方面,其中参与轮班系统的人数定义了可以处理多少运营工作。这使得与公司和利益相关者的沟通更加容易,因为一支由5人组成的团队轮换1人意味着5个全职员工中有1个在维护所有与现有产品相关的系统和工作(20% 运营,80% 开发)。这很容易计算和估计。

使用轮班制的团队中 20% 运营、80% 开发的分配示意图。

然而,还有更多的好处随着时间的推移而来,几乎像是副作用一样。所有团队成员都将成为全栈数据科学家。原因是每个团队成员都需要理解产品、客户、系统、模型/逻辑和代码基础设施的某个最小值。他们不需要成为专家,但最终会变得足够好,可以独立处理这些问题,至少可以一个星期。这也将确保当一个有价值的团队成员休假时,这不会成为问题,因为值班人员将始终支持团队。

此外,尽管这种值班时间有时可能会更有压力,但它为数据科学家提供了与商业方面和客户合作的机会。这可能是一种非常有价值和有意义的经验。

如何设置这样的系统?

这就是它变得有点技术化的地方(对于那些喜欢编码的人,只需向下滚动到最后)。设置这样的系统相当简单,但可能涉及一些编码。最重要的部分是与团队和利益相关者进行沟通,并告知他们这将如何工作。

由于整个系统的重点是支持团队,而不是创建更多的开销,我强烈建议完全自动化它。为此,您需要至少有3个系统:

  • 与生产连接的寻呼机系统,用于在生产失败时发出警报(例如,Opsgenie或Pagerduty)
  • 检测谁在值班并可以将其通知另一个系统的调度系统(例如,Apache Airflow或Keboola)
  • 用于联系团队并创建工单的通信平台(例如,Slack或Teams)

如果您已经拥有这些系统并且可以访问寻呼机系统和通信平台的API,则几乎完成了。唯一剩下的事情是在调度系统中设置一个作业,该作业首先运行API调用以从寻呼机系统获取值班人员,然后运行API推送以在通信平台中通知或覆盖通道/组/标记。

下面是一个简单的API调用示例,它将向您提供从Opsgenie获取值班人员的方式:

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

之后,您可以运行一个命令,在您的通信系统中执行某些操作。例如,在Slack中,覆盖一个用户组,以仅包含值班人员:

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

在这个故事的结尾,您将找到完整的代码版本,说明如何自动安排这段代码。这将确保每当有人在Slack上标记您的组(例如@ team),只有值班人员会被标记,并且可以决定是否需要通知更多团队成员。它还允许您快速添加新任务到dag中。例如,当您想要通知公司或团队谁现在正在值班,或者如果您想要相应地调整您的工单系统。

总结

为团队的操作、商业和技术部门工作制定轮换计划,可以使您的数据团队更加高效。它将减少上下文切换并允许更好的时间估计。此外,它将教育全栈数据科学家,他们可以自信地处理各种问题,以保护团队的其他成员。

除非另有说明,所有图片均由作者提供。

代码附录:

Airflow dag的示例,该dag从Opsgenie获取值班人员,并覆盖Slack中的用户组以仅包含该人员。编码肯定不完美(工作中的数据科学家),但我相信您会明白:

# 导入from airflow import DAG, XComArgfrom typing import Dict, Listfrom airflow.operators.bash import BashOperatorfrom airflow.operators.python import PythonOperatorfrom airflow.models import Variableimport json# 获取秘密令牌slack_token = Variable.get("slack_token")opsgenie_token = Variable.get("opsgenie_token")# 设置DAGdag = DAG(    dag_id,    schedule_interval=schedule_interval,    default_args=default_args,    catchup=catchup,    max_active_runs=max_active_runs,)with dag:        # 运行从Opsgenie获取值班人员的BashOperator    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    # 在PythonOperator中运行BashOperator并提供上下文    opsgenie_pull = PythonOperator(        task_id="opsgenie_pull",        python_callable=fetch_who_is_on_call,        provide_context=True,        dag=dag,    )        # 覆盖Slack组,使其仅包含值班人员    def overwrite_slack_group(**kwargs):                # 首先:从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]        ]                # 第二:运行BashOperator以覆盖Slack组        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    # 在PythonOperator中运行Slack覆盖的BashOperator    overwrite_slack = PythonOperator(        task_id="overwrite_slack",        python_callable=overwrite_slack_group,        provide_context=True,        dag=dag,    )    opsgenie_pull >> overwrite_slack    return dag
Leave a Reply

Your email address will not be published. Required fields are marked *