Komodo Health 公司如何在 EKS 与 EMR 6 上使用多租户 Notebook 平台建立自助服务分析方案

2020 年 8 月 22 日

Komodo Health 公司如何在 EKS 与 EMR 6 上使用多租户 Notebook 平台建立自助服务分析方案

Original URL: https://aws.amazon.com/cn/blogs/startups/how-komodo-health-enables-self-serve-analytics-with-eks-emr/


Komodo Health 公司客座文章作者:Jigar Bhalodia,数据基础设施工程师;Hanyu Cui,数据基础设施高级软件工程师;Stephen Goeppele-Parrish,云基础设施工程师;Chris Han,高级工程经理。


我们还要特别感谢为本文审核以及平台开发做出贡献的工程师们:Scott Edenbaum、Jean Barmash、Andrea Ortuno 以及 Tomo Ishihara。



在 Komodo Health 公司,我们的使命一直在迅速演进,努力基于健康数据打造软件与数据产品、进而减轻全球疾病负担。我们的 Healthcare MapTM 记录超过 3.2 亿美国人(已进行数据脱敏)在整个医疗系统中的经历。我们还不断增加数据来源与临床绝对值,以确保我们的数据始终保持及时性、完整性与关联性。


过去几年当中,我们公司迎来了 100%的同比增长(过去 18 个月中,我们工程技术团队中的工程师与数据科学家也由 35 位增加至 90 多位)。虽然这样的增长势头令人兴奋,但同时也带来一系列规模扩展挑战。其中最大的挑战之一,就是如何在内部运行 Spark 以进行即席分析与批量 ETL 作业。


挑战


我们在 Kubernetes 节点上运行独立 Spark 集群已经有四年时间,主要将其用于生产 ETL 管道与即席分析。在分析方面,我们的数据科学家与数据工程师首选的流行工具当数 Jupyter notebooks,能够借此与 Spark 对接以实现分布式计算。在大规模自动化技术的帮助下,每位工程师或科学家都能获得属于自己的 Spark 集群,并在其中做出种种修改与调整以适应实际需求。另外,各个集群也都在 AWS 当中通过专用的 ASG 与 EC2 实例实现了自我管理。


对于最早接触基础设施的数据科学家与数据工程师们而言,Spark 架构效果极佳,能够为他们提供与需求紧密关联的大量灵活性集群配置选项。但随着业务规模的增长,我们需要进一步改进基础设施以降低成本、扩展访问范围、提高工程效率并增强资源利用率。


愿景与目标


我们的愿景是通过 AWS 的 Elastic Map Reduce (EMR) 6 构建一套平台,借此:


  1. 通过快速帮助工程师及数据科学家访问Jupyter notebooks、JupyterLab与Spark计算资源,缩短入职时间。

  2. 消除基础设施中的复杂性,减少为数据科学家及工程师提供支持所带来的整体负担。

  3. 通过自动规模伸缩与资源优化(例如使用竞价实例)降低EC2运营成本。

  4. 通过容器化技术支持多租户机制,避免计算资源的过度配置。

  5. 提高集群的整体稳定性,并启用蓝/绿部署机制。



工程增长与成本之间的关系


解决方案


我们以 JupyterHub 为前端,EMR 6 为后端构建起一套 Spark 平台。其能够支持现有工作流,且不会令开发人员陷入 Spark 集群管理所带来的沉重负担当中。数据科学家与工程师们现在可以专注于完成自己最擅长的事务,其余工作则由基础设施团队接管负责。整体解决方案涵盖为 notebooks 提供服务的前端 Kubernetes 托管 JupyterHub 服务器、运行 Spark 的后端 EMR 6 集群,以及保证我们稳定如一提供高质量功能、且不会发生性能衰退的整体流程与 CI/CD 管道。


之所以能够成功打造出这样一套解决方案,关键在于我们立足架构与设计层面采取了一系列特殊实现方法。


使用 EKS 与 EMR 6 搭建平台架构


开源、分布式、多用户 Jupyter notebook 环境能够帮助用户组更加轻松高效地使用 Jupyter notebooks。JupyterHub 能够帮助我们构建起可供用户访问的网页,借此快速使用 Jupyter notebooks 服务器。用户不需要接触或者了解 AWS 及 Kubernetes——相反,只需提供自己的单点登录凭证,即可快速完成身份验证。



Example of a Jupyter Notebook


我们将 JupyterHub 运行在一套部署有开源 Helm charts(由 Jupyter 提供)的 EKS 集群之上。当用户访问我们的 HupyterHub 网页时,HupyterHub 将通过 Okta 进行身份验证,并通过开箱即用的代理为该用户创建一个 notebook 服务器 pod。JupyterHub notebook 服务器的工作方式与常规 notebook 服务器相同,用户可以选择 Python 内核以支持纯 Python 代码,也可以选择 PySPark 内核与 Sparkmagic 以访问 EMR 6 集群。



运行不同内核


我们还支持 JupyterLab——一套面向 Jupyter notebooks 的下一代用户界面。JupyterLab 能够帮助用户在同一界面当中排布多个窗格,借此提高工作效率。各窗格可以容纳 notebook、文本文件、终端或者控制台的一个或者多个实例。通过支持传统 notebooks 与 JupyterLab notebooks,工程师与科学家们能够任意选择自己喜爱的界面布局。



JupyterLab 示例


基础设施团队管理着 JupyterHub 及其辅助组件的方方面面,具体包括 Sparkmagic、Livy 以及多租户 EMR Spark 集群。作为唯一的例外,用户可以更改某些 Sparkmagic 配置选项。通过选项调节,我们的用户既能够指定出独一无二的 Spark 配置,又可以为运行在多租户 EMR 集群上的 Spark 应用程序定义出自己的 Docker 镜像。



JupyterHub、EKS 与 Spark 架构


同时支持即席分析与批量 ETL 作业


我们的数据科学家与数据工程师们往往投入大量时间进行即席分析。这类工作主要为交互形式,需要快速轮转,而且用户通常无法预测总体资源需求量。在 2 分钟之内,我们的用户就能访问一个 notebook 并自动生成用于在 EMR 集群上运行代码的 Spark 会话。在登录之后,会话将在用户启动代码的当天之内保持活动状态。我们在 Jupyter notebooks 中还使用到 Sparkmagic,用于实现 notebook 与 PySpark 的无缝集成。我们对开源项目 Sparkmagic 进行了定制化,借此满足我们业务体系中的独特安全性与部署需求。


在我们的 Spark 工作负载当中,ETL 作业同样占据着相当高的比例。我们使用 Airflow 进行编排,而且各管道能够将 Spark 作业提交至 EMR 集群以进行分布式计算。我们还创建了一个内部小型 Python 软件包,用于将批处理作业直接提交至 EMR 集群中的 Livy 端点。即使不使用我们托管 notebooks,Airflow 作业仍然能够充分发挥托管 EMR Spark 集群的优势,借此减轻维护与运营负担。


通过实例组与 YARN 节点标签实现 EMR 自动规模伸缩


作为基础设施团队,我们主要为内部利益相关方提供服务,具体包括 90 多位全职工程师、数据科学家以及数据工程师。我们希望能打造出一套多租户平台,可支持各类用户与用例。凭借着灵活的用户数量与工作负载可变性,这套平台应该在保持成本效益的同时,根据需求可靠实现规模伸缩。最终,我们通过实例组与 YARN 节点标签成功实现了这一目标。


根据资源使用量快速实现节点的规模伸缩,将帮助我们在 10 到 15 分钟之内将资源调整到合适的水平。为了实现这种自动规模伸缩,最重要就是结合实际需求提供适当的 YARN 指标;此外规模伸缩的频率也要合理,避免出现“乒乓”状况,即先触发规模扩展并发现资源过多,再触发规模收缩并导致资源过少,而后反复循环。这只会引发作业失败并严重破坏集群的运行稳定性。


自动规模伸缩规则会直接影响到用户的体验,而在改善用户体验与管理基础设施成本之间寻求平衡点,则是我们不懈追求的终极目标。一方面,用户需要快速扩展资源并借此支持业务运行,另一方面,保留闲置资源以改善用户体验则非常昂贵。在自动规模伸缩方面不存在唯一正确的答案,我们需要遍历调整规则以在成本与用户体验之间找到微妙的最优比例。



自动规模伸缩功能


通过 Spark 动态分配实现高效资源利用


启用 Spark 动态分配,成为我们达成目标的关键所在,这也是我们选择 EMR 与 YARN 资源管理器的原因所在。默认情况下,EMR 会启用动态分配,能够更高效地将资源分配给各 Spark 应用程序。使用临时作业,我们往往很难预测 notebooks 的资源利用率,也无法立足单元级别实现资源分配。而在静态资源分配的情况下,只要 notebook 仍在运行,就会有固定量的资源被分配给该 notebook——无论其计算需求如何、繁忙抑或闲置。但在启用动态分配之后,Spark 能够根据当前创建的任务数量确定分配给 notebook 中每个单元的适当资源量。如果 notebook 正在运行但却处闲置状态,则仅为驱动程序分配资源。当 notebook 闲置时,用户可以通过缓存数据框保留执行程序,并通过设定执行程序同样闲置后的数据块缓存时长,进一步节约系统资源。


使用容器实现多租户与依赖项管理


我们利用 EMR 6 中的 Docker 容器化支持功能作为多租户 Spark 集群的基础。如果没有容器化方案,依赖项管理将变得充满挑战,因为用户可能需要在单一集群上使用相互冲突的多个版本。用户需要使用各自不同的依赖项定义自己的 Docker 镜像,并为集群上运行的各个 Spark 应用程序指定驱动程序与执行程序镜像。我们将 EMR 引入多租户用例,自第一个 beta 版发布以来,我们已经与 AWS EMR 服务团队及支持工程师紧密合作,帮助他们发现问题并探索指导性的正确配置与变通方法。


日志传递架构


通过查看 S3 里面的 EMR 日志来调试 Spark 应用程序也是一项颇为复杂的难题。我们决定使用 logstash 从 S3 中的日志处提取并过滤字段,并将其进一步推送至 AWS ElasticSearch 当中。配合适当的索引管理与日志保留配置,AWS Elasticsearch 极大降低了日志检索难度,也让应用程序调试变得更加轻松。


观察、洞见与经验教训


在平台构建的 5 个月中,我们吸取到很多教训,也观察到不少有趣的用例:


  1. 工程部门以外的其他职能用户也开始使用notebooks。即使对于内部使用者,用户体验同样非常重要。由于我们使用了新的用户友好型平台因此工程部门之外的其他职能用户也可以轻易通过notebooks高效完成自己的预期任务。

  2. 由于notebooks的上手难度有所降低,现在我们看到更多意料之外的精彩用例,例如使用notebooks进行工程师培训。

  3. 在架构阶段,我们预计需要对后端资源设置限制或配额,保证在一定程度上控制其容量过度扩展问题。但事实证明,虽然我们的用户数量众多,但这种风险从未真正出现。

  4. 预判主要目标之外的其他工具需求。我们还努力跟踪用户的使用情况,从多租户环境中明确划分不同部门的具体托管成本。我们可以在团队视图中汇总每位用户的行动以实现成本溯源。

  5. 为新的解决方案建立更准确的期望。在平台启动之后,我们知道其会涵盖大多数用例,但还达不到100%。但在人们开始使用平台并投入运营之后,我们预计人们会很快提出大量支持请求。为此,我们的团队在企业内部构建起多份演示与培训课程,帮助用户快速解决难题、学习相关方法。

  6. 内部工程团队的贡献有所增加,这提升了我们对用户需求的理解。自发布以来,我们已经在路线图中添加了Glue目录以及其他多项增强功能。

  7. EMR的实例组特定于当前可用区,这是为了尽可能降低延迟水平。我们依靠实例组与YARN节点标签在整个可用区内使用多种不同实例类型。


总结


在 EMR 上使用 Spark,可以在基础设施抽象与管理之间达成适当的平衡,同时帮助我们实现粗粒度配置以保证数据科学家及工程师及时获得所需工具。在 Route 53 与 ALB 等多种 AWS 服务的帮助下,整个部署流程也变得更加轻松易行。


总体而言,我们的工程团队获得了高度评价。Jupyter notebooks 与 Spark 得以顺畅配伍,EMR 6 与其他 AWS 服务则成为这套平台全面成功的核心驱动力。


本文转载自亚马逊 AWS 官方博客。


原文链接


Komodo Health 公司如何在 EKS 与 EMR 6 上使用多租户 Notebook 平台建立自助服务分析方案


2020 年 8 月 22 日 14:031290

欲了解 AWS 的更多信息,请访问【AWS 技术专区】

评论

发布
暂无评论
发现更多内容
Komodo Health 公司如何在 EKS 与 EMR 6 上使用多租户 Notebook 平台建立自助服务分析方案-InfoQ