IPv6 在 Docker Swarm 中不起作用?

IPv6 在 Docker Swarm 中不起作用?

我有一台运行 IPv4 和 IPv6(双栈)的 Ubuntu 服务器 16.04 LTS。该服务器还运行 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

我运行了与 about 相同的验证,并且它按预期工作。然后我编写了一个 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

答案1

你遇到了一个 bug,做错了什么。从许多 github 问题和评论中可以看出https://docs.docker.com/compose/compose-file/#ipv4_address-ipv6_addressIPv6 目前在群体中不起作用:

如果需要 IPv6 寻址,则必须设置 enable_ipv6 选项,并且必须使用 2.x 版 Compose 文件。IPv6 选项目前在 Swarm 模式下不起作用。

您可能想尝试 IPv6 NAThttps://github.com/robbertkl/docker-ipv6nat但这似乎也很难设置,特别是当你没有 ipv6tables 等的时候。

您做错的是没有设置启用 ipv6 的 docker swarm scope 桥接网络,或者没有启动启用 ipv6 的 docker - 但考虑到当前的文档,这并不奇怪。

-我认为没有人回答这个问题,因为目前还没有一个好的答案。-

但一个答案是让 docker 做它最擅长的事情,让 linux 的其余部分做剩下的事情。让 docker swarm 成为纯 ipv4 网络,只将 ipv6 流量转发到该网络。使用从 ipv4 到 ipv6 的 ip 表转发是不可能的,但使用socat例如可以实现:

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

注意,我将 docker 正在监听的端口移到了端口 81,因为尽管 swarm 的 docker_gwbridge 可能没有启用 ipv6,但它仍将绑定到 ipv6:80 端口(叹气)。注意,socat 现在会将 ipv4 和 ipv6 流量转发到 ipv4 端口 80。

您可以使用sudo nohup socat ... &该命令将其置于后台。

如何透明地将端口从 IPv4 隧道传输到远程 IPv6 设备?

答案2

Swarm 模式似乎不支持使用 ingress/service-mesh 网络的 IPv6。未决问题对此,我建议您订阅并点赞以获得更多关注。

作为一种解决方法,集群内的服务可以通过 IPv4 进行通信,并且您可以通过在全局模式下运行的代理以主机模式发布端口。例如,以下是部分撰写文件:

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

相关内容