AWS XRay SDK не может прочитать переменные среды в контейнере docker - PullRequest
0 голосов
/ 10 марта 2020

AWS XRay - это сервис трассировки, который позволяет вам отслеживать запросы в распределенных системах и даже профилировать ваши сервисы. Не вдаваясь в подробности о том, как работает XRay, он в основном отслеживает вашу службу и отправляет данные о каждом запросе к службе через UDP демону, который собирает эти данные и отправляет их на AWS.

Этот демон, работающий локально или в EC2, является локальным по отношению к машине, на которой работает служба, и доступен через порт 2000. Это конфигурация по умолчанию для расположения хоста демона.

При работе в Kubernetes вам необходимо настроить демон для запуска на каждом узле. Согласно документации для настройки XRay с Kubernetes , вы можете переопределить значение по умолчанию, установив переменную среды AWS_XRAY_DAEMON_ADDRESS с требуемым хостом, или вы можете установить системную переменную JVM com.amazonaws.xray.emitters.daemonAddress. Об этом также говорится в документации SDK .

Из-за моего варианта использования и того, как мы обмениваемся конфигурациями в моей организации, я хотел бы использовать метод настройки среды. переменная.

В соответствии с документацией, мы устанавливаем его при развертывании через наши рулевые диаграммы:

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

Выполняя c вход в модуль, на котором запущена служба и работает printenv мы видим, что это значение успешно устанавливается при развертывании.


Проблема:

Когда 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]
        ...

Это означает, что AWS SDK не выбирает эту переменную среды, как предлагается в документации, а просто использует значение по умолчанию 127.0.0.1:2000.

Затем я покопался в коде 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()));
        }
    }

Итак Я подумал, может я не правильно установил переменную окружения? Поэтому я добавил журнал получения переменной среды при запуске службы и обнаружил, что JVM действительно может найти значение:

Код:

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

Вывод:

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

Насколько я могу судить, этот код точно соответствует тому, что должно выполняться AWS SDK, и, тем не менее, он никогда не выполняется и, если это так, результат не будет таким же, как в моих журналах.

Работая локально, я не могу воспроизвести эту проблему, так как она выбирает хост, который я дал из переменных локальной среды. Я также подтвердил, что код AWS SDK, вставленный выше, достигается при локальном запуске с использованием точек останова.

Есть идеи?


Фрагмент Gradle:

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'

    ...

}

Другая информация:

  • Запуск в Spring Boot v2.2.1
  • OpenJDK v11.0.4
  • Gradle v6.0.1

Другие попытки: - Я попытался установить переменную среды с помощью Dockerfile. Это имело тот же результат.

1 Ответ

0 голосов
/ 10 марта 2020

Оказывается, что сообщение в блоге , на которое я ссылался, не было хорошим сообщением в блоге. В этом примере они не указывают порт с хостом:

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

Изменение переменной среды для включения порта устранило проблему:

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