本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 在 Amazon ECS 上啟用 Application Signals AWS CDK
若要使用 在 Amazon ECS 上啟用 Application Signals AWS CDK,請執行下列動作。
為應用程式啟用 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 的服務連結角色許可。
-
使用 AWS CDK 中的 AWS::ApplicationSignals Construct Library
檢測您的應用程式。本文件內的程式碼片段在 TypeScript 中提供。如需其他特定語言的替代方案,請參閱 AWS CDK 支援的程式設計語言。 使用附屬程式模式在 Amazon ECS 上啟用 Application Signals
設定
instrumentation以使用 AWS Distro for OpenTelemetry (ADOT) SDK Agent 檢測應用程式。以下是檢測 Java 應用程式的範例。如需所有受支援的語言版本,請參閱 InstrumentationVersion。指定
cloudWatchAgentSidecar將 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'; 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 EC2 上的 Amazon ECS。
以
HOST網路模式執行 CloudWatch 代理程式,作為常駐程式服務。設定
instrumentation以使用 ADOT Python 代理程式檢測應用程式。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 代理程式服務需要特定的安全群組組態,才能與其他服務通訊。對於 Application Signals 功能,依最低傳入規則設定安全群組:連接埠 2000 (HTTP) 和連接埠 4316 (HTTP)。此組態可確保 CloudWatch 代理程式與相依服務之間建立正確的連線。
透過服務連線將 CloudWatch 代理程式作為複本服務執行。
設定
instrumentation以使用 ADOT Python 代理程式檢測應用程式。將
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, }); } }
設定採用 ESM 模組格式的 Node.js 應用程式。對於採用 ESM 模組格式的 Node.js 應用程式,我們提供的支援有限。如需詳細資訊,請參閱 Node.js 搭配使用 ESM 的已知限制。
對於 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。
將其他組態新增至您的應用程式容器。
設定
NODE_OPTIONS.(選用) 如果選擇附屬程式模式,新增 CloudWatch 代理程式。
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, }); }
部署更新的堆疊 – 在應用程式的主目錄中執行
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