[アップデート] Amazon CloudWatchが関連するテレメトリやリソース関係を可視化できるようになりました

[アップデート] Amazon CloudWatchが関連するテレメトリやリソース関係を可視化できるようになりました

Clock Icon2024.11.26

こんにちは。たかやまです。

Amazon CloudWatchが関連するテレメトリやリソースの関係を可視化することで、問題の根本原因をより迅速に特定し、運用効率を向上させることができるようになりました!

https://aws.amazon.com/jp/about-aws/whats-new/2024/11/amazon-cloudwatch-observability-data-consoles-analysis/

三行まとめ

  • CloudWatchで関連するテレメトリやリソースの関係を可視化できるようになった
  • AWSマネジメントコンソールの「Operational troubleshooting」タブからも利用可能
  • ネイティブに対応していないテレメトリについてはカスタムテレメトリとして追加も可能

やってみた

サンプルリソースとしてAuto ScalingするEC2インスタンスを作成します。
以下CDKサンプルコードです。

サンプルコード
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import * as autoscaling from 'aws-cdk-lib/aws-autoscaling';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';

class AutoScalingStack extends cdk.Stack {
  constructor(app: cdk.App, id: string, props?: cdk.StackProps) {
    super(app, id, props);

    const vpc = new ec2.Vpc(this, 'MyVPC', {
      maxAzs: 2,
      natGateways: 1,
    });
    (vpc.node.defaultChild as ec2.CfnVPC).overrideLogicalId('MyVPC');

    const albSecurityGroup = new ec2.SecurityGroup(this, 'ALBSecurityGroup', {
      vpc,
      description: 'Security group for ALB',
      allowAllOutbound: true,
      securityGroupName: 'my-alb-sg',
    });
    (albSecurityGroup.node.defaultChild as ec2.CfnSecurityGroup).overrideLogicalId('ALBSecurityGroup');

    albSecurityGroup.addIngressRule(
      ec2.Peer.anyIpv4(),
      ec2.Port.tcp(80),
      'Allow HTTP traffic'
    );

    const ec2SecurityGroup = new ec2.SecurityGroup(this, 'EC2SecurityGroup', {
      vpc,
      description: 'Security group for EC2 instances',
      allowAllOutbound: true,
      securityGroupName: 'my-ec2-sg',
    });
    (ec2SecurityGroup.node.defaultChild as ec2.CfnSecurityGroup).overrideLogicalId('EC2SecurityGroup');

    ec2SecurityGroup.addIngressRule(
      albSecurityGroup,
      ec2.Port.tcp(80),
      'Allow traffic from ALB'
    );

    const userData = ec2.UserData.forLinux();
    userData.addCommands(
      'yum update -y',
      'yum install -y httpd',
      'systemctl start httpd',
      'systemctl enable httpd',
      'echo "<html><body><h1>Hello from EC2</h1></body></html>" > /var/www/html/index.html',
      'chmod 644 /var/www/html/index.html'
    );

    const asg = new autoscaling.AutoScalingGroup(this, 'ASG', {
      vpc,
      vpcSubnets: {
        subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
      },
      securityGroup: ec2SecurityGroup,
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE4_GRAVITON, ec2.InstanceSize.MICRO),
      machineImage: ec2.MachineImage.latestAmazonLinux2023({
        cpuType: ec2.AmazonLinuxCpuType.ARM_64
      }),
      userData: userData,
      minCapacity: 2,
      maxCapacity: 4,
      desiredCapacity: 2,
      healthCheck: autoscaling.HealthCheck.elb({ grace: cdk.Duration.seconds(180) }),
      autoScalingGroupName: 'my-asg',
    });
    (asg.node.defaultChild as autoscaling.CfnAutoScalingGroup).overrideLogicalId('MyASG');

    const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', {
      vpc,
      internetFacing: true,
      securityGroup: albSecurityGroup,
      loadBalancerName: 'my-alb',
    });
    (lb.node.defaultChild as elbv2.CfnLoadBalancer).overrideLogicalId('MyALB');

    const listener = lb.addListener('Listener', {
      port: 80,
      defaultAction: elbv2.ListenerAction.fixedResponse(200, {
        contentType: 'text/plain',
        messageBody: 'OK',
      }),
    });
    (listener.node.defaultChild as elbv2.CfnListener).overrideLogicalId('MyALBListener');

    const targetGroup = listener.addTargets('Target', {
      port: 80,
      targets: [asg],
      targetGroupName: 'my-target-group',
      healthCheck: {
        path: '/',
        unhealthyThresholdCount: 2,
        healthyThresholdCount: 2,
        interval: cdk.Duration.seconds(15),
        timeout: cdk.Duration.seconds(10),
      },
      deregistrationDelay: cdk.Duration.seconds(30),
    });
    (targetGroup.node.defaultChild as elbv2.CfnTargetGroup).overrideLogicalId('MyTargetGroup');

    const requestCountPolicy = asg.scaleOnRequestCount('AModestLoad', {
      targetRequestsPerMinute: 60,
    });
    (requestCountPolicy.node.defaultChild as autoscaling.CfnScalingPolicy).overrideLogicalId('RequestCountScalingPolicy');

    const cpuPolicy = asg.scaleOnCpuUtilization('CpuScaling', {
      targetUtilizationPercent: 70,
      cooldown: cdk.Duration.seconds(300),
    });
    (cpuPolicy.node.defaultChild as autoscaling.CfnScalingPolicy).overrideLogicalId('CPUUtilizationScalingPolicy');

    new cdk.CfnOutput(this, 'LoadBalancerDNS', {
      value: lb.loadBalancerDnsName,
      description: 'The DNS name of the load balancer',
    }).overrideLogicalId('LoadBalancerDNS');
  }
}

const app = new cdk.App();
new AutoScalingStack(app, 'AutoScalingStack');
app.synth();

AWSマネジメントコンソールから確認する

こちらの機能は、AWSマネジメントコンソール全体に統合されています。

最初見た時どこにあるのだろうと探しましたが...
Amazon Qにならぶ形でOperational troubleshootingとしてタブにありました!

CleanShot 2024-11-26 at 19.46.37-1.png

開くと「リソースを検索」がでるので、こちらから検索していきます。

CleanShot 2024-11-26 at 19.48.14-1.png

リソースタグやインスタンスタイプで絞り込めるようなので、さきほどサンプルコードで作成したEC2を検索してみます。

すると、以下のようにトポロジーマップとして対象EC2とそれに関連するリソースが合わせて表示されました。

CleanShot 2024-11-26 at 19.59.46-1.png

その他情報としては、対象リソースの関連メトリクスやログも合わせて表示してくれるようです。
後述するCloudWatchからの検索方法ではメトリクスが表示されているので、AWSマネジメントコンソールからの呼び出しはまだ動作が安定していないのかもしれません。

リソースを見ているときに、このリソースがどのリソースと紐づいているだろうという際に活用できるかと思います。

CloudWatchから確認する

また、この機能はCloudWatchと連携して利用することができます。
個人的にこちらの使い方がとても便利だと感じました。

作成したAuto ScalingグループのCloudWatch Alarmを確認してみます。
こちらを確認すると 関連するものを詳しく見る というボタンが追加されていることがわかります。

CleanShot 2024-11-26 at 20.08.09-1.png

こちらを選択するとCloudWatch Alarmに紐づくリソースが自動で検索され、トポロジーマップとして表示されます。

CleanShot 2024-11-26 at 20.13.51-1.png

また、紐づくリソースを選択すると芋づる式に関連リソースが表示されます。

CleanShot 2024-11-26 at 20.18.52-1.png

CloudWatch Alarmが増えてくるとどのアラームがどのリソースと紐づいているのかわかりづらいことがありますが、そういった場合にこの機能を活用すると便利そうです。

また、Container Insightsなどの他のCloudWatch機能とも連携しているようなので、ぜひお使いのモニタリングツールの調査に活用いただければと思います。

CleanShot 2024-11-26 at 20.24.43-1.png

テレメトリ対象リソース

100を超えるAWSサービスを対象としてます。
リソースごとにメトリクス / ログを取得できるかは異なるので詳細は以下のリンクを参照してください。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/services-with-related-telemetry.html

カスタムテレメトリの追加

ネイティブに対応しているリソース以外にもカスタムテレメトリの形で追加することができます。

カスタムテレメトリとして登録したい情報について、メトリクスについてはPutMetricData、ログについてはPutLogEventsで登録することができます。

その際にKeyAttributesおよびAttributesを指定することで、リソースとの関連性を持たせることができます。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/adding-your-own-related-telemetry.html

また、CloudWatch AgentまたはEKSで追加テレメトリ情報を送る場合に以下のバージョン以上が対応となります。

  • CloudWatch Agent: 1.300049.1
  • EKS: v2.3.1-eksbuild.1 および CloudWatch Observability EKS アドオン

最後に

CloudWatchでの関連するテレメトリやリソースの関係の可視化に対応しました。

リソースマップだったり、可視化されることで困ることはないのでありがたいアップデートですね!
私も積極的に使っていきたいと思います。

このブログがどなたかの参考になれば幸いです。

以上、たかやま(@nyan_kotaroo)でした。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.