说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!
接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/105335943
说明: 运行nginx容器,nginx服务默认绑定到容器172.17.0.4 ip上,将172.17.0.4端口映射到本机linux端口,就不用访问172.17.0.4了,直接访问本地localhost 127.0.0.1即可,同理还可以通过博主这台centos7虚拟机的ip来访问
UnderLay指的是物理网络,它由物理设备和物理链路组成。常见的物理设备有交换机、路由器、防火墙、负载均衡、入侵检测、行为管理等,这些设备通过特定的链路连接起来形成了一个传统的物理网络,这样的物理网络,我们称之为UnderLay网络。
OverLay其实就是一种隧道技术,VXLAN,NVGRE及STT是典型的三种隧道技术,它们都是通过隧道技术实现大二层网络。将原生态的二层数据帧报文进行封装后在通过隧道进行传输。总之,通过OverLay技术,我们在对物理网络不做任何改造的情况下,通过隧道技术在现有的物理网络上创建了一个或多个逻辑网络即虚拟网络,有效解决了物理数据中心,尤其是云数据中心存在 的诸多问题,实现了数据中心的自动化和智能化。
UnderLay是底层网络,负责互联互通而Overlay是基于隧道技术实现的,overlay的流量需要跑在underlay之上。
参考文章《浅谈SDN中的OverLay与UnderLay技术》&&《Underlay、Overlay、大二层介绍》
说明:在上一节中通过在同一个docker同一台linux机器上实现不同的容器redis和flask-redis是如何进行通信的,那么这两个容器在不同的linux机器上(分别部署在不同的linux机器上)试想能不能进行通信,其实是肯定可以通信的。
列举:有两台linux机器,要想让这两台linux机器中的docker container进行互相通信的前提是这两台linux机器是能够相互ping通的,那么linux1机器会向linux2机器发送数据包,这个数据包包含的网络分层为三层即HTTP层——TCP层——IP层,IP层包含src ip也就是192.168.88.212;dst ip为linux2机器的ip也就是192.168.88.211,在linux1机器上部署的redis容器(ip 172.17.0.2)要想访问部署在linux2机器上的flask-redis容器(ip 172.17.0.3)则将redis容器的数据包(src ip 172.17.0.2 dst ip 172.17.0.3 )放到linux1机器向linux2机器发送的数据包网络分层中的HTTP层,这样的话redis容器的数据包就会随着linux1机器的数据包发送到linux2机器上,到linux2机器上后,则会将linux1机器发送的数据包进行解包,解包后发现http层的redis数据包中的dst ip 172.17.0.3为本机linux2机器中的flask-redis容器的ip,则就会将这个数据包转发到flask-redis容器中,同理linux2机器上的flask-redis容器访问linux1机器上的redis容器也是这个道理,即这两个容器在不同的linux机器上实现了互相通信,以上过程的则是通过VXLAN方式实现的隧道技术
说明: 要实现多机器中的不同容器进行互相通信需要借助etcd(分布式键值数据库),之所以需要借助etcd的原因很简单,因为防止在不同的机器上创建的不同的容器所产生的IP地址不会被占用,通过etcd分布式存储就会帮我们去查看容器的IP以及name是被占用,占用的话会提示的。
1. 首先需要保证这两台linux机器的主机名不能一致,之前博主通过VMware 创建的centos7和centos7_2两台机器的主机名同为localhost,这样会导致手动运行dockerd指定cluster store参数会提示host name不唯一,所以博主将主机分别改为docker-node1和docker-node2
sudo hostnamectl set-hostname docker-node1
sudo hostnamectl set-hostname docker-node2
2. 保证两台linux机器能够互相ping通
3. 在centos7和centos7_2两台机器上下载解压etcd-v3.0.12压缩包并进入解压目录中,因为是从github上下载速度很慢,建议大家用迅雷进行下载
wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
cd etcd-v3.0.12-linux-amd64
4. 在centos7机器上运行一个名为docker-node1进程,192.168.88.212为centos7的IP,然后在centos7_2机器上运行一个名为docker-node2进程,192.168.88.211为centos7_2的IP
# 在centos7上
nohup ./etcd --name docker-node1 --initial-advertise-peer-urls http://192.168.88.212:2380 \
--listen-peer-urls http://192.168.88.212:2380 \
--listen-client-urls http://192.168.88.212:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.88.212:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.88.212:2380,docker-node2=http://192.168.88.211:2380 \
--initial-cluster-state new&
# 在centos7_2上
nohup ./etcd --name docker-node2 --initial-advertise-peer-urls http://192.168.88.211:2380 \
--listen-peer-urls http://192.168.88.211:2380 \
--listen-client-urls http://192.168.88.211:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.88.211:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.88.212:2380,docker-node2=http://192.168.88.211:2380 \
--initial-cluster-state new&
1. 先查看docker-node1的状态,没有问题健康的状态
./etcdctl cluster-health
2. 然后docker-node2状态,结果发现连接不上docker-node2 192.168.88.212 host
./etcdctl cluster-health
3. 导致docker-node2无法访问到docker-node1,说明docker-node1所在的centos7机器运行了防火墙,所以将其关闭,再次,检查cluster状态,都是健康的,搭建etcd集群成功
systemctl stop firewalld.service
firewall-cmd --state
sudo ./etcdctl member list
1. 停止docke-node1的docker服务,如果停止不了,则通过ps -ef | grep dockerd查看进程pid,使用sudo kill -9 pid直接杀死进程即可
sudo service docker stop
2. 启动docker-node1主机的docker服务,使用其本地的cluster store
# centos7
sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.88.212:2379 --cluster-advertise=192.168.88.212:2375&
3. 查看docker-node1主机的docker server服务启动成功
4. 停止docke-node2的docker服务
sudo service docker stop
5. 启动docker-node2的docker服务,使用其本地的cluster store,然后在docker-node1主机上会显示info信息docker-node2加入进来,也就是说docker-node1和docker-node2主机双方都知道了对方的存在
# centos7_2
sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.88.211:2379 --cluster-advertise=192.168.88.211:2375&
1. 在docker-node1主机上创建一个overlay的网络,然后在docker-node2主机上,查看网络,通过在docker-node1主机上创建的网络已经同步过来了,这是因为etcd的原因
sudo docker network create -d overlay my-overlay
2. 在docker-node2主机上通过./etcdctl 查看/docker/network/v1.0/network目录下的NETWORK ID,这个网络ID则是在docker-node1主机上创建的overlay的网络ID
1. 首先在创建redis容器之前,先查看test-demo的网络数据
sudo docker network inspect my-overlay
2. 在docker-node1主机上创建名为redis的redis服务容器,结果发现出错了提示Failed to deserialize netlink ndmsg: invalid argument 参数失效,即使提示这样,但容器是创建成功的,当在docker-node2主机上创建相同的容器则会提示容器已存在,此错误提示最终会导致在docker-node1和docker-node2两天主机上创建的容器不能通过容器name 互相ping通,即无法实现多容器应用的部署
docker run -d --name redis --net my-overlay redis
3. 为了解决该错误,博主试了很多种办法都不行,最终决定尝试升级CentOS内核版本为最新版本再进行验证
# 载入公钥
sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# 安装ELRepo
sudo rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
# 载入elrepo-kernel元数据
sudo yum --disablerepo=\* --enablerepo=elrepo-kernel repolist
# 查看可用的rpm包
sudo yum --disablerepo=\* --enablerepo=elrepo-kernel list kernel*
# 安装最新版本的kernel
sudo yum --disablerepo=\* --enablerepo=elrepo-kernel install -y kernel-ml.x86_64
# 删除旧版本工具包
sudo yum remove kernel-tools-libs.x86_64 kernel-tools.x86_64
# 安装新版本工具包
sudo yum --disablerepo=\* --enablerepo=elrepo-kernel install -y kernel-ml-tools.x86_64
4. 进行从头开始重复操作,在docker-node1主机上创建基于overlay的redis容器没有提示Failed to deserialize netlink ndmsg: invalid argument 错误,并且在docker-node2上创建相同network 及容器name同为redis的容器,提示在my-overlay网络中容器name已存在(因为在etcd cluster key-value中已经存在my-overlay network中已经存在名为redis的容器了)
docker run -d --name redis -net my-overlay redis
5. 博主现在在docker-node主机上创建基于centos image my-overlay network的 test1的容器,同理测试在docker-node2上创建相同name network的容器(为了不出现etcd的日志,这里重新连接docker-node1和docker-node2主机),那么和上面一样,在docker-node2主机上无法创建test1容器,因为已存在与my-overlay网络
docker run -d --name test1 --network my-overlay centos /bin/sh -c "while true; do sleep 3000; done"
6. 在docker-node2上创建overlay network test2容器,即肯定会创建成功
docker run -d --name test2 --network my-overlay centos /bin/sh -c "while true; do sleep 3000; done"
7. 此时查看overlay network元数据,容器中就存在redis、test1和test2,并能看到他们的ip地址
docker network inspect my-overlay
8. 通过容器ip及name来验证test1和test2容器连通性,因为redis容器也是基于my-overlay network的所以也是可以ping通的
docker exec test1 ping 10.0.0.4
docker exec test2 ping 10.0.0.3
docker exec test1 ping test2
docker exec test2 ping test1
docker exec test1 ping redis
docker exec test2 ping redis
在上一章节中,博主在docker-node1主机上已经创建并运行了redis容器,所以这里就不用再创建了
docker run -d --name redis -net my-overlay redis
1. 现在则需要在docker-node2主机上通过Dockerfile 构建一个image(也就是在第三章节多容器复杂应用的部署中的操作,只是将redis容器部署在docker-node1上而flask-redis容器部署在docker-node2主机上)
docker build -t cdtaogang/flask-redis .
2. 紧接着通过cdtaogang/flask-redis image创建基于my-overlay network的flask-redis容器
docker run -d --name flask-redis --network my-overlay -e REDIS_HOST=redis cdtaogang/flask-redis
1. 首先查看my-overlay network container 数据,在docker-node2主机上创建的flask-redis容器存在于my-overlay network
docker network inspect my-overlay
2. 进入flask-redis容器中,通过ping docker-node1主机上的redis容器name测试连通性没有问题,并且通过curl工具可以拉取到flask-redis容器运行app程序数据
docker exec -it flask-redis /bin/bash
3. 因为博主在创建flask-redis容器时没有做端口映射,所以当退出容器在使用curl工具拉取数据,则显示被拒绝
4. 删除容器,重新创建flask-redis容器并进行端口映射,测试在docker-node2主机上通过curl工具能够拉取到app数据
docker run -d -p 5000:5000 --name flask-redis --network my-overlay -e REDIS_HOST=redis cdtaogang/flask-redis
5. 现在测试在docker-node1主机上来通过curl工具拉取docker-node2主机上的运行flask-redis容器运行的app数据,也是可以拉取到的,没有任何问题
6. 现在查看docker-node1主机和docke-node2主机上查看本地network 会发现多了一个docker_gwbridge network,这个bridge network是链接到eth1网络接口的,具体可以在github上查看overlay network的架构说明