V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
GeekHub
NoBeeBee
V2EX  ›  程序员

docker + ipv6

  •  
  •   NoBeeBee · 2019-04-10 18:33:35 +08:00 · 2972 次点击
    这是一个创建于 529 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目需求需要利用 docker 支持 ipv6 网络环境。 于是简单研究了一下 docker 针对 ipv6 的部署情况。 官网写的挺简单,https://docs.docker.com/config/daemon/ipv6/ 如下:

    Edit /etc/docker/daemon.json and set the ipv6 key to true. { "ipv6": true } Save the file.

    Reload the Docker configuration file. $ systemctl reload docker

    You can now create networks with the --ipv6 flag and assign containers IPv6 addresses using the --ip6 flag.

    结果发现这样配置后,随意 run 一个 docker 镜像,并没有发现 docker 内部会自动获取 ipv6 地址(开发环境中已存在 ipv6 的 dhcp 服务器,host 主机会自动获取 ipv6 地址)。 于是继续观摩官网 https://docs.docker.com/v17.09/engine/userguide/networking/default_network/ipv6/#how-ipv6-works-on-docker 发现如下信息:How IPv6 works on Docker By default, the Docker daemon configures the container network for IPv4 only. You can enable IPv4/IPv6 dualstack support by running the Docker daemon with the --ipv6 flag. Docker will set up the bridge docker0 with the IPv6 link-local address fe80::1.

    By default, containers that are created will only get a link-local IPv6 address. To assign globally routable IPv6 addresses to your containers you have to specify an IPv6 subnet to pick the addresses from. Set the IPv6 subnet via the --fixed-cidr-v6 parameter when starting Docker daemon:

    You can run dockerd with these flags directly, but it is recommended that you set them in the daemon.json configuration file instead. The following example daemon.json enables IPv6 and sets the IPv6 subnet to 2001:db8:1::/64.

    { "ipv6": true, "fixed-cidr-v6": "2001:db8:1::/64" } The subnet for Docker containers should at least have a size of /80, so that an IPv6 address can end with the container ’ s MAC address and you prevent NDP neighbor cache invalidation issues in the Docker layer.

    By default, --fixed-cidr-v6 parameter causes Docker to add a new route to the routing table, by basically running the three commands below on your behalf. To prevent the automatic routing, set ip-forward to false in the daemon.json file or start the Docker daemon with the --ip-forward=false flag. Then, to get the same routing table that Docker would create automatically for you, issue the following commands:

    $ ip -6 route add 2001:db8:1::/64 dev docker0

    $ sysctl net.ipv6.conf.default.forwarding=1

    $ sysctl net.ipv6.conf.all.forwarding=1 All traffic to the subnet 2001:db8:1::/64 will now be routed via the docker0 interface.

    大概意思就是 docker 会自动获取 ipv4 地址,ipv6 地址需要开启 v6 服务。即使开启 v6 服务,也只是会获取本地局域类型的 v6 地址(非全球公网 ipv6 地址),公网 ipv6 的地址需要手动配置。

    按照这个思路观察原有 v4 环境下项目的部署,的确 docker 环境中确实只要 host 寄主机能够访问公网,docker 容器不需要配置公网 v4 地址就可以访问公网( docker 镜像获取的都是私网地址,例如 172.17..)。寄主机会自动路由容器内部的公网访问请求。

    但是!!!

    目前发现 docker 在 ipv6 的环境下就不一样了。即使 host 寄主机已经自动获取到 v6 的公网地址,如果不手动配置 docker ipv6 的路由地址,不管是 docker run 还是 docker-compose 启动的容器,内部都不能访问 v6 的公网。进入到容器内部查看网络配置,你会发现容器只获取到了 link-local IPv6 address (如官网所说)。然后这个 v6 的本地地址和 v4 的私网地址不同,v6 中已经没有私网地址这个概念了。

    按 v4 的使用习惯,寄主机应该自动路由容器内部对于公网 ipv6 请求的路由信息,即使容器内部并没有获取到动网 ipv6 地址。结果确并不是这样。。。

    最后试着利用 docker-compose 的配置去手动设置了 ipv6 地址,如下:networks: app_net: driver: bridge enable_ipv6: true ipam: driver: default config: - subnet: 172.19.0.0/24 gateway: 172.19.0.1 - subnet: 2123:abcd:1234:5678::0/120 gateway: 2123:abcd:1234:5678::1

    其中 subnet 和 gateway 需要参考寄主机自动获取的 v6 地址进行适度更改。

    并且还要将寄主机的自动获取到 ipv6 的网口做成路由网口(栗子为 ens160 ),并且配置 docker 的 NDP 邻居发现,如下:

    sysctl net.ipv6.conf.default.forwarding=1 sysctl net.ipv6.conf.all.forwarding=1 sysctl net.ipv6.conf.ens160.accept_ra=2 sysctl net.ipv6.conf.ens160.proxy_ndp=1

    重启 docker 服务 systemctl reload docker

    并将对应的容器获取到的 v6 地址映射到寄主机的网口上:ip -6 neigh add proxy 2123:abcd:1234:5678::2 dev ens160

    添加完后不需要重启 docker 实例,直接生效;

    经过这样一番折腾后,容器内部才能 ping6 ipv6.baidu.com 这个地址,也就是能正常访问 ipv6 的公网了。

    总结:docker 有没有像 v4 那样,只需要寄主机获取到 ipv6 的公网地址(并且能够正常访问),容器内部只要支持 v6 并不需要!不需要!不需要! 配置 v6 的公网地址就可以访问到外部的 ipv6 公网资源。 每次这样手配地址真的很麻烦,而且不知道有没有和别的 v6 设备地址冲突...

    求各位大神指点迷津

    7 条回复    2020-09-15 23:16:21 +08:00
    whatsmyip
        1
    whatsmyip   2019-04-10 18:41:06 +08:00
    曾经尝试过,没有成功。。。
    NoBeeBee
        2
    NoBeeBee   2019-04-11 16:28:34 +08:00
    自顶求不沉,求大佬之路
    lanlanmengmeng
        3
    lanlanmengmeng   339 天前
    绑定,我最近也在弄这个。
    weiwenwong90
        5
    weiwenwong90   174 天前
    不好意思挖以下,请问这个问题有解决方法没有,我翻文档看起来还是只能手动指定 prefix
    padeoe
        6
    padeoe   174 天前
    @weiwenwong90 #5 按照楼主说的也就是文档上说的,可以解决,就是麻烦了点
    gam2046
        7
    gam2046   4 天前
    想咨询一下 @padeoe

    docker-compose 中使用 ports 公开的端口,如果宿主机同时拥有 v4 和 v6 的地址,似乎无法通过宿主机的 IPv6 地址进行访问。

    有没有比较简单的方法,就可以让公开的宿主机的端口能够直接通过主机的 v6 地址访问?
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2544 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 11:28 · PVG 19:28 · LAX 04:28 · JFK 07:28
    ♥ Do have faith in what you're doing.