Плохой шлюз с трафиком и роем докера во время обновления сервиса - PullRequest
2 голосов
/ 16 апреля 2019

Я пытаюсь использовать traefik с Docker Swarm, но у меня возникают проблемы при обновлении сервиса.Я запускаю stack deploy или service update служба останавливается на несколько секунд

Как воспроизвести:

1 - Создать файл Docker:

FROM jwilder/whoami
RUN echo $(date) > daniel.txt

2 -Создайте 2 демонстрационных изображения:

$ docker build -t whoami:01 .
$ docker build -t whoami:02 .

3 - создайте docker-compose.yml:

version: '3.5'

services:
  app:
    image: whoami:01
    ports:
      - 81:8000
    deploy:
      replicas: 2
      restart_policy:
        condition: on-failure
      update_config:
        parallelism: 1
        failure_action: rollback
      labels:
        - traefik.enable=true
        - traefik.backend=app
        - traefik.frontend.rule=Host:localhost
        - traefik.port=8000
        - traefik.docker.network=web
    networks:
      - web

  reverse-proxy:
    image: traefik
    command: 
      - "--api"
      - "--docker"
      - "--docker.swarmMode"
      - "--docker.domain=localhost"
      - "--docker.watch"
      - "--docker.exposedbydefault=false"
      - "--docker.network=web"
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
      update_config:
        parallelism: 1
        failure_action: rollback
      placement:
        constraints:
          - node.role == manager
    networks:
      - web
    ports:
      - 80:80
      - 8080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

networks:
  web:
    external: true

4 - разверните стек:

$ docker stack deploy -c docker-compose.yml stack_name

5 -Завиток, чтобы получить ответ службы:

$ while true ; do sleep .1; curl localhost; done

Вы должны увидеть что-то вроде этого:

I'm adc1473258e9
I'm bc82ea92b560
I'm adc1473258e9
I'm bc82ea92b560

Это означает, что баланс нагрузки работает

6 - Обновить службу

$ docker service update --image whoami:02 got_app

Traefik отвечает Bad Gateway, когда должно быть нулевое время простоя.

Как это исправить?

1 Ответ

1 голос
/ 17 апреля 2019

Плохой шлюз означает, что traefik настроен на пересылку запросов, но он не может получить доступ к контейнеру на ip и порте, которые он настроил для использования. Распространенные проблемы, вызывающие это:

  • трафик и сервис в разных докерских сетях
  • услуга существует в нескольких сетях, и трафик выбирает не ту
  • неверный порт, используемый для подключения к контейнеру (используйте порт контейнера и убедитесь, что он прослушивает все интерфейсы, он же 0.0.0.0)

Из комментариев это происходит только во время развертывания, что означает, что traefik запускает контейнеры, прежде чем они будут готовы к приему запросов или пока они останавливаются.

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

FROM jwilder/whoami
RUN echo $(date) >/build-date.txt
HEALTHCHECK --start-period=30s --retries=1 CMD wget -O - -q http://localhost:8000

А потом в docker-compose.yml:

  labels:
    - traefik.enable=true
    - traefik.backend=app
    - traefik.backend.loadbalancer.swarm=true
    ...

И я бы также настроил службу traefik со следующими параметрами:

  - "--retry.attempts=2"
  - "--forwardingTimeouts.dialTimeout=1s"

Однако traefik будет держать соединение открытым, и VIP продолжит отправлять все запросы одному и тому же внутреннему контейнеру по тому же соединению. Вместо этого вы можете использовать traefik для проверки здоровья:

  labels:
    - traefik.enable=true
    - traefik.backend=app
    - traefik.backend.healthcheck.path=/
    ...

Я бы все же оставил проверку работоспособности на самом контейнере, чтобы Docker давал время запуску контейнера перед остановкой другого контейнера. И оставьте параметр повтора в сервисе traefik, чтобы любой запрос к остановившему контейнеру или просто тот, который не был обнаружен проверкой работоспособности, имел шанс повторить попытку.


Вот итоговый файл композиции, который я использовал в своей среде:

version: '3.5'

services:
  app:
    image: test-whoami:1
    ports:
      - 6081:8000
    deploy:
      replicas: 2
      restart_policy:
        condition: on-failure
      update_config:
        parallelism: 1
        failure_action: rollback
      labels:
        - traefik.enable=true
        - traefik.backend=app
        - traefik.backend.healthcheck.path=/
        - traefik.frontend.rule=Path:/
        - traefik.port=8000
        - traefik.docker.network=test_web
    networks:
      - web

  reverse-proxy:
    image: traefik
    command:
      - "--api"
      - "--retry.attempts=2"
      - "--forwardingTimeouts.dialTimeout=1s"
      - "--docker"
      - "--docker.swarmMode"
      - "--docker.domain=localhost"
      - "--docker.watch"
      - "--docker.exposedbydefault=false"
      - "--docker.network=test_web"
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
      update_config:
        parallelism: 1
        failure_action: rollback
      placement:
        constraints:
          - node.role == manager
    networks:
      - web
    ports:
      - 6080:80
      - 6880:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

networks:
  web:

Dockerfile, как указано выше. Имена изображений, порты, имена сетей и т. Д. Были изменены, чтобы избежать конфликтов с другими объектами в моей среде.

...