首先,Docker对IPv6的支持肯定没有IPv4好;其次,如果可以使用Docker的host网络模式,就可以借用host的IPv6协议栈进行通信,而无需多余配置;以实现容器ipv6通信的需求。
Docker开启IPv6支持
# ipv6:true开启ipv6支持;fixed-cidr-v6:设置默认网络IPv6网段(必填)
vi /etc/docker/daemon.json
{
"ipv6": true,
"fixed-cidr-v6": "fd00:db8:1::/64"
}
Docker开启ip6tables支持
# 设置ip6tables为true,该功能为experimental feature,所以需要开启。
vi /etc/docker/daemon.json
{
"ipv6": true,
"fixed-cidr-v6": "fd00:db8:1::/64",
"experimental": true,
"ip6tables": true
}
如果不启动ip6tables功能,则不会自动创建ip6tables策略,无法实现跨节点通信;也可以手动创建ip6tables已实现跨节点通信目的:
ip6tables -t nat -A POSTROUTING -s fd00:db8:2:ddff::1/64 ! -o docker0 -j MASQUERADE
自定义Docker默认网络的IPv6网关
# default-gateway-v6:自定义Docker默认网络中,容器中ipv6网络默认网关。
# 设置之后虽然容器内部的default route已经设置为fd00:db8:1::ffff
# 但是,docker0 bridge interface的ipv6地址仍然使用默认地址:fd00:db8:1::1
vi /etc/docker/daemon.json
{
"ipv6": true,
"fixed-cidr-v6": "fd00:db8:1::/64",
"experimental": true,
"ip6tables": true,
"default-gateway-v6": "fd00:db8:1::ffff"
}
重启docker
systemctl reload docker 或 systemctl restart docker
容器节点上创建的bridge interface docker0已经分配到了IPv6地址
ip add show docker0|grep inet
inet 172.103.0.1/24 brd 172.103.0.255 scope global docker0
inet6 fd00:db8:1::1/48 scope global
inet6 fe80::42:87ff:fe3e:9b6b/64 scope link
inet6 fe80::1/64 scope link现在可以创建容器了,容器内部IPv6的默认网关:fd00:db8:1::1
docker exec -it f85f6080648a /bin/bash -c '/sbin/ip -6 route show'
fd00:db8:1::/48 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via fd00:db8:1::1 dev eth0 metric 1024 pref medium
创建docker网络
docker network create -d bridge --ipv6 --subnet "fd00:db8:2:ddee::/64" --gateway="fd00:db8:2:ddee::1" --subnet=172.104.1.0/24 --gateway=172.104.1.1 ipv6bridge
## 不配置ipv4 network,则会自动创建:"Subnet": "172.103.2.0/24","Gateway": "172.103.2.1"
docker network create --ipv6 --subnet "fd00:db8:2:ddff::/64" --gateway="fd00:db8:2:ddff::1" ipv6only## 创建的ipv6 network确实不指定gateway,但是创建容器时,使用该network,容器的ipv6默认网关为:fd00:db8:2:de00::1
docker network create --ipv6 --subnet "fd00:db8:2:de00::/64" ipv6only-nogwdocker network ls # 查看所有网络
docker network inspect ipv6bridge # 查看某个网络详情
docker network rm ipv6bridge # 删除某个网络
使用host的IPv6协议栈
上面说了这么多,令容器具有IPv6协议栈,并进行通信的最简单方法是:使用--network=host参数创建容器。也就是直接集成宿主机的IPv6网络。
docker-compose 启动ipv6支持
docker-compose.yml,其version需2.1+
networks:
my-network:
enable_ipv6: true
driver: bridge
ipam:
driver: default
config:
- subnet: fd01:3200:3200::/64
gateway: fd01:3200:3200::1
或,对version没有要求:
networks:
harbor:
external: true
name: ipv6bridge
Harbor支持IPv6
Harbor支持IPv6应该是自2.2.0开始支持的。但是,也是伪支持:
通过“docker-compose 启动ipv6支持”章节,我们可以在创建harbor各个服务时,分配IPv6地址。此时查看docker-proxy创建的端口转发情况:
/usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 443 -container-ip 172.103.1.10 -container-port 8443
/usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 443 -container-ip fd01:3200:3200::a -container-port 8443
但是,输入IPv6 URL(https://[fd88::20c:29ff:fe27:85b5]/)访问失败:curl -g https://[fd88::20c:29ff:fe27:85b5]/
curl: (7) Failed connect to fd88::20c:29ff:fe27:85b5:443; Connection refused
curl -g https://[fd01:3200:3200::a]:8443/curl: (7) Failed connect to fd01:3200:3200::a:8443; Connection refused
进入到nginx代理服务内部,查看发现所有服务也是监听在IPv4协议栈上的:而取消掉docker-compose对ipv6的支持,可以发现也会生成::443的映射,但是映射到了IPv4上:
/usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 443 -container-ip 172.103.4.9 -container-port 8443
/usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 443 -container-ip 172.103.4.9 -container-port 8443
输入IPv6 URL(https://[fd88::20c:29ff:fe27:85b5]/)访问成功:结论:harbor支持ipv6的方式(需要host存在双栈):docker、docker-compose都无需配置ipv6即可,使用host的IPv6即可。不然,应该重新打包nginx镜像。
FAQ
CentOS8上的Docker环境配置IPv6,docker.service服务成功启动,但是会报错:
level=error msg="Could not add route to IPv6 network fd00:db8:1::/48" via device docker0, network is down"
CentOS7.*上相同版本Docker、相同配置则无问题。并且CentOS8上虽有如上报错,但是配置却是生效的,也能正常使用。此外,还有两个warning也是出现在CentOS8上,CentOS7.*也无此问题。如下warning可以忽略,并未发现影响使用的地方。
level=warning msg="Your kernel does not support cgroup blkio weight"
level=warning msg="Your kernel does not support cgroup blkio weight_device"