赞
踩
当用户受到 DDoS 攻击的时候,如果没有事先配置 Amanzon WAF 和 Amazon Shield Advanced 保护,往往在短时间内会产生大量的 Amazon CloudFront 请求或者流量,从而产生大量的 CDN 费用。站在 payer 账号的角度,payer 底下有很多 linked 账号在使用 Amazon CloudFront,我们希望可以集中和智能地监控所有 linked account 的 CDN 使用情况,在异常情况下发出告警。Amazon CloudFront 账单数据有一两天的延迟,所以我们决定结合 Amazon CloudWatch 的跨账号异常检测功能来实现这一目标。开始之前,我们先来了解什么是 Amazon CloudFront。
Amazon CloudFront 是一个全球内容分发网络 (CDN) 服务,它可以帮助您通过全球分布式的服务器网络更快地向用户提供内容。它的主要特性包括:
低延迟和高可用性:Amazon CloudFront 利用亚马逊云科技遍布全球的边缘节点,可以将内容快速传输到用户附近,减少延迟,提高可用性。
安全性:Amazon CloudFront 支持 HTTPS 协议,可以保护传输中的内容不被窃取或篡改。同时它还提供多种安全功能,如防 DDoS 攻击等。
静态请求加速:Amazon CloudFront 会自动缓存您的静态内容,如图片、视频、CSS 和 JavaScript 文件等,减少源站的负载压力,提高响应速度。
动态请求加速:Amazon CloudFront 可以轻松集成您的动态内容,如 API 、Web 应用程序等,为您提供全面的内容分发解决方案。
Amazon CloudWatch
跨账号异常检测介绍
从 2024 年 4 月起,Amazon CloudWatch 支持对账户间共享的指标进行异常检测。Amazon CloudWatch 异常检测功能允许您在单个监控账户中通过 Amazon CloudWatch 跨账户可观测性跟踪多个账户之间的指标行为的异常变化(需要源账号授权)。
Amazon CloudWatch 的异常检测功能将机器学习算法应用于指标的历史数据,自动创建预期值模型。这个模型会评估指标的趋势,并捕捉每小时、每日和每周的模式变化。算法会训练最近两周的指标数据,但即使没有完整的两周数据,您仍然可以为指标启用异常检测。
与传统的静态阈值方式不同,Amazon CloudWatch 异常检测可以自动发现异常行为,避免了由于阈值设置不当而漏报或误报的情况。及时发现系统异常,有助于快速定位和解决潜在问题,提高系统稳定性。
在配置异常检测时,您需要设置一个异常检测阈值 ANOMALY_DETECTION_BAND,我们会在下文详细说明。Amazon CloudWatch 将使用这个阈值和模型来确定指标值的”正常”范围。阈值设置越高,判定为正常的值范围就越大。一旦模型创建完成,Amazon CloudWatch 会持续评估并调整模型,以保证尽可能精准。这包括重新训练模型,使其能随着指标值的变化而自我调整。还包括优化针对季节性、峰值或稀疏指标的预测器模型。
您还可以在启用异常检测后排除指标的某些时间段,这些数据将不会用于训练模型。通过排除部署或其他异常事件的影响,可以确保创建最准确的模型。同时,也可以设置异常发生时自动执行操作,如发送通知或触发自动化工作流,实现自动化运维。
总的来说,Amazon CloudWatch 异常检测通过机器学习自动发现异常,能够提高系统可观测性和可靠性,同时简化了异常检测的实施和管理。无需搭建和维护独立的异常检测系统,直接使用 Amazon CloudWatch 的托管服务,降低运维成本,中国区和海外区都已经上线。
修改异常检测模型
扫码了解更多
接下来我们使用一个集中账号连接另外一个源账号实现异常监控。
配置集中账号
要实现跨账号监控,先得在集中账号开通 Amazon CloudWatch 跨账号监控功能,由于我们监控的目标服务是 Amazon CloudFront,所以必须选择美东 1 区域进行配置。打开 Amazon CloudWatch 服务,点击 settings,并在 Monitoring account configuration 处点击 Configure。
对于 Amazon CloudFront 的监控,我们只需要启用 Metrics 就可以,Logs 和 Metrics 的共享在功能上是免费的,其他数据共享会产生额外的功能费。
在 source accounts 里面把需要收集数据的源账号 ID 填上。
保存配置并退出,然后点击 “Resources to link accounts” 来获取源账号链接信息。
如果源账号和集中账号之间是已经使用 Amazon Organization 来管理,则可以使用下图左侧的连接方式。由于实验环境是独立的账号,所以我们选择右侧的 “Any Account”, 并点击 “Copy URL” 来保存源账号的连接配置 URL 地址。
配置源账号
首先使用新的浏览器登录源账号,跳转到美东 1 区域,并打开 Link 配置的链接地址,确认配置信息无误后点解 “Link”。
验证集中账号能否看到
源账号的 CW 指标
配置完后大概等待 5 分钟,在集中账号的 Amazon CloudWatch 选择 Amazon CloudFront 就能看到同步过来的 CDN metrics 信息。
配置 SNS 用于接受告警信息
创建一个 topic 叫 test-alert
创建 email 订阅,登陆邮箱通过订阅服务,并记下 topic 的 ARN 地址串 arn:aws:sns:us-east-1:xxxxxxxx:test-alert,后面配置 Amazon CloudFront 监控告警需要使用到。
部署代码
1、打开监控账号的 cloudshell ,然后从 git 上拉取代码
git clone https://github.com/Rayment915/aws-cdn-anamoly-detecor.git
左右滑动查看完整示意
跨账号监控只需要用到这两个文件:
- get_cross_account_distributionId.py
- create_alert_from_mon_account.py
左右滑动查看完整示意
- # get_cross_account_distributionId.py
- # use to list CloudFront distribution ID in source account and create alert in monitoring account
-
-
- import boto3
- from create_alert_from_mon_account import create_cloudwatch_alarm
-
-
- def get_distribution_list(OwningAccount,next_token = None):
- cloudwatch = boto3.client('cloudwatch')
- metrics = []
-
-
- while True:
- # Call the list_metrics API with the appropriate parameters
- if next_token:
- response = cloudwatch.list_metrics(
- Namespace='AWS/CloudFront',
- NextToken=next_token,
- IncludeLinkedAccounts=True,
- OwningAccount=OwningAccount
- )
- else:
- response = cloudwatch.list_metrics(
- Namespace='AWS/CloudFront',
- IncludeLinkedAccounts=True,
- OwningAccount=OwningAccount
- )
-
-
- # Append the retrieved metrics to the list
- metrics.extend(response['Metrics'])
-
-
- # Check if there are more results to retrieve
- next_token = response.get('NextToken', None)
- if not next_token:
- break
-
-
- distribution_ids= [metric['Dimensions'][1]['Value'] for metric in metrics]
- ret=set(distribution_ids)
- return ret
-
-
- if __name__ == "__main__":
- OwningAccount='YOUR_SOURCE_ACOUNT_ID'
- distributions_list=get_distribution_list(OwningAccount)
-
-
- # Modify it according to your use case
- ANOMALY_DETECTION_BAND=5
-
-
- metric_list=['Requests','BytesDownloaded']
- sns_arn='arn:aws:sns:us-east-1:YOUR_MONITORING_ACCOUNT_ID:test-alarm'
- for distribution_id in distributions_list:
- for metric in metric_list:
- create_cloudwatch_alarm(distribution_id,metric,sns_arn,ANOMALY_DETECTION_BAND,OwningAccount)
左右滑动查看完整示意
- # create_alert_from_mon_account.py
-
-
- import boto3
- from botocore.exceptions import ClientError
-
-
-
-
- def create_cloudwatch_alarm(distribution_id,metric,sns_arn,ANOMALY_DETECTION_BAND,account_id):
- """
- 创建基于 Anomaly Detection 的 CloudWatch 告警
- """
- # 创建 CloudWatch 客户端
- ALARM_NAME = f"CloudFront-{account_id}-{distribution_id}-{metric}-Anomaly"
- cloudwatch = boto3.client('cloudwatch', region_name='us-east-1')
-
-
- try:
- # 创建异常检测模型
- response = cloudwatch.put_anomaly_detector(
- MetricName=metric,
- Namespace='AWS/CloudFront',
- Dimensions=[
- {
- 'Name': 'DistributionId',
- 'Value': distribution_id
- },
- ],
- Stat='Sum',
-
-
- )
- print(f"==== created detactor model for {ALARM_NAME}==== ")
-
-
- # 创建基于异常检测的告警
- response = cloudwatch.put_metric_alarm(
- AlarmName=ALARM_NAME,
- ComparisonOperator='GreaterThanUpperThreshold',
- TreatMissingData = "notBreaching",
- ActionsEnabled = True,
- EvaluationPeriods = 5,
- DatapointsToAlarm = 3,
- Metrics = [
- {
- "Id": f"m_cdn_{metric}_{account_id}_{distribution_id}",
- "MetricStat": {
- "Metric": {
- "Namespace": "AWS/CloudFront",
- "MetricName": metric,
- "Dimensions": [
- {
- "Name": "Region",
- "Value": 'Global'
- },
- {
- "Name": "DistributionId",
- "Value": distribution_id
- }
- ]
- },
- "Period": 60,
- "Stat": "Sum"
- },
- "AccountId": account_id,
- "ReturnData": True
- },
- {
- "Id": f"ad_cdn_{metric}_{account_id}_{distribution_id}",
- "Expression": f"ANOMALY_DETECTION_BAND(m_cdn_{metric}_{account_id}_{distribution_id}, {ANOMALY_DETECTION_BAND})",
- "Label": f"{metric} (expected)",
- "ReturnData": True
- }
- ],
-
- ThresholdMetricId=f"ad_cdn_{metric}_{account_id}_{distribution_id}",
- AlarmActions=[sns_arn]
- )
-
-
- print(f"已创建告警: {ALARM_NAME}")
- except ClientError as e:
- print(f"创建告警失败: {e}")
左右滑动查看完整示意
2、 执行代码部署上去
两个文件需要放同一个目录,并修改 get_cross_account_distributionId.py 文件的部分信息:
OwningAccount ,源账号的 Amazon account ID
sns_arn ,修改为实际的 SNS ARN 地址
python3 get_cross_account_distributionId.py
3、 ANOMALY_DETECTION_BAND 说明
在创建异常检测告警时,我们需要指定一个参数 ANOMALY_DETECTION_BAND。这个值用于定义异常检测带的厚度。您设置的数值会乘以指标的标准差。如果使用较高的值,异常检测带就会变得更宽更厚,这样一些异常值可能被忽略。但如果使用较小的数值,就可能产生大量的误报。基本上,这个值取决于您的指标数据的特征,以及您希望异常检测带有多精确。考虑到 CDN 的流量通常会产生较大的请求数和带宽的波动,您可以先将 ANOMALY_DETECTION_BAND 设置的高一些,例如 5 。然后选择几个 Amazon CloudFront 分配,观察异常检测带是否能覆盖正常的 Request 和 BytesDownloaded 波形,再根据实际情况将 BAND 调大或者调小。我们的目的是监控 CDN 流量的异常增长,所以只需要观察波峰。另外,您也不需要观察所有的 Amazon CloudFront 分配,选择几个典型的分配来评估 BAND 数值即可。由于 Amazon CloudWatch 异常检测会对模型进行持续的评估和调整,所以 ANOMALY_DETECTION_BAND 主要起到种子的作用,您不需要过于担心它的精准性。
成本预估
异常检测警报会产生以下成本(集中账号):
您在 alarm 中用到的每个指标的成本。
额外的两个警报指标成本,用于计算异常检测模型生成的上下限指标。
官方计价
扫码了解更多
举例:
假设现在有一个集中账号和一个源账号,其中源账号有 100 个分配需要跨账号监控。这时候源账号在只共享 Logs 和 Metrics 的情况下不会产生额外的费用,集中账号会产生 100*3*2 = 600 个 metric alarms 的费用,因为每个 metric 会产生 3 个 alarm-metric 的费用,然后我们的代码监控 ‘Requests’ 和 ‘BytesDownloaded’ 这两个源账号的指标。
总结
通过 Amazon CloudWatch 的跨账号异常检测功能,我们可以实现使用集中账号来监控多个源账号的 Amazon CloudFront 维度,通过机器学习自动和迅速地发现异常,提高系统可观测性和可靠性,同时简化了异常检测的实施和管理。但是对于新创建的或者预知到有突发流量(如线上推广活动)的 Amazon CloudFront 分配,异常监控可能会产生误报,在这期间可以适当暂停异常监控告警功能,转而使用 Amazon Budgets 对 Link 账号进行成本控制。
参考链接
Amazon CloudWatch
现在支持跨账户异常检测
扫码了解更多
建立监控账号
扫码了解更多
使用
Amazon CloudWatch
异常检测
扫码了解更多
左右滑动查看更多
本篇作者
林进风
2017 年加入亚马逊云科技,现从事方案架构( SA )工作,在计算、联网、数据库方面以及 Serverless 领域学习和研究。在硬件和应用容灾以及高可用方面有相关经验。
张振威
亚马逊云科技 APN 解决方案架构师,主要负责合作伙伴架构咨询和方案设计,同时致力于亚马逊云科技云服务在国内的应用及推广,擅长数据迁移、数据库调优和数据分析。
陈程
亚马逊云科技高级边缘产品架构师,专注于
Amazon CloudFront 、 Amazon WAF 、 Amazon Shield 、 Amazon Global Accelerator 、 Amazon Route 53 等产品和服务。
庄颖勤
亚马逊云科技解决方案架构师,负责基于亚马逊云科技的云计算方案架构设计、咨询、实施等工作。在 DevOps 、 CI/CD 和容器等领域拥有丰富的技术和支持经验,致力于帮助客户实现技术创新和业务发展。
柯俊雄
亚马逊云科技解决方案架构师,专注于数据分析/容器化领域。
星标不迷路,开发更极速!
关注后记得星标「亚马逊云开发者」
点击阅读原文查看博客,获得更详细内容
听说,点完下面4个按钮
就不会碰到bug了!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。