我有一台运行 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 ... &
该命令将其置于后台。
答案2
Swarm 模式似乎不支持使用 ingress/service-mesh 网络的 IPv6。未决问题对此,我建议您订阅并点赞以获得更多关注。
作为一种解决方法,集群内的服务可以通过 IPv4 进行通信,并且您可以通过在全局模式下运行的代理以主机模式发布端口。例如,以下是部分撰写文件:
version: '3.8'
services:
proxy:
deploy:
mode: global
ports:
- target: 80
published: 80
protocol: "tcp"
mode: "host"
# ...