Habilitar o Application Signals no Amazon ECC usando o AWS CDK
Para habilitar o Application Signals no Amazon ECS usando o AWS CDK, faça o seguinte:
Habilitar o Application Signals para as aplicações: caso ainda não tenha habilitado o Application Signals nessa conta, você deve conceder as permissões necessárias para que o Application Signals descubra seus serviços.
import { aws_applicationsignals as applicationsignals } from 'aws-cdk-lib'; const cfnDiscovery = new applicationsignals.CfnDiscovery(this, 'ApplicationSignalsServiceRole', { } );O recurso Discovery CloudFormation concede as seguintes permissões ao Application Signals:
-
xray:GetServiceGraph -
logs:StartQuery -
logs:GetQueryResults -
cloudwatch:GetMetricData -
cloudwatch:ListMetrics -
tag:GetResources
Para obter mais informações sobre essa função, consulte Permissões de perfis vinculados ao serviço para o CloudWatch Application Signals.
-
Instrumentalize a aplicação com a AWS::ApplicationSignals Construct Library
no AWS CDK. Os trechos de código neste documento são fornecidos em TypeScript. Para outras alternativas específicas de linguagem, consulte Linguagens de programação suportadas para o AWS CDK. Habilitar o Application Signals no Amazon ECS usando o modo de arquivo associado
Configure
instrumentationpara instrumentalizar a aplicação com o Agente do SDK do AWS Distro para OpenTelemetry (ADOT). Veja a seguir um exemplo de instrumentação de uma aplicação Java. Consulte InstrumentationVersion para ver todas as versões de linguagens compatíveis.Especifique
cloudWatchAgentSidecarpara configurar o agente do CloudWatch como um contêiner de arquivo associado.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, }); } }
Habilitar o Application Signals no Amazon ECS usando o modo daemon
nota
A estratégia de implantação do daemon não é compatível com o Fargate para Amazon ECS, e só é compatível com o Amazon ECS no Amazon EC2.
Execute o agente do CloudWatch como um serviço daemon com o modo de rede
HOST.Configure
instrumentationpara instrumentalizar a aplicação com o agente do Python do ADOT.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, }); } }
Habilitar o Application Signals no Amazon ECS usando o modo de réplica
nota
A execução do serviço do agente do CloudWatch usando o modo de réplica exige configurações específicas de grupos de segurança para permitir a comunicação com outros serviços. Para a funcionalidade do Application Signals, configure o grupo de segurança com as regras mínimas de entrada: porta 2000 (HTTP) e porta 4316 (HTTP). Essa configuração garante a conectividade adequada entre o agente do CloudWatch e os serviços dependentes.
Execute o agente do CloudWatch como um serviço de réplica com conexão de serviço.
Configure
instrumentationpara instrumentalizar a aplicação com o agente do Python do ADOT.Substitua as variáveis de ambiente ao configurar
overrideEnvironmentspara usar endpoints de conexão de serviço para comunicação com o servidor do agente do 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, }); } }
Como configurar uma aplicação do Node.js usando o formato de módulo ESM. Existe um suporte limitado para aplicações do Node.js com o formato de módulo ESM. Para obter mais informações, consulte Limitações conhecidas sobre o uso de ESM com o Node.js.
No formato de módulo ESM, a habilitação do Application Signals ao usar o contêiner
initpara injetar o SDK de instrumentação do Node.js não é aplicável. Ignore a Etapa 2 deste procedimento e execute as ações apresentadas a seguir.Instale as dependências relevantes para a instrumentação automática na aplicação do Node.js.
npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation npm install @opentelemetry/instrumentation@0.54.Atualize TaskDefinition.
Adicione uma configuração adicional ao contêiner da aplicação.
Configure o
NODE_OPTIONS.(Opcional) Adicione o agente do CloudWatch se você escolher o modo de arquivo associado.
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, }); }
Implantar a pilha atualizada: execute o comando
cdk synthno diretório principal da aplicação. Para implantar o serviço na sua conta da AWS, execute o comandocdk deployno diretório principal da aplicação.Se você tiver usado a estratégia de arquivo associado, verá um serviço criado:
APPLICATION_SERVICEé o serviço da sua aplicação. Inclui os três seguintes contêineres:init: um contêiner necessário para inicializar o Application Signals.ecs-cwagent: um contêiner executando o agente do CloudWatch: esse é o exemplo de contêiner de aplicação na nossa documentação. Nas suas workloads reais, esse contêiner específico pode não existir ou pode ser substituído por seus próprios contêineres de serviço.my-app
Se você tiver usado a estratégia de daemon, verá dois serviços criados:
CloudWatchAgentDaemoné o serviço de daemon do agente do CloudWatch.APPLICATION_SERVICEé o serviço da sua aplicação. Inclui os dois seguintes contêineres:init: um contêiner necessário para inicializar o Application Signals.: esse é o exemplo de contêiner de aplicação na nossa documentação. Nas suas workloads reais, esse contêiner específico pode não existir ou pode ser substituído por seus próprios contêineres de serviço.my-app
Se você tiver usado a estratégia de réplica, verá dois serviços criados:
CloudWatchAgentServiceé o serviço de réplica do agente do CloudWatch.APPLICATION_SERVICEé o serviço da sua aplicação. Inclui os dois seguintes contêineres:init: um contêiner necessário para inicializar o Application Signals.: esse é o exemplo de contêiner de aplicação na nossa documentação. Nas suas workloads reais, esse contêiner específico pode não existir ou pode ser substituído por seus próprios contêineres de serviço.my-app