Spring Boot Admin с Docker Swarm Невозможно получить показатели здоровья - PullRequest
0 голосов
/ 31 декабря 2018

Я пытаюсь заставить администратора весенней загрузки работать в кластере Docker Swarm, используя механизм службы обнаружения zookeeper, чтобы обеспечить динамическое обнаружение всех клиентов после подключения к zookeeper.Проблема заключается в том, что администратор Springboot не может получить доступ к конечным точкам исполнительного механизма работоспособности на клиентах из-за отклоненного соединения, даже если все службы Docker используют одну и ту же оверлейную сеть, и каждый контейнер может пропинговать друг друга, что подтверждено с помощью Docker Exec.убедитесь, что все они доступны друг другу.

Я также проверил, что клиенты и службы администратора правильно подключаются к zookeeper и что панель управления zookeeper + admin фактически видит этих клиентов как зарегистрированных.

Чтобы воссоздать эту проблему, я создал простой докер-композитор, который развертывает два приложения админки с весенней загрузкой с активаторами в одной и той же оверлейной сети с помощью файла компоновки ниже:

version: '3.1'

services:
    zoo1:
        image: zookeeper:3.4.12
        hostname: zoo1
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda5v]
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888

    zoo2:
        image: zookeeper:3.4.12
        hostname: zoo2
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda6v]
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888

    nspadmin:
        image: admin:77
        ports:
            - "9084:8080"
        networks:
            - nsp_test
        depends_on:
            - "zoo1"
            - "zoo2"
        deploy:
            restart_policy:
                condition: on-failure
            mode: global
        environment:
            ZK_HOST: zoo1:2181,zoo2:2182
            SPRING_PROFILES_ACTIVE: ssldev
networks:
    nsp_test:
      external:
        name: nsp_test

Из этой конфигурацииЯ вижу обе панели администратора админки, зарегистрированные в zookeeper и отображаемые как OFFLINE (так как он не может достичь исполнительного элемента / health)

Следующие два адреса - это то, что он регистрирует для клиентов в SBA.https://10.255.0.19:8080/ OFFLINE https://10.255.0.20:8080/ OFFLINE

Исключение, которое я получаю.

2018-12-31 04:20:31.926  INFO 1 --- [    updateTask1] d.c.boot.admin.registry.StatusUpdater    : Couldn't retrieve status for Application [id=28eab1e1, name=nsp-admin, managementUrl=https://10.255.0.20:8080/, healthUrl=https://10.255.0.20:8080/health, serviceUrl=https://10.255.0.20:8080/]
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://10.255.0.20:8080/health": Connect to 10.255.0.20:8080 [/10.255.0.20] failed: connect timed out; nested exception is org.apache.http.conn.ConnectTimeoutException: Connect to 10.255.0.20:8080 [/10.255.0.20] failed: connect timed out
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:666) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:628) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:549) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at de.codecentric.boot.admin.web.client.ApplicationOperations.doGet(ApplicationOperations.java:68) ~[spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at de.codecentric.boot.admin.web.client.ApplicationOperations.getHealth(ApplicationOperations.java:58) ~[spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at de.codecentric.boot.admin.registry.StatusUpdater.queryStatus(StatusUpdater.java:111) [spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at de.codecentric.boot.admin.registry.StatusUpdater.updateStatus(StatusUpdater.java:65) [spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at de.codecentric.boot.admin.registry.StatusUpdateApplicationListener$1.run(StatusUpdateApplicationListener.java:47) [spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) [spring-context-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_151]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_151]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_151]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_151]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]
Caused by: org.apache.http.conn.ConnectTimeoutException: Connect to 10.255.0.20:8080 [/10.255.0.20] failed: connect timed out
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:151) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:89) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:652) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        ... 15 common frames omitted
Caused by: java.net.SocketTimeoutException: connect timed out
        at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_151]
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_151]
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_151]
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_151]
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_151]
        at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_151]
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:339) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) ~[httpclient-4.5.3.jar!/:4.5.3]

Моя конфигурация SBA yml

server:
  port: 8080
spring:
  boot:
    admin:
      client:
        prefer-ip: false
  datasource:
    driverClassName: org.postgresql.Driver
    url: ${DB_URL}
    username: ${DB_USER}
    password: ${DB_PASSWORD}
  application:
    name: nsp-admin
  cloud:
    config:
      discovery:
        enabled: true
    zookeeper:
      connect-string: ${ZK_HOST}
      discovery:
        uri-spec: https://{address}:{port}
        metadata:
          management:
            context-path: /
          health:
            path: /health

management:
  security:
    enabled: false

security:
  basic:
    enabled: false

#security.require-ssl: true
server.ssl.enabled: true
server.ssl.key-store-type: PKCS12
server.ssl.key-store: *****
server.ssl.key-store-password: *****

ОБНОВЛЕНИЕ После отладки проблемы я понял, что это, без сомнения, связано с именем хоста / IP, которые клиенты регистрируют в zookeeper.

Когда я выполняю скручивание с использованием идентификатора докера в качестве имени хоста, API / health возвращается при выполнении скручивания из SBA к идентификатору контейнера клиента.

Это работает: docker exec -it 8403c5001b9e curl -k https://bf41c73af594:8080/health

Это не работает, приводит к превышению времени ожидания: docker exec -it 8403c5001b9e curl -k https://10.255.0.20:8080/health

Можно ли заставить zookeeper регистрировать имя хоста или идентификатор контейнера?

ОБНОВЛЕНИЕ Установка spring.cloud.zookeeper.discovery.instanceHost: $ {HOSTNAME} в моем application.yml решает проблему.Это заставляет правильный идентификатор контейнера быть зарегистрированным в zookeeper.

1 Ответ

0 голосов
/ 31 декабря 2018

Вам не нужно делать все эти цирки.В Docker существует концепция, называемая обнаружением службы.Это локальное DNS-разрешение, которое позаботится докер.

Вы можете использовать имя контейнера или указать псевдоним вместо IP / идентификатора контейнера, так как они будут меняться каждый раз.

Метод 1:

По умолчанию docker добавляет имя сети с именем службы для имени контейнера.Вы можете исправить имя контейнера, используя ключевое слово container_name в decker-compose.Тогда вы можете использовать это имя вместо IP.Это приведет к разрешению соответствующих контейнеров.

Пример составного файла:

version: '3.1'

services:
    zoo1:
        image: zookeeper:3.4.12
        hostname: zoo1
        container_name: zoo1
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda5v]
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888

    zoo2:
        image: zookeeper:3.4.12
        hostname: zoo2
        container_name: zoo2
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda6v]
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888

    nspadmin:
        image: admin:77
        ports:
            - "9084:8080"
        networks:
            - nsp_test
        depends_on:
            - "zoo1"
            - "zoo2"
        deploy:
            restart_policy:
                condition: on-failure
            mode: global
        environment:
            ZK_HOST: zoo1:2181,zoo2:2182
            SPRING_PROFILES_ACTIVE: ssldev
networks:
    nsp_test:
      external:
        name: nsp_test

Теперь вы можете достичь zoo1 и zoo2 как zoo1 zoo2. Не подходит для режима роя, так как container_name игнорируется

Метод 2: (Рекомендуется для режима роя докера)

Вы можете указать псевдоним длякаждый хост и может получить доступ к этой службе с помощью псевдонима.

Пример файла компоновки:

version: '3.1'
services:
    zoo1:
        image: zookeeper:3.4.12
        hostname: zoo1
        networks:
            default:
                aliases:
                    - zoo1
                    - zoo.1
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda5v]
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888

    zoo2:
        image: zookeeper:3.4.12
        hostname: zoo2
        networks:
            default:
                aliases:
                    - zoo2
                    - zoo.2
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda6v]
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888

    nspadmin:
        image: admin:77
        ports:
            - "9084:8080"
        networks:
            - nsp_test
        depends_on:
            - "zoo1"
            - "zoo2"
        deploy:
            restart_policy:
                condition: on-failure
            mode: global
        environment:
            ZK_HOST: zoo1:2181,zoo2:2182
            SPRING_PROFILES_ACTIVE: ssldev
networks:
    default:
      external:
        name: nsp_test

Здесь zoo1 может быть разрешен как zoo1, zoo.1, zoo1.nsp_test zoo.1.nsp_test.То же самое касается zoo2. подходит и для режима роя.

Метод 3:

Если вы знаете, как называется создаваемая служба, то выможет также использовать это для разрешения контейнера.

Например:

version: '3.1'
services:
    zoo1:
        image: zookeeper:3.4.12
        hostname: zoo1
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda5v]
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888

    zoo2:
        image: zookeeper:3.4.12
        hostname: zoo2
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda6v]
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888

    nspadmin:
        image: admin:77
        ports:
            - "9084:8080"
        networks:
            - nsp_test
        depends_on:
            - "zoo1"
            - "zoo2"
        deploy:
            restart_policy:
                condition: on-failure
            mode: global
        environment:
            ZK_HOST: zoo1:2181,zoo2:2182
            SPRING_PROFILES_ACTIVE: ssldev
networks:
    nsp_test:
      external:
        name: nsp_test

Предположим, что вышеуказанный конфиг создает контейнеры с именами zoo1_nsp_test и zoo2_nsp_test.Вы также можете разрешить контейнеры, используя эти имена. Не подходит для узла роя, так как имя контейнера отличается от хоста к хосту.

Примечание:
Все вышеперечисленные методы работают, только есликонтейнеры подключены к одной и той же сети.

Ссылки:

  1. Ссылка на версию 3 составного файла # имя_ контейнера
  2. Ссылка на файл версии 3, ссылка # псевдонимы
  3. обнаружение службы
  4. Балансировка нагрузки, обнаружение службы и безопасность
...