You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pulumi中配置AWS OTEL容器并向Datadog传输数据

问题

我将Java代码打包在了steinko/helloworld-backend Docker容器中,需要把容器的日志、指标及追踪数据发送至Datadog。目前采用AWS Distro for OpenTelemetry容器作为边车,需通过config.yaml配置Datadog导出器,且已通过以下Pulumi代码将二者部署在ECS Fargate服务中:

export const service = new awsx.ecs.FargateService("backend", {
  taskDefinitionArgs: {  
    containers: {  
      otelCollector: {                                                                                                                                                     
        image:"docker.io/amazon/aws-otel-collector"
      },
      backend: { 
        image: 'steinko/helloworld-backend',
                                                                            
      },
      dependsOn: [ {
        containerName: "otelCollector",                                                                       
        condition: "START"
      } ]
    }
  }
});

请问如何在Pulumi代码中为docker.io/amazon/aws-otel-collector配置config.yaml文件?

解决方案

有两种常用方式可以在Pulumi中配置AWS OTel Collector的config.yaml:

方式一:通过环境变量直接传入配置内容

AWS OTel Collector支持通过AOT_CONFIG_CONTENT环境变量加载配置内容,无需挂载文件,适合配置内容不复杂的场景。

修改后的Pulumi代码

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";

// 从AWS Secrets Manager获取Datadog API密钥(替换为你的Secret ID)
const datadogApiKey = aws.secretsmanager.getSecretValue({
  secretId: "datadog-api-key",
}).then(secret => secret.secretString);

// 定义OTel Collector的配置内容
const otelConfig = pulumi.interpolate`receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
  prometheus:
    config:
      scrape_configs:
        - job_name: 'backend'
          scrape_interval: 15s
          static_configs:
            - targets: ['localhost:8080']
  awslogs:
    endpoint: 0.0.0.0:2818
    polling_interval: 10s

exporters:
  datadog:
    api_key: ${datadogApiKey}
    site: "datadoghq.com"
    metrics:
      resource_attributes_as_tags: true
    traces:
      resource_attributes_as_tags: true
    logs:
      service: "helloworld-backend"
      source: "java"

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [datadog]
    metrics:
      receivers: [otlp, prometheus]
      exporters: [datadog]
    logs:
      receivers: [awslogs]
      exporters: [datadog]
`;

export const service = new awsx.ecs.FargateService("backend", {
  taskDefinitionArgs: {
    containers: {
      otelCollector: {
        image: "docker.io/amazon/aws-otel-collector",
        // 传入配置内容和必要环境变量
        environment: [
          { name: "AOT_CONFIG_CONTENT", value: otelConfig },
          { name: "AWS_REGION", value: aws.config.region },
        ],
        // 暴露OTel Collector需要的端口
        portMappings: [
          { containerPort: 4317, protocol: "tcp" }, // OTLP gRPC
          { containerPort: 4318, protocol: "tcp" }, // OTLP HTTP
          { containerPort: 2818, protocol: "tcp" }, // AWS Logs接收端口
        ],
      },
      backend: {
        image: "steinko/helloworld-backend",
        // 配置Java应用将数据发送到OTel边车
        environment: [
          { name: "OTEL_EXPORTER_OTLP_ENDPOINT", value: "http://localhost:4318" },
          { name: "OTEL_SERVICE_NAME", value: "helloworld-backend" },
          { name: "OTEL_METRICS_EXPORTER", value: "otlp" },
          { name: "OTEL_TRACES_EXPORTER", value: "otlp" },
          { name: "OTEL_LOGS_EXPORTER", value: "otlp" },
        ],
        dependsOn: [
          {
            containerName: "otelCollector",
            condition: "START",
          },
        ],
      },
    },
  },
});

方式二:通过文件挂载配置文件

如果配置内容复杂,可将config.yaml作为Pulumi资源挂载到容器中:

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";

const datadogApiKey = aws.secretsmanager.getSecretValue({
  secretId: "datadog-api-key",
}).then(secret => secret.secretString);

const otelConfig = pulumi.interpolate`receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
  prometheus:
    config:
      scrape_configs:
        - job_name: 'backend'
          scrape_interval: 15s
          static_configs:
            - targets: ['localhost:8080']
  awslogs:
    endpoint: 0.0.0.0:2818
    polling_interval: 10s

exporters:
  datadog:
    api_key: ${datadogApiKey}
    site: "datadoghq.com"
    metrics:
      resource_attributes_as_tags: true
    traces:
      resource_attributes_as_tags: true
    logs:
      service: "helloworld-backend"
      source: "java"

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [datadog]
    metrics:
      receivers: [otlp, prometheus]
      exporters: [datadog]
    logs:
      receivers: [awslogs]
      exporters: [datadog]
`;

// 将配置内容转为Pulumi资产
const otelConfigAsset = new pulumi.asset.StringAsset(otelConfig);
const otelConfigVolume = awsx.ecs.Volume.fromAsset("otel-config", otelConfigAsset);

export const service = new awsx.ecs.FargateService("backend", {
  taskDefinitionArgs: {
    volumes: [otelConfigVolume],
    containers: {
      otelCollector: {
        image: "docker.io/amazon/aws-otel-collector",
        // 指定配置文件路径
        command: ["--config", "/etc/otel/config.yaml"],
        // 挂载配置文件到容器
        mountPoints: [
          {
            sourceVolume: otelConfigVolume.name,
            containerPath: "/etc/otel",
            readOnly: true,
          },
        ],
        environment: [
          { name: "AWS_REGION", value: aws.config.region },
        ],
        portMappings: [
          { containerPort: 4317, protocol: "tcp" },
          { containerPort: 4318, protocol: "tcp" },
          { containerPort: 2818, protocol: "tcp" },
        ],
      },
      backend: {
        image: "steinko/helloworld-backend",
        environment: [
          { name: "OTEL_EXPORTER_OTLP_ENDPOINT", value: "http://localhost:4318" },
          { name: "OTEL_SERVICE_NAME", value: "helloworld-backend" },
          { name: "OTEL_METRICS_EXPORTER", value: "otlp" },
          { name: "OTEL_TRACES_EXPORTER", value: "otlp" },
          { name: "OTEL_LOGS_EXPORTER", value: "otlp" },
        ],
        dependsOn: [
          {
            containerName: "otelCollector",
            condition: "START",
          },
        ],
      },
    },
  },
});
注意事项
  • 密钥安全:Datadog API密钥必须存储在AWS Secrets Manager等安全存储中,禁止硬编码在代码里。
  • 应用配置:确保Java应用已集成OpenTelemetry SDK,并配置将数据发送到OTel边车的地址(http://localhost:4318)。
  • 配置调整:根据应用实际的数据发送方式,调整receivers和pipelines配置,比如不需要的接收器可以删除。
  • 端口设置:OTel Collector的端口仅需在任务内部访问,无需暴露到外部负载均衡。

内容的提问来源于stack exchange,提问作者stein korsveien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:10:56