使用Amazon CloudWatch构建一个集中监控和报告解决方案,用于Amazon SageMaker
使用Amazon CloudWatch构建集中监控和报告解决方案,用于Amazon SageMaker
Amazon SageMaker是一个完全托管的机器学习(ML)平台,提供了一套全面的服务,用于端到端的ML工作负载。根据AWS的最佳实践建议,客户使用单独的帐户来简化用户的策略管理,并通过工作负载和帐户来隔离资源。然而,当越来越多的用户和团队在云中使用ML平台时,在扩展的多帐户环境中监控大规模的ML工作负载变得更加具有挑战性。为了更好地可观察性,客户正在寻找解决方案来监控跨帐户资源使用情况和跟踪活动,例如作业启动和运行状态,这对于他们的ML治理和管理要求至关重要。
SageMaker的服务,例如处理、训练和托管,从运行实例收集指标和日志,并将其推送到用户的Amazon CloudWatch账户。要查看不同帐户中这些作业的详细信息,您需要登录到每个帐户,找到相应的作业,并查看其状态。没有一个单一的界面可以轻松显示这个跨帐户和多作业的信息。此外,云管理员团队需要为不同的SageMaker工作负载帐户提供个人访问权限,这为云平台团队增加了额外的管理开销。
在本文中,我们提供了一个跨帐户可观察性仪表板,用于监控SageMaker用户活动和多个帐户中的资源。它允许终端用户和云管理团队高效地监控正在运行的ML工作负载,查看这些工作负载的状态,并在特定时间点追踪不同帐户的活动。通过该仪表板,您不需要从SageMaker控制台导航并点击每个作业以查找作业日志的详细信息。相反,您可以轻松查看正在运行的作业和作业状态,解决作业问题,并在共享帐户中发现问题时设置警报,例如作业失败、资源利用率低等。您还可以控制对这个集中监控仪表板的访问权限,或与相关机构共享仪表板以满足审计和管理要求。
解决方案概述
该解决方案旨在实现对多帐户环境中的SageMaker作业和活动的集中监控。该解决方案不依赖于AWS组织,但可以轻松在组织或AWS控制中心环境中采用。该解决方案可以帮助运营团队从单一界面高层次地查看分布在多个工作负载帐户中的所有SageMaker工作负载。它还可以选择在SageMaker工作负载帐户之间启用CloudWatch跨帐户可观察性,以提供对来自集中监控帐户的监控遥测数据(例如指标、日志和跟踪)的访问。下面是一个示例仪表板的截图。
下图显示了这个集中式仪表板解决方案的架构。
SageMaker与Amazon EventBridge原生集成,可以监控SageMaker中的状态更改事件。EventBridge使您能够自动化SageMaker并对事件(例如训练作业状态更改或端点状态更改)进行自动响应。SageMaker的事件以近实时方式传送到EventBridge。有关由EventBridge监控的SageMaker事件的更多信息,请参阅使用Amazon EventBridge自动化Amazon SageMaker。除了SageMaker的原生事件外,当您进行API调用时,AWS CloudTrail也会发布事件,并将其流式传输到EventBridge,以便许多下游自动化或监控用例使用。在我们的解决方案中,我们在工作负载帐户中使用EventBridge规则,将SageMaker服务事件和API事件流式传输到监控帐户的事件总线,以进行集中监控。
在集中监控帐户中,事件被一个EventBridge规则捕获,并进一步处理为不同的目标:
- 一个CloudWatch日志组,用于以下用途:
- 审计和存档目的。有关更多信息,请参阅Amazon CloudWatch日志用户指南。
- 使用CloudWatch日志洞察查询分析日志数据。CloudWatch Logs Insights使您能够在CloudWatch日志中交互式搜索和分析日志数据。您可以执行查询,以帮助您更高效和有效地响应操作问题。如果出现问题,您可以使用CloudWatch Logs Insights识别潜在原因并验证已部署的修复措施。
- 支持CloudWatch仪表板中的CloudWatch指标洞察查询小部件,将CloudWatch Insights查询添加到仪表板,并导出查询结果。
- 一个AWS Lambda函数,用于完成以下任务:
- 执行自定义逻辑以增强SageMaker服务事件。一个例子是在接收到作业完成事件时,在SageMaker作业主机的利用率指标上执行度量查询。
- 将事件信息转换为特定日志格式中的指标,作为EMF日志进行摄入。有关更多信息,请参阅在日志中嵌入指标。
本帖中的示例使用本地CloudWatch跨帐户可观察性功能来实现跨帐户的指标、日志和跟踪访问。如架构图底部所示,它与此功能集成,以实现跨帐户的指标和日志。要启用此功能,需要在监控帐户和源工作负载帐户中创建必要的权限和资源。
您可以将此解决方案用于组织管理的AWS帐户或独立帐户。以下部分说明了每种情况的步骤。请注意,在每种情况下,步骤是在不同的AWS帐户中执行的。为了方便起见,每个步骤的执行账户类型在每个步骤开始时都会突出显示。
先决条件
在开始此过程之前,请从GitHub仓库中克隆我们的源代码到您的本地环境或AWS Cloud9。此外,您还需要以下内容:
- 已安装Node.js 14.15.0(或更高版本)和nmp
- 已安装AWS命令行界面(AWS CLI)版本2
- 已安装AWS CDK工具包
- 已安装Docker引擎(在执行部署过程时处于运行状态)
在组织环境中部署解决方案
如果监控帐户和所有SageMaker工作负载帐户都在同一个组织中,则会通过来自组织管理帐户的AWS CloudFormation StackSet自动创建源工作负载帐户中所需的基础架构。因此,不需要手动部署基础架构到源工作负载帐户中。当创建新帐户或将现有帐户移动到目标组织单位(OU)时,源工作负载基础架构堆栈将被自动部署并包含在集中监控的范围内。
设置监控帐户资源
我们需要收集以下AWS帐户信息来设置监控帐户资源,这些信息将在稍后的设置脚本中用作输入。
输入 | 描述 | 示例 |
Home Region | 工作负载运行的区域。 | ap-southeast-2 |
监控帐户AWS CLI配置文件名称 | 您可以在~/.aws/config 中找到配置文件名称。这是可选的。如果不提供,它将使用链中的默认AWS凭证。 |
。 |
SageMaker工作负载OU路径 | 具有SageMaker工作负载帐户的OU路径。在路径末尾保留/ 。 |
o-1a2b3c4d5e/r-saaa/ou-saaa-1a2b3c4d/ |
要检索OU路径,您可以转到组织控制台,在AWS帐户下找到构建OU路径的信息。对于以下示例,相应的OU路径是o-ye3wn3kyh6/r-taql/ou-taql-wu7296by/
。
检索到此信息后,运行以下命令在监控帐户上部署所需的资源:
./scripts/organization-deployment/deploy-monitoring-account.sh
您可以从部署中获得以下输出。记下这些输出,以便在部署管理帐户堆栈时使用。
设置管理账号资源
我们需要收集以下 AWS 账号信息来设置管理账号资源,这些信息将作为后续设置脚本的输入。
输入 | 描述 | 示例 |
Home Region | 工作负载运行的区域。这应该与监控堆栈相同。 | ap-southeast-2 |
管理账号 AWS CLI 配置文件名称 | 您可以在 ~/.aws/config 中找到配置文件名称。这是可选的。如果不提供,将使用默认的 AWS 凭证链。 |
. |
SageMaker 工作负载 OU ID | 这里我们只使用 OU ID,而不是路径。 | ou-saaa-1a2b3c4d |
监控账号 ID | 监控堆栈部署的账号 ID。 | . |
监控账号角色名称 | 上一步骤的 MonitoringAccountRoleName 输出。 |
. |
监控账号事件总线 ARN | 上一步骤的 MonitoringAccountEventbusARN 输出。 |
. |
监控账号 Sink 标识符 | 上一步骤的 MonitoringAccountSinkIdentifier 输出。 |
. |
您可以通过运行以下命令部署管理账号资源:
./scripts/organization-deployment/deploy-management-account.sh
在非组织环境中部署解决方案
如果您的环境不使用组织,监控账号基础设施堆栈将以类似的方式部署,但需要进行一些更改。但是,工作负载基础设施堆栈需要手动部署到每个工作负载账号中。因此,此方法适用于账号数量有限的环境。对于大型环境,建议考虑使用组织。
设置监控账号资源
我们需要收集以下 AWS 账号信息来设置监控账号资源,这些信息将作为后续设置脚本的输入。
输入 | 描述 | 示例 |
Home Region | 工作负载运行的区域。 | ap-southeast-2 |
SageMaker 工作负载账号列表 | 以逗号分隔的运行 SageMaker 工作负载并将事件流式传输到监控账号的账号列表。 | 111111111111,222222222222 |
监控账号 AWS CLI 配置文件名称 | 您可以在 ~/.aws/config 中找到配置文件名称。这是可选的。如果不提供,将使用默认的 AWS 凭证链。 |
. |
在收集必要信息后,我们可以通过运行以下命令部署监控账户资源:
./scripts/individual-deployment/deploy-monitoring-account.sh
部署完成后,我们会得到以下输出。请记下这些输出,以便在部署管理账户堆栈时使用。
设置工作负载账户监控基础架构
我们需要收集以下 AWS 账户信息来设置工作负载账户监控基础架构,这些信息将在稍后的设置脚本中使用。
输入 | 描述 | 示例 |
Home Region | 工作负载运行的区域。这应与监控堆栈相同。 | ap-southeast-2 |
监控账户 ID | 监控堆栈部署的账户 ID。 | . |
监控账户角色名称 | 前一步中 MonitoringAccountRoleName 的输出。 |
. |
监控账户事件总线 ARN | 前一步中 MonitoringAccountEventbusARN 的输出。 |
. |
监控账户 sink 标识符 | 前一步中 MonitoringAccountSinkIdentifier 的输出。 |
. |
工作负载账户 AWS CLI 配置文件名称 | 您可以在 ~/.aws/config 中找到配置文件名称。这是可选的。如果未提供,将使用链中的默认 AWS 凭据。 |
. |
我们可以通过运行以下命令部署监控账户资源:
./scripts/individual-deployment/deploy-workload-account.sh
在 CloudWatch 仪表板上可视化 ML 任务
为了检查解决方案是否有效,我们需要在前面的部分中使用的工作负载账户上运行多个 SageMaker 处理作业和 SageMaker 训练作业。CloudWatch 仪表板可以根据您自己的场景进行自定义。我们的示例仪表板由用于可视化 SageMaker 处理作业和 SageMaker 训练作业的小部件组成。此仪表板显示了所有用于监控工作负载账户的作业。在每种类型的作业中,我们显示三个小部件,分别是作业总数、失败作业数以及每个作业的详细信息。在我们的示例中,我们有两个工作负载账户。通过该仪表板,我们可以轻松找到一个工作负载账户既有处理作业又有训练作业,而另一个工作负载账户只有训练作业。与 CloudWatch 中使用的功能一样,我们可以设置刷新间隔,指定图表类型,进行缩放,或者运行诸如将日志下载为 CSV 文件等操作。
自定义您的仪表板
GitHub 存储库提供的解决方案包括 SageMaker 训练作业和 SageMaker 处理作业的监控。如果您想要添加更多仪表板以监控其他 SageMaker 作业(例如批量转换作业),可以按照本节中的说明自定义您的仪表板。通过修改 index.py 文件,您可以自定义要在仪表板上显示的字段。您可以通过 EventBridge 访问 CloudWatch 捕获的所有详细信息。在 Lambda 函数中,您可以选择要在仪表板上显示的必要字段。请参阅以下代码:
@metric_scope
def lambda_handler(event, context, metrics):
try:
event_type = None
try:
event_type = SAGEMAKER_STAGE_CHANGE_EVENT(event["detail-type"])
except ValueError as e:
print("Unexpected event received")
if event_type:
account = event["account"]
detail = event["detail"]
job_detail = {
"DashboardQuery": "True"
}
job_detail["Account"] = account
job_detail["JobType"] = event_type.name
metrics.set_dimensions({"account": account, "jobType": event_type.name}, use_default=False)
metrics.set_property("JobType", event_type.value)
if event_type == SAGEMAKER_STAGE_CHANGE_EVENT.PROCESSING_JOB:
job_status = detail.get("ProcessingJobStatus")
metrics.set_property("JobName", detail.get("ProcessingJobName"))
metrics.set_property("ProcessingJobArn", detail.get("ProcessingJobArn"))
job_detail["JobName"] = detail.get("ProcessingJobName")
job_detail["ProcessingJobArn"] = detail.get("ProcessingJobArn")
job_detail["Status"] = job_status
job_detail["StartTime"] = detail.get("ProcessingStartTime")
job_detail["InstanceType"] = detail.get("ProcessingResources").get("ClusterConfig").get("InstanceType")
job_detail["InstanceCount"] = detail.get("ProcessingResources").get("ClusterConfig").get("InstanceCount")
if detail.get("FailureReason"):
要自定义仪表板或小部件,您可以修改 monitoring-account-infra-stack.ts 文件中的源代码。请注意,您在此文件中使用的字段名称应与 Lambda 文件中定义的那些(即job_detail
的键)相同:
// CloudWatch 仪表板
const sagemakerMonitoringDashboard = new cloudwatch.Dashboard(
this, 'sagemakerMonitoringDashboard',
{
dashboardName: Parameters.DASHBOARD_NAME,
widgets: []
}
)
// 处理作业
const processingJobCountWidget = new cloudwatch.GraphWidget({
title: "总处理作业计数",
stacked: false,
width: 12,
height: 6,
left:[
new cloudwatch.MathExpression({
expression: `SEARCH('{${AWS_EMF_NAMESPACE},account,jobType} jobType="PROCESSING_JOB" MetricName="ProcessingJobCount_Total"', 'Sum', 300)`,
searchRegion: this.region,
label: "${PROP('Dim.account')}",
})
]
});
processingJobCountWidget.position(0,0)
const processingJobFailedWidget = new cloudwatch.GraphWidget({
title: "失败的处理作业计数",
stacked: false,
width: 12,
height:6,
right:[
new cloudwatch.MathExpression({
expression: `SEARCH('{${AWS_EMF_NAMESPACE},account,jobType} jobType="PROCESSING_JOB" MetricName="ProcessingJobCount_Failed"', 'Sum', 300)`,
searchRegion: this.region,
label: "${PROP('Dim.account')}",
})
]
})
processingJobFailedWidget.position(12,0)
const processingJobInsightsQueryWidget = new cloudwatch.LogQueryWidget(
{
title: 'SageMaker 处理作业历史记录',
logGroupNames: [ingesterLambda.logGroup.logGroupName],
view: cloudwatch.LogQueryVisualizationType.TABLE,
queryLines: [
'sort @timestamp desc',
'filter DashboardQuery == "True"',
'filter JobType == "PROCESSING_JOB"',
'fields Account, JobName, Status, Duration, InstanceCount, InstanceType, Host, fromMillis(StartTime) as StartTime, FailureReason',
'fields Metrics.CPUUtilization as CPUUtil, Metrics.DiskUtilization as DiskUtil, Metrics.MemoryUtilization as MemoryUtil',
'fields Metrics.GPUMemoryUtilization as GPUMemoeyUtil, Metrics.GPUUtilization as GPUUtil',
],
width:24,
height: 6,
}
);
processingJobInsightsQueryWidget.position(0, 6)
sagemakerMonitoringDashboard.addWidgets(processingJobCountWidget);
sagemakerMonitoringDashboard.addWidgets(processingJobFailedWidget);
sagemakerMonitoringDashboard.addWidgets(processingJobInsightsQueryWidget);
在您修改仪表板之后,您需要从头重新部署此解决方案。您可以运行 GitHub 存储库中提供的 Jupyter 笔记本来重新运行 SageMaker 流水线,这将再次启动 SageMaker 处理作业。作业完成后,您可以转到 CloudWatch 控制台,在导航窗格中选择仪表板下的自定义仪表板。您可以找到名为 SageMaker-Monitoring-Dashboard 的仪表板。
清理
如果您不再需要此自定义仪表板,可以清理资源。要删除所有创建的资源,请使用本节中的代码。对于组织环境与非组织环境,清理稍有不同。
对于组织环境,请使用以下代码:
make destroy-management-stackset # 对管理账户执行
make destroy-monitoring-account-infra # 对监控账户执行
对于非组织环境,请使用以下代码:
make destroy-workload-account-infra # 对每个工作负载账户执行
make destroy-monitoring-account-infra # 对监控账户执行
或者,您可以登录到监控账户、工作负载账户和管理账户,从 CloudFormation 控制台中删除堆栈。
结论
在本文中,我们讨论了使用 CloudWatch 为 SageMaker 实现集中式监控和报告解决方案的实现方法。通过遵循本文中概述的逐步说明,您可以创建一个多账户监控仪表板,实时显示与各个 SageMaker 作业相关的关键指标和汇总日志。通过这个集中式监控仪表板,您可以更好地了解跨多个账户的 SageMaker 作业的活动,更快地排查问题,并根据实时数据做出明智的决策。总的来说,使用 CloudWatch 实现集中式监控和报告解决方案为组织管理基于云的 ML 基础设施和资源利用率提供了一种高效的方式。
请尝试使用该解决方案并向我们发送反馈,可以通过Amazon SageMaker的AWS论坛或您通常的AWS联系人进行反馈。
要了解有关跨账户可观察性功能的更多信息,请参阅博客文章Amazon CloudWatch跨账户可观察性。