简体   繁体   English

AWS XRay SDK 无法读取 docker 容器内的环境变量

[英]AWS XRay SDK fails to read environment variables within a docker container

AWS XRay is a tracing service that allows you to trace requests in distributed systems, and even profile your services. AWS XRay 是一种跟踪服务,可让您跟踪分布式系统中的请求,甚至分析您的服务。 Without going too much in to how XRay works, it basically monitors your service and sends data about each request to the service via UDP to a daemon that collects this data and sends it to AWS.无需过多介绍 XRay 的工作原理,它基本上会监控您的服务,并通过 UDP 将有关每个对服务的请求的数据发送到收集这些数据并将其发送到 AWS 的守护进程。

This daemon, when running locally or in EC2, is local to the machine the service is running on and is available on port 2000. This is the default configuration for the location of the daemon host.该守护进程在本地运行或在 EC2 中运行时,对于运行该服务的机器来说是本地的,并且在端口 2000 上可用。这是守护进程主机位置的默认配置。

When running in Kubernetes, you need to set up a daemon to run on each node.在Kubernetes中运行时,需要设置一个守护进程在每个节点上运行。 As per the documentation for setting up XRay with Kubernetes , you can override the default value by setting an environment variable AWS_XRAY_DAEMON_ADDRESS with the required host, or you can set a JVM system variable com.amazonaws.xray.emitters.daemonAddress .根据使用 Kubernetes 设置 XRay文档,您可以通过使用所需主机设置环境变量AWS_XRAY_DAEMON_ADDRESS来覆盖默认值,或者您可以设置 JVM 系统变量com.amazonaws.xray.emitters.daemonAddress There is also a reference to this in the SDK documentation . SDK 文档中也有对此的引用。

Due to my use case, and how we share configurations in my organisation, I would like to utilise the method of setting the environment variable.由于我的用例,以及我们如何在我的组织中共享配置,我想利用设置环境变量的方法。

As per the documentation, we set it on deployment via our helm charts:根据文档,我们通过 helm charts 在部署时设置它:

env:
  - name: AWS_XRAY_DAEMON_ADDRESS
    value: aws-xray-daemon.default

By exec'ing in to the pod the service is running on, and running printenv we can see that this value is successfully set upon deployment.通过执行到正在运行服务的 pod,并运行printenv我们可以看到该值在部署时已成功设置。


The Issue:问题:

When XRay tries to profile and send data to the daemon, an SdkClientException is thrown:当 XRay 尝试分析并将数据发送到守护程序时,会抛出SdkClientException

com.amazonaws.SdkClientException: Unable to execute HTTP request: Connect to 127.0.0.1:2000 [/127.0.0.1] failed: Connection refused (Connection refused)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleRetryableException(AmazonHttpClient.java:1201) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1147) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:796) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:764) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:738) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:698) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:680) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:544) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:524) ~[aws-java-sdk-core-1.11.739.jar!/:na]
        at com.amazonaws.services.xray.AWSXRayClient.doInvoke(AWSXRayClient.java:1607) ~[aws-java-sdk-xray-1.11.739.jar!/:na]
        at com.amazonaws.services.xray.AWSXRayClient.invoke(AWSXRayClient.java:1574) ~[aws-java-sdk-xray-1.11.739.jar!/:na]
        at com.amazonaws.services.xray.AWSXRayClient.invoke(AWSXRayClient.java:1563) ~[aws-java-sdk-xray-1.11.739.jar!/:na]
        at com.amazonaws.services.xray.AWSXRayClient.executeGetSamplingRules(AWSXRayClient.java:800) ~[aws-java-sdk-xray-1.11.739.jar!/:na]
        at com.amazonaws.services.xray.AWSXRayClient.getSamplingRules(AWSXRayClient.java:771) ~[aws-java-sdk-xray-1.11.739.jar!/:na]
        at com.amazonaws.xray.strategy.sampling.pollers.RulePoller.pollRule(RulePoller.java:65) ~[aws-xray-recorder-sdk-core-2.4.0.jar!/:na]
        at com.amazonaws.xray.strategy.sampling.pollers.RulePoller.lambda$start$0(RulePoller.java:46) ~[aws-xray-recorder-sdk-core-2.4.0.jar!/:na]
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
        at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
        ...

This means that the AWS SDK is not picking up this environment variable as the documentation suggest, and just uses the default value of 127.0.0.1:2000 .这意味着 AWS 开发工具包没有像文档建议的那样选择这个环境变量,而只是使用默认值127.0.0.1:2000

I then went for a dig in to the SDK code as to find how it goes about retrieving this variable and found that the code that runs it uses System.getenv("AWS_XRAY_DAEMON_ADDRESS") as shown below:然后我深入研究了 SDK 代码,以了解它如何检索此变量,并发现运行它的代码使用System.getenv("AWS_XRAY_DAEMON_ADDRESS") ,如下所示:

    /**
     * Environment variable key used to override the address to which UDP packets will be emitted. Valid values are of the form `ip_address:port`. Takes precedence over any system property,
     * constructor value, or setter value used.
     */
    public static final String DAEMON_ADDRESS_ENVIRONMENT_VARIABLE_KEY = "AWS_XRAY_DAEMON_ADDRESS";

    /**
     * System property key used to override the address to which UDP packets will be emitted. Valid values are of the form `ip_address:port`. Takes precedence over any constructor or setter value
     * used.
     */
    public static final String DAEMON_ADDRESS_SYSTEM_PROPERTY_KEY = "com.amazonaws.xray.emitters.daemonAddress";

    public DaemonConfiguration() {
        String environmentAddress = System.getenv(DAEMON_ADDRESS_ENVIRONMENT_VARIABLE_KEY);
        String systemAddress = System.getProperty(DAEMON_ADDRESS_SYSTEM_PROPERTY_KEY);

        if (setUDPAndTCPAddress(environmentAddress)) {
            logger.info(String.format("Environment variable %s is set. Emitting to daemon on address %s.", DAEMON_ADDRESS_ENVIRONMENT_VARIABLE_KEY, getUDPAddress()));
        } else if (setUDPAndTCPAddress(systemAddress)) {
            logger.info(String.format("System property %s is set. Emitting to daemon on address %s.", DAEMON_ADDRESS_SYSTEM_PROPERTY_KEY, getUDPAddress()));
        }
    }

So I thought, maybe I haven't set the environment variable properly?所以我想,也许我没有正确设置环境变量? So I added a log of the retrieval of the environment variable upon start up of the service, and found that the JVM can indeed find the value:于是我在服务启动时添加了检索环境变量的日志,发现JVM确实可以找到该值:

Code:代码:

System.out.println("System.getenv(\"AWS_XRAY_DAEMON_ADDRESS\")" + " = " + System.getenv("AWS_XRAY_DAEMON_ADDRESS")) 

Output:输出:

System.getenv("AWS_XRAY_DAEMON_ADDRESS") = aws-xray-daemon.default

As far as I can tell, this code matches exactly what should be run by the AWS SDK, and yet it never seems to be executed, and if it is, it doesn't have the same outcome as what i've tested with my logs.据我所知,这段代码与 AWS SDK 应该运行的代码完全匹配,但它似乎从未被执行过,如果是,它的结果与我用我的测试过的结果不同日志。

Running locally, I am unable to replicate this issue, as it picks up the host i've given from my local environment variables.在本地运行,我无法复制此问题,因为它会从我的本地环境变量中获取我提供的主机。 I have also confirmed that the AWS SDK code pasted above is reached when running locally by using breakpoints.我还确认在使用断点在本地运行时达到了上面粘贴的 AWS SDK 代码。

Any ideas?有任何想法吗?


Gradle Snippet:摇篮片段:

ext {
    ...
    springCloudVersion = "Greenwich.RELEASE"
    awsCoreVersion = '1.11.739'
    awsXrayVersion = '2.4.0' 
    ...
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        mavenBom "com.amazonaws:aws-java-sdk-bom:${awsCoreVersion}"
        mavenBom "com.amazonaws:aws-xray-recorder-sdk-bom:${awsXrayVersion}"
    }
}

dependencies {
    ...

    implementation "com.amazonaws:aws-java-sdk-core"
    implementation "com.amazonaws:aws-xray-recorder-sdk-core" 
    implementation "com.amazonaws:aws-xray-recorder-sdk-aws-sdk" 
    implementation "com.amazonaws:aws-xray-recorder-sdk-spring" 
    implementation "com.amazonaws:aws-xray-recorder-sdk-apache-http" 
    implementation "com.amazonaws:aws-xray-recorder-sdk-sql-postgres" 

    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-security'

    ...

}

Other info:其他信息:

  • Running in Spring Boot v2.2.1在 Spring Boot v2.2.1 中运行
  • OpenJDK v11.0.4 OpenJDK v11.0.4
  • Gradle v6.0.1摇篮 v6.0.1

Other attempts: - I have tried setting the environment variable via the Dockerfile .其他尝试: - 我尝试通过Dockerfile设置环境变量。 This had the same outcome.这有同样的结果。

Turns out that the blog post I linked was not a good blog post.事实证明,我链接的博客文章不是一篇好的博客文章。 In the example they don't specify the port with the host:在示例中,他们没有指定主机的端口:

env:
- name: AWS_XRAY_DAEMON_ADDRESS 
  value: xray-service.default

Changing the environment variable to include the port fixed the issue:更改环境变量以包含端口修复了问题:

env:
- name: AWS_XRAY_DAEMON_ADDRESS 
  value: xray-service.default:2000

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AWS SDK 无法读取环境变量 - AWS SDK can not read environment variables api 无法将跟踪发送到 docker 容器中的 aws-xray deamon - api unable to send the traces to aws-xray deamon in docker container 在 Intellij 中运行 Java 应用程序时无法读取 AWS SDK 的环境变量 - Cannot read environment variables for AWS SDK while running Java application in Intellij Docker将db容器与spring boot连接起来并获取环境变量 - Docker linking db container with spring boot and get environment variables 使用 Quarkus 的 AWS XRay - AWS XRay with Quarkus 如何为运行 Java 应用程序的多 docker 容器 AWS Elastic Beanstalk 环境动态分配内存 - How to dynamically allocate memory to multi-docker container AWS Elastic Beanstalk environment running Java applications AWS SDK 无法通过区域提供商链从 docker 容器中找到区域 - AWS SDK Unable to find a region via the region provider chain from docker container 使用 gradle 任务构建映像时,无法在 docker 容器内设置环境变量 - Not able to set environment variables inside a docker container when building image using gradle task Docker + Tomcat + .properties - 环境变量 - Docker + Tomcat + .properties — Environment Variables Docker重新启动-保留环境变量 - Docker Restart - Keep Environment Variables
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM