Docker——Docker网络(Network)+ 部署Redis高可用集群
Posted Pakho`
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker——Docker网络(Network)+ 部署Redis高可用集群相关的知识,希望对你有一定的参考价值。
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
,≈ 65535Docker
中的所有网络接口都是虚拟的,虚拟的转发效率高!(如:内网传递文件)- 只要容器删除,对应的网桥一对同样移除!
容器互联 (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高可用集群的主要内容,如果未能解决你的问题,请参考以下文章
Testcontainers, Docker in Docker with custom network, 容器不属于网络