Habilitar o Application Signals no Amazon ECC usando o AWS CDK - Amazon CloudWatch

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:

  1. 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.

  2. 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

      1. Configure instrumentation para 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.

      2. Especifique cloudWatchAgentSidecar para 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.

      1. Execute o agente do CloudWatch como um serviço daemon com o modo de rede HOST.

      2. Configure instrumentation para 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.

      1. Execute o agente do CloudWatch como um serviço de réplica com conexão de serviço.

      2. Configure instrumentation para instrumentalizar a aplicação com o agente do Python do ADOT.

      3. Substitua as variáveis de ambiente ao configurar overrideEnvironments para 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, }); } }
  3. 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 init para 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.

      1. Adicione uma configuração adicional ao contêiner da aplicação.

      2. Configure o NODE_OPTIONS.

      3. (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, }); }
  4. Implantar a pilha atualizada: execute o comando cdk synth no diretório principal da aplicação. Para implantar o serviço na sua conta da AWS, execute o comando cdk deploy no 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

      • my-app: 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.

    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.

      • my-app: 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.

    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.

      • my-app: 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.