使用 在 Amazon ECS 上啟用 Application Signals AWS CDK - Amazon CloudWatch

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 在 Amazon ECS 上啟用 Application Signals AWS CDK

若要使用 在 Amazon ECS 上啟用 Application Signals AWS CDK,請執行下列動作。

  1. 為您的應用程式啟用 Application Signals – 如果您尚未在此帳戶中啟用 Application Signals,您必須授予 Application Signals 探索服務所需的許可。

    import { aws_applicationsignals as applicationsignals } from 'aws-cdk-lib'; const cfnDiscovery = new applicationsignals.CfnDiscovery(this, 'ApplicationSignalsServiceRole', { } );

    Discovery CloudFormation 資源會授予 Application Signals 下列許可:

    • xray:GetServiceGraph

    • logs:StartQuery

    • logs:GetQueryResults

    • cloudwatch:GetMetricData

    • cloudwatch:ListMetrics

    • tag:GetResources

    如需有關此角色的詳細資訊,請參閱 CloudWatch Application Signals 的服務連結角色許可

  2. 使用 AWS CDK 中的 AWS::ApplicationSignals 建構程式庫來檢測您的應用程式。本文件中的程式碼片段提供於 TypeScript。如需其他特定語言的替代方案,請參閱 AWS CDK 支援的程式設計語言

    • 使用附屬模式在 Amazon ECS 上啟用 Application Signals

      1. 設定 instrumentation以使用 AWS Distro for OpenTelemetry (ADOT) SDK Agent 檢測應用程式。以下是檢測 Java 應用程式的範例。如需所有支援的語言版本,請參閱 InstrumentationVersion

      2. 指定 將 CloudWatch Agent cloudWatchAgentSidecar設定為附屬容器。

        import { Construct } from 'constructs'; import * as appsignals from '@aws-cdk/aws-applicationsignals-alpha'; import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as ecs from 'aws-cdk-lib/aws-ecs'; class MyStack extends cdk.Stack { public constructor(scope?: Construct, id?: string, props: cdk.StackProps = {}) { super(); const vpc = new ec2.Vpc(this, 'TestVpc', {}); const cluster = new ecs.Cluster(this, 'TestCluster', { vpc }); const fargateTaskDefinition = new ecs.FargateTaskDefinition(this, 'SampleAppTaskDefinition', { cpu: 2048, memoryLimitMiB: 4096, }); fargateTaskDefinition.addContainer('app', { image: ecs.ContainerImage.fromRegistry('test/sample-app'), }); new appsignals.ApplicationSignalsIntegration(this, 'ApplicationSignalsIntegration', { taskDefinition: fargateTaskDefinition, instrumentation: { sdkVersion: appsignals.JavaInstrumentationVersion.V2_10_0, }, serviceName: 'sample-app', cloudWatchAgentSidecar: { containerName: 'ecs-cwagent', enableLogging: true, cpu: 256, memoryLimitMiB: 512, } }); new ecs.FargateService(this, 'MySampleApp', { cluster: cluster, taskDefinition: fargateTaskDefinition, desiredCount: 1, }); } }
    • 使用常駐程式模式在 Amazon ECS 上啟用 Application Signals

      注意

      Amazon ECS Fargate 不支援協助程式部署策略,且僅支援 Amazon ECS on Amazon EC2。

      1. HOST網路模式執行 CloudWatch Agent 做為協助程式服務。

      2. 設定 instrumentation以使用 ADOT Python Agent 檢測應用程式。

        import { Construct } from 'constructs'; import * as appsignals from '@aws-cdk/aws-applicationsignals-alpha'; import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as ecs from 'aws-cdk-lib/aws-ecs'; class MyStack extends cdk.Stack { public constructor(scope?: Construct, id?: string, props: cdk.StackProps = {}) { super(scope, id, props); const vpc = new ec2.Vpc(this, 'TestVpc', {}); const cluster = new ecs.Cluster(this, 'TestCluster', { vpc }); // Define Task Definition for CloudWatch agent (Daemon) const cwAgentTaskDefinition = new ecs.Ec2TaskDefinition(this, 'CloudWatchAgentTaskDefinition', { networkMode: ecs.NetworkMode.HOST, }); new appsignals.CloudWatchAgentIntegration(this, 'CloudWatchAgentIntegration', { taskDefinition: cwAgentTaskDefinition, containerName: 'ecs-cwagent', enableLogging: false, cpu: 128, memoryLimitMiB: 64, portMappings: [ { containerPort: 4316, hostPort: 4316, }, { containerPort: 2000, hostPort: 2000, }, ], }); // Create the CloudWatch Agent daemon service new ecs.Ec2Service(this, 'CloudWatchAgentDaemon', { cluster, taskDefinition: cwAgentTaskDefinition, daemon: true, // Runs one container per EC2 instance }); // Define Task Definition for user application const sampleAppTaskDefinition = new ecs.Ec2TaskDefinition(this, 'SampleAppTaskDefinition', { networkMode: ecs.NetworkMode.HOST, }); sampleAppTaskDefinition.addContainer('app', { image: ecs.ContainerImage.fromRegistry('test/sample-app'), cpu: 0, memoryLimitMiB: 512, }); // No CloudWatch Agent sidecar is needed as application container communicates to CloudWatch Agent daemon through host network new appsignals.ApplicationSignalsIntegration(this, 'ApplicationSignalsIntegration', { taskDefinition: sampleAppTaskDefinition, instrumentation: { sdkVersion: appsignals.PythonInstrumentationVersion.V0_8_0 }, serviceName: 'sample-app' }); new ecs.Ec2Service(this, 'MySampleApp', { cluster, taskDefinition: sampleAppTaskDefinition, desiredCount: 1, }); } }
    • 使用複本模式在 Amazon ECS 上啟用 Application Signals

      注意

      使用複本模式執行 CloudWatch Agent 服務需要特定的安全群組組態,才能與其他 服務通訊。對於 Application Signals 功能,使用最低傳入規則設定安全群組:連接埠 2000 (HTTP) 和連接埠 4316 (HTTP)。此組態可確保 CloudWatch Agent 與相依服務之間的適當連線。

      1. 執行 CloudWatch Agent 做為具有服務連線的複本服務。

      2. 設定 instrumentation以使用 ADOT Python Agent 檢測應用程式。

      3. 將 設定為overrideEnvironments使用服務連線端點與 CloudWatch 代理程式伺服器通訊,以覆寫環境變數。

        import { Construct } from 'constructs'; import * as appsignals from '@aws-cdk/aws-applicationsignals-alpha'; import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import { PrivateDnsNamespace } from 'aws-cdk-lib/aws-servicediscovery'; class MyStack extends cdk.Stack { public constructor(scope?: Construct, id?: string, props: cdk.StackProps = {}) { super(scope, id, props); const vpc = new ec2.Vpc(this, 'TestVpc', {}); const cluster = new ecs.Cluster(this, 'TestCluster', { vpc }); const dnsNamespace = new PrivateDnsNamespace(this, 'Namespace', { vpc, name: 'local', }); const securityGroup = new ec2.SecurityGroup(this, 'ECSSG', { vpc }); securityGroup.addIngressRule(securityGroup, ec2.Port.tcpRange(0, 65535)); // Define Task Definition for CloudWatch agent (Replica) const cwAgentTaskDefinition = new ecs.FargateTaskDefinition(this, 'CloudWatchAgentTaskDefinition', {}); new appsignals.CloudWatchAgentIntegration(this, 'CloudWatchAgentIntegration', { taskDefinition: cwAgentTaskDefinition, containerName: 'ecs-cwagent', enableLogging: false, cpu: 128, memoryLimitMiB: 64, portMappings: [ { name: 'cwagent-4316', containerPort: 4316, hostPort: 4316, }, { name: 'cwagent-2000', containerPort: 2000, hostPort: 2000, }, ], }); // Create the CloudWatch Agent replica service with service connect new ecs.FargateService(this, 'CloudWatchAgentService', { cluster: cluster, taskDefinition: cwAgentTaskDefinition, securityGroups: [securityGroup], serviceConnectConfiguration: { namespace: dnsNamespace.namespaceArn, services: [ { portMappingName: 'cwagent-4316', dnsName: 'cwagent-4316-http', port: 4316, }, { portMappingName: 'cwagent-2000', dnsName: 'cwagent-2000-http', port: 2000, }, ], }, desiredCount: 1, }); // Define Task Definition for user application const sampleAppTaskDefinition = new ecs.FargateTaskDefinition(this, 'SampleAppTaskDefinition', {}); sampleAppTaskDefinition.addContainer('app', { image: ecs.ContainerImage.fromRegistry('test/sample-app'), cpu: 0, memoryLimitMiB: 512, }); // Overwrite environment variables to connect to the CloudWatch Agent service just created new appsignals.ApplicationSignalsIntegration(this, 'ApplicationSignalsIntegration', { taskDefinition: sampleAppTaskDefinition, instrumentation: { sdkVersion: appsignals.PythonInstrumentationVersion.V0_8_0, }, serviceName: 'sample-app', overrideEnvironments: [ { name: appsignals.CommonExporting.OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT, value: 'http://cwagent-4316-http:4316/v1/metrics', }, { name: appsignals.TraceExporting.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, value: 'http://cwagent-4316-http:4316/v1/traces', }, { name: appsignals.TraceExporting.OTEL_TRACES_SAMPLER_ARG, value: 'endpoint=http://cwagent-2000-http:2000', }, ], }); // Create ECS Service with service connect configuration new ecs.FargateService(this, 'MySampleApp', { cluster: cluster, taskDefinition: sampleAppTaskDefinition, serviceConnectConfiguration: { namespace: dnsNamespace.namespaceArn, }, desiredCount: 1, }); } }
  3. 使用 ESM 模組格式設定 Node.js 應用程式。ESM 模組格式的 Node.js 應用程式支援有限。如需詳細資訊,請參閱使用 ESM 的 Node.js 的已知限制

    對於 ESM 模組格式,使用init容器注入 Node.js 檢測 SDK 來啟用 Application Signals 不適用。略過此程序的步驟 2,並改為執行下列動作。

    • 將相關的相依性安裝到您的 Node.js 應用程式以進行自動檢測。

      npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation npm install @opentelemetry/instrumentation@0.54.
    • 更新 TaskDefinition。

      1. 將其他組態新增至您的應用程式容器。

      2. 設定 NODE_OPTIONS.

      3. (選用) 如果您選擇附屬模式,請新增 CloudWatch Agent。

        import { Construct } from 'constructs'; import * as appsignals from '@aws-cdk/aws-applicationsignals-alpha'; import * as ecs from 'aws-cdk-lib/aws-ecs'; class MyStack extends cdk.Stack { public constructor(scope?: Construct, id?: string, props: cdk.StackProps = {}) { super(scope, id, props); const fargateTaskDefinition = new ecs.FargateTaskDefinition(stack, 'TestTaskDefinition', { cpu: 256, memoryLimitMiB: 512, }); const appContainer = fargateTaskDefinition.addContainer('app', { image: ecs.ContainerImage.fromRegistry('docker/cdk-test'), }); const volumeName = 'opentelemetry-auto-instrumentation' fargateTaskDefinition.addVolume({name: volumeName}); // Inject additional configurations const injector = new appsignals.NodeInjector(volumeName, appsignals.NodeInstrumentationVersion.V0_5_0); injector.renderDefaultContainer(fargateTaskDefinition); // Configure NODE_OPTIONS appContainer.addEnvironment('NODE_OPTIONS', '--import @aws/aws-distro-opentelemetry-node-autoinstrumentation/register --experimental-loader=@opentelemetry/instrumentation/hook.mjs') // Optional: add CloudWatch agent const cwAgent = new appsignals.CloudWatchAgentIntegration(stack, 'AddCloudWatchAgent', { containerName: 'ecs-cwagent', taskDefinition: fargateTaskDefinition, memoryReservationMiB: 50, }); appContainer.addContainerDependencies({ container: cwAgent.agentContainer, condition: ecs.ContainerDependencyCondition.START, }); }
  4. 部署更新的堆疊 – 在應用程式的主目錄中執行 cdk synth命令。若要在 AWS 帳戶中部署服務,請在應用程式的主目錄中執行 cdk deploy命令。

    如果您使用附屬策略,您會看到已建立一項服務:

    • APPLICATION_SERVICE 是您應用程式的服務。它包含以下三個容器:

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

      • ecs-cwagent– 執行 CloudWatch 代理程式的容器

      • my-app– 這是我們文件中的範例應用程式容器。在您的實際工作負載中,此特定容器可能不存在,或者可能會取代為您自己的服務容器。

    如果您使用 協助程式策略,您會看到已建立兩個 服務:

    • CloudWatchAgentDaemon 是 CloudWatch 代理程式協助程式服務。

    • APPLICATION_SERVICE 是您應用程式的服務。它包含下列兩個容器:

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

      • my-app– 這是我們文件中的範例應用程式容器。在您的實際工作負載中,此特定容器可能不存在,或者可能會取代為您自己的服務容器。

    如果您使用複本策略,您會看到已建立兩個 服務:

    • CloudWatchAgentService 是 CloudWatch 代理程式複本服務。

    • APPLICATION_SERVICE 是您應用程式的服務。它包含下列兩個容器:

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

      • my-app– 這是我們文件中的範例應用程式容器。在您的實際工作負載中,此特定容器可能不存在,或者可能會取代為您自己的服務容器。