)
一、理解 docker0一三个地址详解1、loloopback 本地回环网卡inet 127.0.0.1/8含义本机内部虚拟网卡作用程序本机内部互相通信不经过物理网卡不会走局域网。通俗理解自己和自己对话。特点所有 Linux 系统默认自带ping 127.0.0.1永远能通外部电脑无法访问这个地址2、ens33虚拟机物理网卡和宿主机通信的网卡inet 192.168.193.134/24含义虚拟机局域网 IP静态 IP作用Windows 宿主机、其他同网段虚拟机通过这个 IP 远程连接、互相访问。网段192.168.193.xVMware NAT 网段3、docker0Docker 虚拟网桥网卡inet 172.17.0.1/16含义Docker 内置虚拟网桥桥接网卡作用宿主机Ubuntu ↔ Docker 容器之间通信桥梁所有新建容器默认接入 docker0 网桥规则docker0 地址172.17.0.1相当于容器网段网关启动容器后容器会自动分配172.17.x.x的内网地址NO-CARRIER当前没有正在运行的容器网桥无设备接入当你 run 一个容器后这个 NO-CARRIER 标识会消失。容器端口映射原理 Windows 访问192.168.193.134:端口→ ens33 接收 → 转发到 docker0 → 最终转发到容器内部服务。二docker 间通信1、安装并运行rootubuntu:~# docker run -d -P --name tomcat01 tomcat2、安装IP工具并执行安装工具官方 tomcat 镜像属于精简版容器内部没有安装iproute2工具包不存在ip这条命令# 宿主机一步安装 rootubuntu:~# docker exec -it tomcat01 /bin/bash -c apt update apt install iproute2 -y // -c 代表引号内所有命令全部在容器内部运行。 // ping 工具安装docker exec -it tomcat01 /bin/bash -c apt update apt install iputils-ping -y3、执行查询docker ip# 查看容器的内部网络地址发现容器启动的时候会得到 eth0if4 这样一个IP地址 rootubuntu:~# docker exec -it tomcat01 ip addr发现 linux 能 ping 通容器内部4、原理①每启动一个 docker 容器docker 就会给 docker 容器分配一个 ip。只要安装了 docker就会有一个网卡 docker0 桥接模式使用的技术是 veth-pair 技术执行测试 ip addr再启动一个容器测试发现又多了一对网卡5、22、5综上发现容器里的 ip2eth0if5与 linux 里查看的的 ip5: vethae82936if2发现2、55、2算一对总是成对出现的。同理容器里的 ip2: eth0if4与 linux 里查看的的 ip4: vethd53ffeaif2发现2、44、2算一对总是成对出现的。理解veth-pair技术比如虚拟机linux 与 容器通信就是通过veth-pair这个技术的一对接口彼此相连一个接口在linux上一个接口在容器上如图。总结# 我们发现这个容器带来网卡都是一对对的# veth-pai 就是一对的虚拟设备接口他们都是成对出现的一段连着协议一段彼此相连# 正因为有这个特性evth-pair 充当一个桥梁连接各种虚拟网络设备的# OpenStackDocker容器之间的连接OVS的连接都是使用 veth-pair 技术②tomcat01 与 tomcat02 是否可以 ping 通安装ping命令工具# 进容器两步安装 rootubuntu:~# docker exec -it tomcat02 /bin/bash root4e45ace3b4e8:/usr/local/tomcat# apt update apt install iputils-ping -ytomcat01安装同理。tomcat01 与 tomcat02 互pingrootubuntu:~# docker exec -it tomcat02 ping 172.17.0.2发现 tomcat01 与 tomcat02 能互相 ping 通 关系图解docker01 和 docker02 是共用一个路由器 docker0 。所有容器在不指定路由的情况下都是 docker0 路由的docker 会给容器分配一个默认的可用 iptomcat01 与 tomcat02 之间通信都是通过 docker0 来通信Docker中的所有的网络接口都是虚拟的。虚拟的转发效率高(内网传递文件)只要容器删除对应网桥一对就没了二、--link一发现二解决通过 --link 绑定后可以通过容器名称 ping 通rootubuntu:~# docker run -d -P --name tomcat03 --link tomcat01 tomcat但反向 ping 是 ping 不通的需要在对应容器上做对应的 --link 配置三原理探究# 发现做了 --link 配置的 tomcat03 的 hosts 本地域名解析里面写死了 tomcat01 与 ip rootubuntu:~# docker exec -it tomcat03 cat /etc/hosts /* /etc/hosts 文件是 Linux 本地域名解析文件优先级高于 DNS。 系统访问域名时先查 /etc/hosts匹配不到才去 DNS 服务器查询。 */--link 就是我们在 hosts 配置中增加了一个 172.18.0.3 tomoat02 312857784cd4 的映射四注意✅旧方案--link参数官方已经废弃不推荐新项目使用✅标准现代方案Docker 自定义网络推荐完美解决该场景三、自定义网络查看所有的 docker 网络一网路属性bridge 桥接 docker默认自己创建也使用bridge模式 即 docker0none 不配置网络host 和宿主机共享网络container 容器网络连通用的少!局限很大# 环境准备一键强制删除本机全部 Docker 容器 rootubuntu:~# docker rm -f $(docker ps -aq)二测试# 前面我们直接启动的第一条命令形式其实是省略了 --net bridge 这个参数的而这个 bridge 参数就是 docker0 docker run -d -P --name tomcat01 tomcat docker run -d -P --name tomcat01 --net bridge tomcat # docker0特点默认域名不能访问通过 --link 可以打通连接1、创建自定义网络rootubuntu:~# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet /* --driver bridge 驱动类型bridge桥接模式 作用使用网桥网络驱动和默认docker0类型一致 --subnet 192.168.0.0/16 自定义网段指定这个网络下所有容器分配 IP 的地址池 /16子网掩码 255.255.0.0 容器启动加入该网络时自动从192.168.x.x范围内分配 IP --gateway 192.168.0.1 网关地址必须属于上面 subnet 网段 代表这个网桥的网关 IP容器访问外部网络的出口地址。 mynet 自定义网络名称网络标识后续启动容器通过--network mynet加入 */2、查看详细配置信息3、验证使用自创建网络开启两个容器并查看详细信息三自定义网络好处1、通过自定义网络已经维护好了容器间的映射关系就不用通过 --link 再一一配置推荐使用自定义网络2、通过自定义网络不同的集群例如集群 redis 和 集群 mysql 使用不同的网络保证集群是安全和健康的通过后续网络连通的知识了解不同网段的集群如何连通四、网络连通一关键命令及使用方法二测试1、目的实现 docker0 网段的 tomcat01 与 mynet 网段的 tomcat01-mynet012、方法操作只能通过网络间打通 无法通过打通网卡 docker0 和 网卡 mynet 来实现不同网段的连通# 打通不通网段的网卡与容器的连接 rootubuntu:~# docker network connect mynet tomcat01 rootubuntu:~# docker network inspect mynet测试打通之后发现 tomcat01 成了 mynet 网络下的一个容器。说明tomcat01拥有了两个ip地址类似于阿里云服务里的公网ip和私网ip两个ip均可访问------- 因此tomcat01可以访问互相ping通mynet网络下的所有容器3、结果测试连通结论要跨网段操作就要使用 docker network connect 连通五、实战Redis 集群部署一环境准备rootubuntu:~# docker rm -f $(docker ps -aq) 663315891a84 742bf4370ae6 400383e2b9b1 f8c014fef221 rootubuntu:~#二创建网卡rootubuntu:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES rootubuntu:~# docker network create --subnet 172.38.0.0/16 redis 6e4e0c96985d68b1a137fa235d6d128ad4267c68729dbd8b58adbce8cf13406e rootubuntu:~# docker network ls NETWORK ID NAME DRIVER SCOPE 34c3bc740b5a bridge bridge local 019c5b7c5b7b host host local 1eb43649f7bf none null local 6e4e0c96985d redis bridge local三脚本创建redis配置并查看rootubuntu:~# for port in $(seq 1 6); \ do \ # 循环变量 port 依次取值 1~6对应 6 个 redis 节点 mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat EOF /mydata/redis/node-${port}/conf/redis.conf port 6379 # 允许所有网卡地址访问 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.38.0.1${port} cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes EOF done rootubuntu:~# cd /mydata/redis/ rootubuntu:/mydata/redis# ls node-1 node-2 node-3 node-4 node-5 node-6 rootubuntu:/mydata/redis# cat /mydata/redis/node-2/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes # 集群信息文件存放节点 ID、槽位、主从关系容器启动之后自动生成挂载到宿主机目录持久化。 cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.38.0.12 # 对外公布 redis 服务端口 cluster-announce-port 6379 # 集群内部总线端口节点之间心跳、消息通信端口 服务端口 10000 cluster-announce-bus-port 16379 # 开启 AOF 持久化防止宕机之后内存数据丢失 appendonly yes四创建并运行容器rootubuntu:/mydata/redis# for i in $(seq 1 6) do host_port$((6370i)) bus_port$((16370i)) ip_addr172.38.0.1${i} docker run -p ${host_port}:6379 -p ${bus_port}:16379 --name redis-${i} \ ‑v 就是目录挂载redis‑1 对应的宿主机/mydata/redis/node‑1/data容器内/data -v /mydata/redis/node-${i}/data:/data \ -v /mydata/redis/node-${i}/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip ${ip_addr} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf done rootubuntu:/mydata/redis# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b440b6570e12 redis:5.0.9-alpine3.11 docker-entrypoint.s… 2 minutes ago Up 2 minutes 0.0.0.0:6376-6379/tcp, [::]:6376-6379/tcp, 0.0.0.0:16376-16379/tcp, [::]:16376-16379/tcp redis-6 1b983b5e59b1 redis:5.0.9-alpine3.11 docker-entrypoint.s… 3 minutes ago Up 3 minutes 0.0.0.0:6375-6379/tcp, [::]:6375-6379/tcp, 0.0.0.0:16375-16379/tcp, [::]:16375-16379/tcp redis-5 74c3629891ab redis:5.0.9-alpine3.11 docker-entrypoint.s… 3 minutes ago Up 3 minutes 0.0.0.0:6374-6379/tcp, [::]:6374-6379/tcp, 0.0.0.0:16374-16379/tcp, [::]:16374-16379/tcp redis-4 161c4cdd7a4c redis:5.0.9-alpine3.11 docker-entrypoint.s… 3 minutes ago Up 3 minutes 0.0.0.0:6373-6379/tcp, [::]:6373-6379/tcp, 0.0.0.0:16373-16379/tcp, [::]:16373-16379/tcp redis-3 2ee5b7020ad5 redis:5.0.9-alpine3.11 docker-entrypoint.s… 3 minutes ago Up 3 minutes 0.0.0.0:6372-6379/tcp, [::]:6372-6379/tcp, 0.0.0.0:16372-16379/tcp, [::]:16372-16379/tcp redis-2 effde8abb150 redis:5.0.9-alpine3.11 docker-entrypoint.s… 3 minutes ago Up 3 minutes 0.0.0.0:6371-6379/tcp, [::]:6371-6379/tcp, 0.0.0.0:16371-16379/tcp, [::]:16371-16379/tcp redis-1五执行并进入容器rootubuntu:/mydata/redis# rootubuntu:/mydata/redis# docker exec -it redis-1 /bin/sh /data # ls appendonly.aof nodes.conf六安装工具 redis-cli 并创建集群rootubuntu:/mydata/redis# apt install redis-tools rootubuntu:/mydata/redis# redis-cli --cluster create \ 172.38.0.11:6379 \ 172.38.0.12:6379 \ 172.38.0.13:6379 \ 172.38.0.14:6379 \ 172.38.0.15:6379 \ 172.38.0.16:6379 \ --cluster-replicas 1七进入集群# -c 开启集群模式客户端不会死板停留在当前连接节点 先计算 key 对应的哈希槽再依照集群槽位表自动跳转到管理该槽位的主节点。 rootubuntu:/mydata/redis# redis-cli -c -h 172.38.0.11 -p 6379 172.38.0.11:6379 cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:485 cluster_stats_messages_pong_sent:491 cluster_stats_messages_sent:976 cluster_stats_messages_ping_received:486 cluster_stats_messages_pong_received:485 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:976 172.38.0.11:6379 cluster nodes e69768da5ca3fd2520a0b62a255335cad77e4c4a 172.38.0.12:637916379 master - 0 1785986444725 2 connected 5461-10922 2f463a185d78002d0108aeda693f26c33a01f2d5 172.38.0.14:637916379 slave b05c255a2fd912fde2489e404c58de4e7544e0c2 0 1785986443217 4 connected b05c255a2fd912fde2489e404c58de4e7544e0c2 172.38.0.13:637916379 master - 0 1785986444222 3 connected 10923-16383 8b4e659419c4df6ac10f194f2e7b2ecde0a3ea23 172.38.0.15:637916379 slave d543bc8bf98f5fc909a5b042e32f487b76b63e02 0 1785986444000 5 connected 069f95eb41c4d3e609f6c858faded99c1e78b680 172.38.0.16:637916379 slave e69768da5ca3fd2520a0b62a255335cad77e4c4a 0 1785986443521 6 connected d543bc8bf98f5fc909a5b042e32f487b76b63e02 172.38.0.11:637916379 myself,master - 0 1785986444000 1 connected 0-5460八测试集群停掉主集群redis-3172.38.0.11:6379 set user:name lli - Redirected to slot [15593] located at 172.38.0.13:6379 OK 172.38.0.13:6379 get user:name lli 172.38.0.13:6379 get user:name Could not connect to Redis at 172.38.0.13:6379: No route to host (16.35s) not connected redis-cli -c -h 172.38.0.11 -p 6379 Could not connect to Redis at 172.38.0.13:6379: No route to host (3.06s) not connected exit rootubuntu:/mydata/redis# redis-cli -c -h 172.38.0.11 -p 6379 172.38.0.11:6379 get user:name - Redirected to slot [15593] located at 172.38.0.14:6379 lli 172.38.0.14:6379 cluster nodes九疑惑解答1、Redis‑Cluster 底层规则Redis 集群一共有0~16383 合计 16384 个哈希槽每一条键名user:name会执行固定哈希算法slot CRC16(user:name) % 16384图中插入的键名被计算得出该 key 固定归属槽位 155932、第一次跳转11 -- 13由于初始槽位分配最刚开始搭建三主三从集群的时候172.38.0.11 → 负责槽位 0‑5460172.38.0.12 → 负责槽位 5461‑10922172.38.0.13 → 负责槽位 10923‑16383包含 1559311 节点只掌管 0‑5460 的槽并不存放 user:name。---所以重定向到了 172.38.0.133、第二次跳转13 -- 14进入11后由于访问槽位本属于13的内容但由于redis‑13 容器关闭、失联13 对应的从节点 172.38.0.14发起选举晋升成新 master。由此全部节点更新槽位映射槽 10923‑16383 现在交给 14 管理因此之后你再查询user:name‑c 客户端就重定向至172.38.0.14