使用 AWS Cloud Development Kit (AWS CDK) 进行部署 - Amazon CloudWatch

使用 AWS Cloud Development Kit (AWS CDK) 进行部署

步骤 1:在账户中启用 Application Signals

如果您尚未在此账户中启用 Application Signals,则必须向 Application Signals 授予发现您的服务所需的权限。为此,请执行以下操作:您的账户只需执行一次该操作。

为您的应用程序启用 Application Signals
  1. 通过 https://console.aws.amazon.com/cloudwatch/ 打开 CloudWatch 控制台。

  2. 在导航窗格中,选择服务

  3. 选择开始发现您的服务

  4. 选中该复选框并选择开始发现服务

    首次在您的账户中完成此步骤会创建 AWSServiceRoleForCloudWatchApplicationSignals 服务相关角色。此角色授予 Application Signals 以下权限:

    • xray:GetServiceGraph

    • logs:StartQuery

    • logs:GetQueryResults

    • cloudwatch:GetMetricData

    • cloudwatch:ListMetrics

    • tag:GetResources

    有关该角色的更多信息,请参阅 CloudWatch Application Signals 的服务相关角色权限

步骤 2:创建 IAM 角色

您必须创建一个 IAM 角色。如果您已创建此角色,则可能需要向其添加权限。

  • ECS 任务角色 – 容器使用此角色运行。权限应是您的应用程序所需的任何权限,以及 CloudWatchAgentServerPolicy

有关创建 IAM 角色的更多信息,请参阅创建 IAM 角色

步骤 3:在 AWS CDK 中使用 CloudWatch 代理检测您的应用程序

要使用 AWS CDK 为 Amazon ECS 启用 Application Signals,请执行下文所述的步骤。本文档中的代码片段为 TypeScript 格式。有关其他特定语言的备选方案,请参阅 AWS CDK cloudwatch-agent 支持的编程语言

注意

本文档概况介绍了使用 AWS CDK 设置 Application Signals 的过程。请参阅 步骤 4:使用 CloudWatch 代理检测您的应用程序 以了解有关指定 MOUNT_VOLUME>、MOUNT_CONTAINER_PATH>、INIT_CONTAINER_COMMAND> 和 ENVIRONMENT_VARIABLES 的值的语言特定设置说明

使用 CloudWatch 代理检测您的应用程序
  1. 在应用程序任务定义中,指定一个绑定挂载。根据应用程序使用的语言替换 MOUNT_VOLUME。例如,对于 Java 使用 opentelemetry-auto-instrumentation。在接下来的步骤中,该卷将用于跨容器共享文件。您将在此过程的稍后阶段使用此绑定挂载:

    const taskDefinition = new ecs.FargateTaskDefinition(this, 'MyTaskDefinition', { ... volumes: [{ name: MOUNT_VOLUME, }] );
  2. 然后您需要添加 CloudWatch 代理。添加 CloudWatch 代理的方法有两种:挎斗策略和进程守护程序策略。要了解每种方法的优缺点,请参阅 使用自定义设置在 Amazon ECS 上启用 Application Signals 并选择适合您环境的方法。

    • 挎斗策略 – 在应用程序的任务定义中添加一个名为 ecs-cwagent 的新容器。将 $IMAGE 替换为 Amazon Elastic Container Registry 上最新 CloudWatch 容器映像的路径。有关更多信息,请参阅 Amazon ECR 上的 cloudwatch-agent

      const cwAgentContainer = taskDefinition.addContainer('ecs-cwagent', { image: ecs.ContainerImage.fromRegistry("$IMAGE"), environment: { CW_CONFIG_CONTENT: '{"agent": {"debug": true}, "traces": {"traces_collected": {"application_signals": {"enabled": true}}}, "logs": {"metrics_collected": {"application_signals": {"enabled": true}}}}', }, logging: new ecs.AwsLogDriver({ streamPrefix: 'ecs', logGroup: new logs.LogGroup(this, 'CwAgentLogGroup', { logGroupName: '/ecs/ecs-cwagent', }), }), });
    • 进程守护程序策略 – 在堆栈中创建一个名为 ecs-cwagent 的新服务。请将 $TASK_ROLE_ARN$EXECUTION_ROLE_ARN 替换为您在 步骤 2:创建 IAM 角色 中准备的 IAM 角色。将 $IMAGE 替换为 Amazon Elastic Container Registry 上最新 CloudWatch 容器映像的路径。有关更多信息,请参阅 Amazon ECR 上的 cloudwatch-agent

      注意

      进程守护程序服务会公开主机上的两个端口,其中端口 4316 用作接收指标和跟踪的端点,端口 2000 用作 CloudWatch 跟踪采样器端点。此设置将允许代理从在主机上运行的所有应用程序任务收集和传输遥测数据。确保主机上的其他服务不使用这些端口,以免发生冲突。

      const cwAgentTaskDefinition = new ecs.Ec2TaskDefinition(this, 'CwAgentDaemonTaskDef', { taskRole: "$TASK_ROLE_ARN", executionRole: "$EXECUTION_ROLE_ARN", }); // Add the CloudWatch agent container const cwAgentContainer = cwAgentTaskDefinition.addContainer('ecs-cwagent', { image: ecs.ContainerImage.fromRegistry("$IMAGE"), cpu: 128, memoryLimitMiB: 64, portMappings: [ { containerPort: 4316, hostPort: 4316, }, { containerPort: 2000, hostPort: 2000, }, ], logging: new ecs.AwsLogDriver({ streamPrefix: 'ecs', logGroup: new logs.LogGroup(this, 'CwAgentLogGroup', { logGroupName: '/ecs/ecs-cwagent-daemon', }), }), environment: { CW_CONFIG_CONTENT: '{"agent": {"debug": true}, "traces": {"traces_collected": {"application_signals": {"enabled": true}}}, "logs": {"metrics_collected": {"application_signals": {"enabled": true}}}}', }, }); // Add the CloudWatch agent service running as a daemon const cwAgentService = new ecs.Ec2Service(this, 'CwAgentDaemonService', { cluster, taskDefinition: cwAgentTaskDefinition, daemon: true, });
  3. 在应用程序的任务定义中添加一个新容器 init。将 $IMAGE 替换为 AWS Distro for OpenTelemetry Amazon ECR 映像存储库中的最新映像。根据应用程序使用的语言替换 MOUNT_CONTAINER_PATHINIT_CONTAINER_COMMAND

    例如,对于 Java 使用 INIT_CONTAINER_COMMAND=["cp", "/javaagent.jar", "/otel-auto-instrumentation/javaagent.jar"], MOUNT_CONTAINER_PATH='/otel-auto-instrumentation'

    const initContainer = taskDefinition.addContainer('init', { image: ecs.ContainerImage.fromRegistry("$IMAGE"), essential: false, command: INIT_CONTAINER_COMMAND }); initContainer.addMountPoints({ sourceVolume: MOUNT_VOLUME, containerPath: MOUNT_CONTAINER_PATH, readOnly: false });
  4. 根据应用程序使用的语言,将环境变量 ENVIRONMENT_VARIABLES 添加到您的应用程序容器中。然后将卷 MOUNT_VOLUME 挂载到该应用程序容器。

    注意

    有关指定 MOUNT_VOLUME>、MOUNT_CONTAINER_PATH>、INIT_CONTAINER_COMMAND> 和 ENVIRONMENT_VARIABLES 的值的语言特定设置说明,请参阅 步骤 4:使用 CloudWatch 代理检测您的应用程序

    以下是示例:

    const appContainer = taskDefinition.addContainer('my-app', { ... environment: { ... ENVIRONMENT_VARIABLES }, }); appContainer.addMountPoints({ sourceVolume: MOUNT_VOLUME, containerPath: MOUNT_CONTAINER_PATH, readOnly: false });

设置采用 ESM 模块格式的 Node.js 应用程序

我们对采用 ESM 模块格式的 Node.js 应用程序提供有限的支持。有关详细信息,请参阅使用 ESM 的 Node.js 的已知限制

对于 ESM 模块格式,通过使用 init 容器注入 Node.js 检测 SDK 启用 Application Signals 不适用。跳过之前程序的步骤 1 和 3,改为执行以下操作。

为使用 ESM 的 Node.js 应用程序启用 Application Signals
  1. 将相关依赖项安装到您的 Node.js 应用程序中以进行自动检测:

    npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation npm install @opentelemetry/instrumentation@0.54.0
  2. 在之前程序的步骤 4 中,删除卷的挂载:

    appContainer.addMountPoints({ sourceVolume: MOUNT_VOLUME, containerPath: MOUNT_CONTAINER_PATH, readOnly: false });

    将环境变量 NODE_OPTIONS 设置为 --import @aws/aws-distro-opentelemetry-node-autoinstrumentation/register --experimental-loader=@opentelemetry/instrumentation/hook.mjs

步骤 4:部署更新后的堆栈

在应用程序的主目录中运行 cdk synth 命令。要在您的 AWS 账户中部署服务,请在应用程序的主目录中运行 cdk deploy 命令。

如果您使用的是挎斗策略,则会看到创建了一个服务:

  • APPLICATION_SERVICE 是您应用程序的服务。该服务包含以下三个容器:

    • init – Application Signals 初始化所必需的容器。

    • ecs-cwagent – 运行 CloudWatch 代理的容器

    • my-app – 这是我们文档中的示例应用程序容器。在实际工作负载中,此特定的容器可能不存在,或者可能被您自己的服务容器所取代。

如果您使用的是进程守护程序策略,则会看到创建了两个服务:

  • CWAgentDaemonService 是 CloudWatch 代理进程守护程序服务。

  • APPLICATION_SERVICE 是您应用程序的服务。该服务包含以下两个容器:

    • init – Application Signals 初始化所必需的容器。

    • my-app – 这是我们文档中的示例应用程序容器。在实际工作负载中,此特定的容器可能不存在,或者可能被您自己的服务容器所取代。