Docker——Docker网络(Network)+ 部署Redis高可用集群

Posted Pakho`

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker——Docker网络(Network)+ 部署Redis高可用集群相关的知识,希望对你有一定的参考价值。

Docker网络模式

  • Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
  • Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p-P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
Docker网络模式配置说明
host模式–net=host容器和宿主机共享Network namespace
container模式–net=container:NAME_or_ID容器内的网络互联(用得少!局限性很大)
none模式–net=none容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等
bridge模式–net=bridge默认为该模式

理解Docker0

  • 清空环境
[root@docker ~]# docker rm -f $(docker ps -aq)
[root@docker ~]# docker rmi -f $(docker images -aq)
  • Docker 0
    • 本机一共三个网络
    • docker如何处理容器网络访问?
[root@docker ~]# ifconfig 
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:6bff:fee8:ce7d  prefixlen 64  scopeid 0x20<link>
        ether 02:42:6b:e8:ce:7d  txqueuelen 0  (Ethernet)
        RX packets 6581  bytes 631301 (616.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 11887  bytes 19551945 (18.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • 运行一个容器
[root@docker ~]# docker run -d -P --name tomcat01 tomcat

#查看容器内部的网络地址 ip add ,发现容器启动的时候会得到一个eth0@if17 ip地址,是由docker分配的
[root@docker ~]# docker exec -it tomcat01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
#使用本机ping容器地址,能够ping通
[root@docker ~]# ping 172.17.0.2
  • 我们每启动一个docker容器,docker就会给docker容器分配一个IP,只要安装了docker,就会有一个网卡 docker 0桥接),使用的技术是evth-pair技术!
    • 我们发现这个容器带来的网卡,都是成对的!
    • evth-pair就是一对的虚拟设备接口,他们都是成对出现,一段连着协议,一段彼此相连
    • 正因为有这个特性,evth-pair充当桥梁,连接各种虚拟网络设备
    • Docker容器之间的连接,OVS连接,都是使用evth-pair技术!
#再次使用ip add发现多一块网卡信息
17: veth9ab243b@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether fa:a6:1c:ca:cd:22 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::f8a6:1cff:feca:cd22/64 scope link 
       valid_lft forever preferred_lft forever
#再启动一个容器测试,发现又多一对网卡
[root@docker ~]# docker run -d -P --name tomcat02 tomcat

19: veth6ba0806@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 82:aa:d4:32:7b:96 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::80aa:d4ff:fe32:7b96/64 scope link 
       valid_lft forever preferred_lft forever

[root@docker ~]# docker exec -it tomcat02 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
  • 测试两个容器网络的联通性
    • 容器之间是可以互相ping通的
[root@docker ~]# docker exec -it tomcat02 ping 172.17.0.2
  • 结论
    • tomcat01和tomcat02 是公用的一个路由器,docker 0
    • 所有的容器在不指定网络的情况下,都是docker 0路由的,docker会给我们的容器分配一个默认的可用IP
      在这里插入图片描述
  • 小结
    • docker使用的是Linux桥接,宿主机中是一个Docker容器的网桥,docker 0≈ 65535
    • Docker中的所有网络接口都是虚拟的,虚拟的转发效率高!(如:内网传递文件)
    • 只要容器删除,对应的网桥一对同样移除!
      -

容器互联 (link)

--link

[root@docker ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                                         NAMES
5b4808dc2295   tomcat    "catalina.sh run"   34 minutes ago   Up 34 minutes   0.0.0.0:49154->8080/tcp, :::49154->8080/tcp   tomcat02
e9a1871a8352   tomcat    "catalina.sh run"   56 minutes ago   Up 56 minutes   0.0.0.0:49153->8080/tcp, :::49153->8080/tcp   tomcat01

#通过服务名无法ping通
[root@docker ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
  • 使用--link使容器互联
    • 这个tomcat03就是在本地配置了tomcat02的配置
    • --link就是在我们hosts配置中增加了tomcat02的映射
    • 我们现在使用Docker已经不建议使用--link了!
    • Docker 0问题:他不支持容器名连接访问!
[root@docker ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat

#通过--link可以解决网络连通问题
[root@docker ~]# docker exec -it tomcat03 ping tomcat02

#但是反向并不能ping通
[root@docker ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

#查看tomcat03域名解析,在这里发现了
[root@docker ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	tomcat02 5b4808dc2295                     
172.17.0.4	d76cfa3d60f0

自定义网络

#查看当前默认网络
[root@docker ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
b3d0bef7a944   bridge    bridge    local
221c3cbd3e0a   host      host      local
7b1beaf36869   none      null      local
#我们直接启动的命令 --net bridge,而这个就是我们的docker 0
[root@docker ~]# docker run -d -P --name tomcat01 --net bridge tomcat

#docker 0特点:默认,域名不能访问
#可以自定义一个网络!

#-创建一个网络create,桥接模式,子网192.168.0.0/16(255*255=65535) 网关192.168.0.1 名字为mynet
[root@docker ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

[root@docker ~]# docker network ls
[root@docker ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "1bb64d5ae9592b73e6521e9ff4686a99372bc88f1208cc05620f689e62a73bbb",
        "Created": "2021-06-26T21:40:47.133399129+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

#启动两个容器进行测试自己配置的网络
[root@docker ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
[root@docker ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
[root@docker ~]# docker network inspect mynet

在这里插入图片描述

  • 我们自定义的网络Docker都已经帮我们维护好了对应的关系,推荐平时这样使用网络
    • 不同的集群使用不同的网络,保证集群时安全和健康的!
#默认的docker0 是无法通过服务区ping通的,自己创建的网络可以互相ping通
#再次测试ping连接,现在不使用--link也可以ping名字
[root@docker ~]# docker exec -it tomcat-net-01 ping tomcat-net-02

网络连通

  • 测试如下图能否实现?
    在这里插入图片描述
[root@docker ~]# docker run -d -P --name tomcat01 tomcat
[root@docker ~]# docker run -d -P --name tomcat02 tomcat

#结论是无法ping通
[root@docker ~]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
  • 使用connect将容器连接到网络
    在这里插入图片描述
docker network connect [OPTIONS] NETWORK CONTAINER

#测试打通tomcat01 - mynet
[root@docker ~]# docker network connect mynet tomcat01

[root@docker ~]# docker network inspect mynet

#连通之后,就是将tomcat01放到了mtnet网络下, 一个容器两个IP地址

在这里插入图片描述

  • 结论:假设要跨网络操作,就需要使用connect进行联通!
#再次测试,能够ping通,完成!
[root@docker ~]# docker exec -it tomcat01 ping tomcat-net-01

部署Redis高可用集群

三主三从配置

#创建redis网卡
[root@docker ~]# docker network create redis --subnet 172.38.0.0/16
[root@docker ~]# docker network inspect redis

#编写脚本进行redis配置,通过脚本创建六个redis配置
[root@docker ~]# vim redis.sh
#!/bin/bash
#通过for循环循环6次
for port in $(seq 1 6)
do
#创建redis配置文件路径
mkdir -p /mydata/redis/node-${port}/conf
#创建redis配置conf配置文件
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF > /mydata/redis/node-${port}/conf/redis.conf
port 6379                                                   #容器端口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}                       #连接具体的IP
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

#等待脚本执行完成返回执行成功
wait
if [[ $? -eq 0 ]]
        then
                echo "Successfully!"
fi
[root@docker ~]# chmod +x redis.sh
[root@docker ~]# ./redis.sh
Successfully!

#脚本执行完成后的检查
[root@docker redis]# ls
node-1  node-2  node-3  node-4  node-5  node-6

#启动redis-1
[root@docker ~]# docker run -p 6371:6379 -p 16371:16379 --name redis-1 \\                    
-v /mydata/redis/node-1/data:/data \\
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \\
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#-d:后台运行 网络使用redis的网络 --ip 绑定ip redis版本使用5.0.9 通过redis.conf文件启动

#启动redis-2
[root@docker ~]# docker run -p 6372:6379 -p 16372:16379 --name redis-2 \\                    
-v /mydata/redis/node-2/data:/data \\
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \\
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

#启动redis-3
[root@docker ~]# docker run -p 6373:6379 -p 16373:16379 --name redis-3 \\                    
-v /mydata/redis/node-3/data:/data \\
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \\
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

#启动redis-4
[root@docker ~]# docker run -p 6374:6379 -p 16374:16379 --name redis-4 \\                    
-v /mydata/redis/node-4/data:/data \\
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \\
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

#启动redis-5
[root@docker ~]# docker run -p 6375:6379 -p 16375:16379 --name redis-5 \\                    
-v /mydata/redis/node-5/data:/data \\
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \\
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

#启动redis-6
[root@docker ~]# docker run -p 6376:6379 -p 16376:16379 --name redis-6 \\                    
-v /mydata/redis/node-6/data:/data \\
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \\
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#创建集群
#进入redis-1节点
[root@docker ~]# docker exec -it redis-1 /bin/sh
/data # 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
#--cluster-replicas 集群分片
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: 2415a4302736f6d044d50724c7bee2634817969a 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 6ac9297fe1c833887d41da36294d219aa462c4f3 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: a475b036f4849d76bc3e201a18a32e9b84b0a8a3 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: 51172257f8e7e739b30b7e0c365391e93057d842 172.38.0.14:6379
   replicates a475b036f4849d76bc3e201a18a32e9b84b0a8a3
S: 4a2140ab2428337a106162c08477671e626a801f 172.38.0.15:6379
   replicates 2415a4302736f6d044d50724c7bee2634817969a
S: 9e60f2b469e0449c942705af9c5ee03657c762b3 172.38.0.16:6379
   replicates 6ac9297fe1c833887d41da36294d219aa462c4f3
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: 2415a4302736f6d044d50724c7bee2634817969a 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: a475b036f4849d76bc3e201a18a32e9b84b0a8a3 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: 6ac9297fe1c833887d41da36294d219aa462c4f3 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 4a2140ab2428337a106162c08477671e626a801f 172.38.0.15:6379
   slots: (0 slots) slave
   replicates 2415a4302736f6d044d50724c7bee2634817969a
S: 9e60f2b469e0449c942705af9c5ee03657c762b3 172.38.0.16:6379
   slots: (0 slots) slave
   replicates 6ac9297fe1c833887d41da36294d219aa462c4f3
S: 51172257f8e7e739b30b7e0c365391e93057d842 172.38.0.14:6379
   slots: (0 slots) slave
   replicates a475b036f4849d76bc3e201a18a32e9b84b0a8a3
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

#连接redis
/data # redis-cli -c           #-c:不加c指单机 +c指集群
127.0.0.1:6379> cluster info   #查看集群信息
127.0.0.1:6379> cluster nodes  #查看节点信息

#为集群添加一个值
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK

#测试:停止master节点查看slave节点是否保存数据并成为master
[root@docker ~]# docker stop redis-3

#再次获取值
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"
172.38.0.14:6379> cluster nodes
  • Docker搭建redis集群完成!
    在这里插入图片描述

以上是关于Docker——Docker网络(Network)+ 部署Redis高可用集群的主要内容,如果未能解决你的问题,请参考以下文章

docker network

docker network

docker network

docker network

docker network命令详解

Testcontainers, Docker in Docker with custom network, 容器不属于网络