AWS CDK를 사용하여 Amazon ECS에서 Application Signals 활성화
AWS CDK를 사용하여 Amazon ECS에서 Application Signals를 활성화하려면 다음을 수행합니다.
애플리케이션에 대해 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 에이전트로 애플리케이션을 계측합니다. 다음은 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에서만 지원됩니다.
CloudWatch Agent를
HOST네트워크 모드의 대몬 서비스로 실행합니다.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 Agent 서비스를 실행하려면 다른 서비스와 통신할 수 있는 특정 보안 그룹 구성이 필요합니다. Application Signals 기능의 경우 최소 인바운드 규칙인 포트 2000(HTTP) 및 포트 4316(HTTP)으로 보안 그룹을 구성합니다. 이 구성에서는 CloudWatch 에이전트와 종속 서비스 간의 적절한 연결이 확보됩니다.
서비스 연결을 통해 CloudWatch Agent를 복제본 서비스로 실행합니다.
instrumentation를 구성하여 ADOT Python 에이전트로 애플리케이션을 계측합니다.Service Connect 연결 엔드포인트를 사용하여 CloudWatch 에이전트 서버와 통신하도록
overrideEnvironments를 구성하여 환경 변수를 재정의합니다.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 애플리케이션은 제한적으로 지원됩니다. 자세한 내용은 ESM 사용 Node.js에 대해 알려진 제한 사항을 참조하세요.
ESM 모듈 형식의 경우
init컨테이너를 사용한 Application Signals 활성화를 통한 Node.js 계측 SDK 주입에는 해당되지 않습니다. 이 절차의 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