如何在AWS CDK中自动获取CloudWatch指标的所有维度?
在AWS CDK中自动获取CloudWatch指标维度并创建告警的方案
CDK本身是静态基础设施即代码工具,在synth阶段生成CloudFormation模板,因此没有直接内置调用list-metrics的方法,但可以通过两种思路实现你的需求:
方案一:构建时通过AWS SDK获取维度(静态生成告警)
在CDK代码执行阶段(本地synth或CI/CD部署时),直接调用AWS CloudWatch SDK的list-metrics接口,获取指定命名空间下的表名维度,再批量生成告警资源。
代码示例(TypeScript)
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; import { CloudWatchClient, ListMetricsCommand } from "@aws-sdk/client-cloudwatch"; export class TableMetricAlarmsStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // 初始化CloudWatch客户端 const cwClient = new CloudWatchClient({ region: this.region }); // 调用list-metrics获取指定维度的指标 const listMetricsCmd = new ListMetricsCommand({ Namespace: "Your-Namespace", // 替换为你的指标命名空间 MetricName: "Your-Metric-Name", // 替换为你的指标名 Dimensions: [{ Name: "TableName" }] // 指定要过滤的维度名称 }); // 同步请求(synth阶段执行) const metricsResponse = await cwClient.send(listMetricsCmd); // 提取所有表名维度值 const tableNames = metricsResponse.Metrics?.map(metric => metric.Dimensions?.find(dim => dim.Name === "TableName")?.Value ).filter(Boolean) as string[]; // 为每个表创建告警 tableNames.forEach(tableName => { new cloudwatch.Alarm(this, `Table-Alarm-${tableName}`, { metric: new cloudwatch.Metric({ namespace: "Your-Namespace", metricName: "Your-Metric-Name", dimensionsMap: { TableName: tableName }, statistic: "Average", period: cdk.Duration.minutes(5), }), threshold: 100, // 替换为你的告警阈值 evaluationPeriods: 2, comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, alarmDescription: `表${tableName}的指标超过阈值`, // 可添加告警动作,如SNS Topic // alarmActions: [new cloudwatch.SnsAction(yourSnsTopic)] }); }); } }
注意事项
- 执行CDK synth/deploy的环境需要有
cloudwatch:ListMetrics权限; - 新表的指标需要先被CloudWatch采集到,才会出现在
list-metrics结果中,新增表后需要重新运行CDK部署才能生成对应告警; - 所有告警会被纳入CDK的基础设施管理,可通过
cdk diff查看变更。
方案二:运行时动态创建告警(自动发现新表)
如果希望新增表无需修改或重新部署CDK代码,可以用Lambda+EventBridge实现定期同步:Lambda调用list-metrics获取最新维度,动态创建/更新CloudWatch告警。
1. Lambda代码(Python)
import boto3 import os cw = boto3.client('cloudwatch') def lambda_handler(event, context): namespace = os.environ['NAMESPACE'] metric_name = os.environ['METRIC_NAME'] threshold = float(os.environ['ALARM_THRESHOLD']) # 获取所有带TableName维度的指标 response = cw.list_metrics( Namespace=namespace, MetricName=metric_name, Dimensions=[{'Name': 'TableName'}] ) # 提取并去重表名 table_names = set() for metric in response['Metrics']: for dim in metric['Dimensions']: if dim['Name'] == 'TableName': table_names.add(dim['Value']) # 为每个表创建或更新告警 for table_name in table_names: alarm_name = f"Table-Alarm-{table_name}" cw.put_metric_alarm( AlarmName=alarm_name, AlarmDescription=f"表{table_name}的指标超过阈值", Namespace=namespace, MetricName=metric_name, Dimensions=[{'Name': 'TableName', 'Value': table_name}], Statistic='Average', Period=300, # 5分钟 EvaluationPeriods=2, Threshold=threshold, ComparisonOperator='GreaterThanThreshold', # 替换为你的告警目标,如SNS Topic ARN # AlarmActions=['arn:aws:sns:us-east-1:123456789012:your-topic'] ) return {'statusCode': 200, 'body': f"已处理{len(table_names)}个表的告警配置"}
2. CDK代码定义Lambda和EventBridge规则
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as events from 'aws-cdk-lib/aws-events'; import * as targets from 'aws-cdk-lib/aws-events-targets'; import * as iam from 'aws-cdk-lib/aws-iam'; export class DynamicAlarmSyncStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const alarmSyncLambda = new lambda.Function(this, 'AlarmSyncLambda', { runtime: lambda.Runtime.PYTHON_3_11, handler: 'index.lambda_handler', code: lambda.Code.fromAsset('lambda'), // 存放Lambda代码的目录 environment: { NAMESPACE: "Your-Namespace", METRIC_NAME: "Your-Metric-Name", ALARM_THRESHOLD: "100" } }); // 给Lambda授予必要权限 alarmSyncLambda.addToRolePolicy(new iam.PolicyStatement({ actions: ['cloudwatch:ListMetrics', 'cloudwatch:PutMetricAlarm'], resources: ['*'] })); // 配置每天凌晨执行一次同步 new events.Rule(this, 'DailyAlarmSyncRule', { schedule: events.Schedule.cron({ hour: '0', minute: '0' }), targets: [new targets.LambdaFunction(alarmSyncLambda)] }); } }
优缺点
- 优势:自动发现新表,无需重新部署CDK;告警配置随指标动态更新;
- 劣势:告警由Lambda动态创建,不在CDK的资源清单中,需要通过CloudWatch控制台或API查看管理。
内容的提问来源于stack exchange,提问作者Scooby
相关产品推荐
相关产品推荐

