IPv6 не работает в Docker Swarm?

У меня есть сервер Ubuntu 16.04 LTS, работающий на IPv4 и IPv6 (двойной стек). На этом сервере также работает Docker. Однако у меня возникают проблемы, когда я пытаюсь получить доступ к контейнерам в рое, но только через IPv6. Вот мои шаги:

Я создал простое приложение под управлением веб-сервера gnuicron:

def app(environ, start_response):
    """Simplest possible application object"""
    data = b'Hello, World!\n'
    status = '200 OK'
    response_headers = [
        ('Content-type', 'text/plain'),
        ('Content-Length', str(len(data)))
    ]
    start_response(status, response_headers)
return iter([data])

Я запускаю это с gunicorn -w 4 -b [::]:5678 myapp:app на моем сервере и убедитесь, что он работает, запустив это на клиенте с двумя стеками в моей сети:

$ curl --connect-timeout 15 http://[2001:db8:db0::5]:5678
Hello, World!
$ curl --connect-timeout 15 http://192.168.10.5:5678
Hello, World!

Я пишу Dockerfile и запускаю его:

docker build -t docker_ipv6_test .
docker run --rm --init -p 5678:5678 docker_ipv6_test

Я запускаю ту же проверку, что и примерно, и она работает, как ожидалось. Затем я пишу docker-compose.yml:

version: '3'
services:
  ipv6_test:
    image: docker_ipv6_test:latest
    deploy:
      replicas: 1
      restart_policy: 
        condition: on-failure
      ports:
        - '5678:5678/tcp'

и запустить его:

docker stack deploy -c docker-compose.yml ipv6_test

Тогда это происходит:

$ curl --connect-timeout 15 http://[2001:db8:db0::5]:5678
curl: (28) Operation timed out after 0 milliseconds with 0 out of 0 bytes received
$ curl --connect-timeout 15 http://192.168.10.5:5678
Hello, World!

Но мне было интересно, если я делаю что-то не так, или я ошибся?

Весь мой код и файлы доступны здесь: https://github.com/SitronNO/docker_ipv6_test

0 ответов

Режим Swarm, похоже, не поддерживает IPv6 с входящей / служебной сетью. По этому поводу есть открытая проблема, на которую я бы порекомендовал подписаться и поставить отметку "Нравится", чтобы привлечь больше внимания.

В качестве обходного пути службы в кластере могут взаимодействовать по IPv4, и вы можете публиковать порты в режиме хоста через прокси, работающий в глобальном режиме. Например, вот частичный файл компоновки:

version: '3.8'
services:
  proxy:
    deploy:
      mode: global
    ports:
    - target: 80
      published: 80
      protocol: "tcp"
      mode: "host"
    # ...

Вы нажали на ошибку и сделали что-то не так. Из многих проблем github и комментария на https://docs.docker.com/compose/compose-file/ узнать, что ipv6 в настоящий момент не работает в роях:

Если требуется адресация IPv6, необходимо установить параметр enable_ipv6 и использовать файл составления версии 2.x. Опции IPv6 в настоящее время не работают в режиме роя.

вы можете попробовать IPv6 NAT https://github.com/robbertkl/docker-ipv6nat но это тоже сложно настроить, особенно если у вас нет ipv6tables и т. д.

То, что вы сделали неправильно, не настроили сеть моста роя роя с поддержкой ipv6, ИЛИ не запустите докер с включенным ipv6 - но, учитывая текущую документацию, это не удивительно.

-Я бы сказал, что никто не ответил на этот вопрос, потому что пока нет хорошего ответа.

НО один из ответов - пусть docker сделает то, что умеет лучше всего, а остальная часть linux сделает все остальное. Оставьте Docker Swarm в качестве чисто сети ipv4 и просто перенаправьте трафик ipv6 в эту сеть. Это невозможно с ip-таблицами пересылки с ipv4 на ipv6, но это возможно при использовании socat например:

sudo socat TCP6-LISTEN:80,,su=nobody,fork,reuseaddr TCP4:127.0.0.1:81

Заметьте, что я перенес докер порта, который прослушивает порт 81, потому что, хотя в docker_gwbridge для роя может быть не включен ipv6, он все равно будет связываться с портом ipv6:80 (вздох). Обратите внимание, что socat теперь будет пересылать ОБА ipv4 и ipv6 трафик на порт ipv4 80.

Вы можете sudo nohup socat ... & эта команда, чтобы получить его в фоновом режиме.

см. Как прозрачно туннелировать порт от IPv4 к удаленному устройству IPv6? и другие.

Другие вопросы по тегам