目录
1. Docker四种网络模式
1)bridge模式(默认)
Docker使用Linux虚拟网络技术在宿主机虚拟一个名为docker0的虚拟网桥。
Docker启动一个容器时会根据Docker0网桥的网段分配给容器一个IP地址(可通过:docker inspect 容器名/ID 查看容
器地址),同时Docker网桥作为每个容器的默认网关,虚拟网桥的工作方式和物理交换机类似,因为在同一宿主机内的容器都接入同一个网桥,这样主机上的所有容器就通过交换机(docker0)连在了一个二层网络中直接通信。
当创建一个 Docker 容器的时候,同时会创建了一对 vethpair接口(当数据包发送到一个接口时,另外一个接口也可
以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通
过直接容器IP访问到容器,如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主机。
示例:创建容器并指定bridge模式
格式:--net=bridge
启动一个nginx容器
[root@localhost ~]# docker run -id --name=nginx --net=bridge -p 80:80 nginx:1.20.2
7c54ae080cd5d8c898877956c156208a17e7473c8ea860ffa0796c9937ca5ab5
查看容器网络
[root@localhost ~]# docker inspect nginx|grep bridge
"NetworkMode": "bridge",
"bridge": {
使用场景:当您需要多个容器在同一个Docker宿主机上进行通信时,使用自定义的桥接网络模式(bridge)是最佳选择。
2)Host模式
在Host类型的网络中,容器不会虚拟出自己的网卡,而是与物理机共享网络,拥有物理机的IP地址和网卡信息,而容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
Host最大的优势就是网络性能比较好,不需要进行NAT,可以直接使用宿主机的IP地址/端口与外界通信。
示例:创建容器并指定Host模式
提示:此模式无法通过-p为容器指定端口,容器内部的服务使用的是宿主机端口,各个host模式的容器不能有端口冲突。
格式:--net=host
启动一个nginx容器,指定host模式
[root@localhost ~]# docker run -id --name=nginx --net=host nginx:1.20.2
13e549e99f0ce9b857564fe1c276e11af4639d2fe9043ae3febf8e331486a3de
查看容器和宿主机开启的端口
查看容器网络
[root@localhost ~]# docker inspect nginx_host
...
host": {
使用场景:当容器网络堆栈不应与Docker主机隔离但又希望隔离容器的其他方面(cgroup,unix file system)时,使用主机网络模式(host)是最佳选择。
3)Container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个网络,而不是和宿主机共享。
新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。
同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo(回环) 网卡设备通信。
示例:创建容器并与其他容器公用网络
格式:--net=container:其它容器名/其它容器ID
[root@localhost ~]# docker run -it --name=ngx_container --net=container:nginx nginx:1.20.2 /bin/bash
4)None模式
None类型的网络,即没有网络,Docker容器不会设置容器内网络的任何信息,不会对网络进行任何配置,但是我们自己可以给该容器添加配置,给予其网络环境。
示例:创建容器并使用None模式
格式:--net=none
[root@localhost ~]# docker run -id --name=nginx_none --net=none nginx:1.20.2
查看容器网络
[root@localhost ~]# docker inspect nginx_none
...
"none": {
2. Docker自定义网络
自定义容器网络可使不同的集群使用不同的网络,避免相互影响。
查看所有docker网络:docker network ls
[root@localhost ~]# docker network --help
connect 将某个容器连接到一个docker网络
create 创建一个docker局域网络
disconnect 将某个容器退出某个局域网络
inspect 显示某个局域网络信息
ls 显示所有docker局域网络
prune 删除所有未引用的docker局域网络
rm 删除docker网络
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
网络 ID 网络名称 网络模式 作用域
自定义docker网络
docker network create --driver bridge --subnet 192.168.1.0/24 --gateway 192.168.1.254 mynet
解释说明:
create #创建网络
--driver #定义网络模式
--subnet #定义网络IP
--gateway #指定网关
mynet #是自己定义的网络名称
删除自定义网络
[root@localhost ~]# docker network rm mynet
示例:创建一个自定义网络
[root@docker ~]# docker network create --driver bridge --subnet 172.16.0.0/16 --gateway 172.16.0.254 mynet
创建容器使用自定义网络:
--net=名称
--ip 地址 #定义容器IP,如果不自定义,将默认分配
启动一个nginx容器,使用自定义网络,容器IP地址指定为172.16.0.10
[root@docker ~]# docker run -id --name=ngx_mynet --net=mynet --ip 172.16.0.10 -p 80:80 nginx:1.20.2
查看网络详细信息:docker network inspect 网络名称/ID
[root@localhost ~]# docker network inspect mynet
容器加入网络:docker network connect 网络名
自定义网络和默认网络是不通的,这样就起到了隔离的作用,那如果我们想要打通这两个网络要使用 connect 将容器加入到该网络
容器加入网络
[root@localhost ~]# docker network connect mynet nginx
查看容器网络(该容器有两个网络)
[root@localhost ~]# docker inspect nginx
...
"bridge": {
"mynet": {
[root@localhost ~]# docker exec -it nginx /bin/bash
root@3a067c8e10f0:/# hostname -I
172.17.0.2 172.16.0.1
提示:打通后,默认网络和自定义网络就可以互相通信
删除网络:docker network rm 网络名
[root@localhost ~]# docker network rm mynet
提示:如果有其他容器使用该网络,需要先清理容器。
3. Docker容器互联--link
容器之间如果想要通过容器名称进行通信的话,可以通过--link来实现容器互联(单方向互联)
格式:- -link name:alias
name表示要链接的容器的名称
alias是别名(也可以不指定别名)
示例:启动centos_1容器
[root@localhost ~]# docker run -id --name=centos_1 centos:7 /bin/bash
启动centos_2容器,并与centos_1互联
[root@localhost ~]# docker run -id --name=centos_2 --link centos_1 centos:7 /bin/bash
进入容器验证(注意:是单方向互联)
[root@localhost ~]# docker exec -it centos_2 /bin/bash
[root@d6f1a8fd8cd2 /]# ping centos_1
查看容器的/etc/hosts文件
注:当容器创建并启动后,会自动在hosts文件里添加解析,对于容器来说,它自己知道自己的IP地址,在没有添加--link的时候是没有172.17.0.3的解析的,当添加--link的时候,这条会自动添加。
4. Docker容器跨主机通信
docker默认的自定义网络的类型就是bridge,但是跨主机的时候bridge就明显不可用的
原生的docker跨主机通信方案有macvlan和overlay两种。
1. 什么叫Macvlan网络
macvlan 本身是 linxu kernel 模块,其功能是允许在同一个物理网卡上配置多个MAC地址,即多个interface,每个interface 可以配置自己的IP。macvlan 本质上是一种网卡虚拟化技术。
使用Macvlan需要注意以下几点:
容器直接连接物理网络,由物理网络负责分配IP地址,可能的结果是物理网络IP地址被耗尽,
另一个后果是网络性能问题,物理网络中接入的主机变多,广播包占比快速升高而引起的网络性能下降问题;
宿主机上的物理网卡(ens33)需要工作在 混乱模式下;前面说到,工作在混乱模式下的物理网卡,其MAC地址会失效,所以,此模式
中运行的容器并不能与外网进行通信,但是不会影响宿主机与外网通信;
从长远来看bridge网络与overlay网络是更好的选择,原因就是虚拟网络应该与物理网络隔离而不是共享。
Macvlan本身不创建网络,本质上首先使宿主机物理网卡工作在‘混杂模式’,这样物理网卡的MAC地址将会失效,所有二层网络中的流量物理网卡都能收到。接下来就是在这张物理网卡上创建虚拟网卡,并为虚拟网卡指定MAC地址,实现一卡多用,在物理网络看来,每张虚拟网卡都是一个单独的接口。
2. 什么叫做overlay网络
overlay网络用于连接不同机器上的docker容器,允许不同机器上的容器相互通信,同时支持对消息进行加密。
在dockerswarm集群环境(overlay)是最佳选择。
字面意思就是叠加的网络,指的就是在物理网络层上再搭建一层网络,通过某种技术再构建一张相同的网络,这张称为逻辑网。
也就是说我们想要两台主机的容器进行通讯,首先这两台主机自己要可以通讯,然后在这个物理机的基础之上部署一张逻辑层的网络,他具有物理网络的所有特性,跟物理网络一模一样。
VLAN是什么,我们想要划分网络就叫做VLAN,VLAN只是单纯的对物理网络进行划分,隔离ip,Mac。VLAN是划分广播域的最基础概念。
vxlan是在物理网络基础之上构建出来的网络,这个网络可以通过 vxlan进行划分,ip,Mac只需要在一个vxlan中就可以进行通讯。
因此,Overlay网络实际上是目前最主流的容器跨节点数据传输和路由方案。
3. Overlan环境准备
主机名 | IP地址 | 角色 |
docker0 | 192.168.0.10 | docker主机 |
docker1 | 192.168.0.11 | docker主机 |
consul | 192.168.0.12 | consul主机 |
注:每个节点安装Docker服务,每台宿主机的hostname必须不同。
4. 运行consul服务
Docker Overlay 网络需要一个 key-value数据库用于保存网络状态信息, 包括 Network、Endpoint(节点)、IP 等。
Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue软件,我们这里使用 Consul。
在consul主机执行如下命令
[root@consul ~]# docker run -d -p 8500:8500 -h consul --name consul --restart always progrium/consul -server -bootstrap
解释:
-server -bootstrap #指定运行模式(该模式指定本机为server端)
-h #设置容器主机名
--restart always #永远自动重启
progrium/consul #consul镜像
5. Docker节点加入consul
修改其他节点配置文件,使得每一台都通过本机的2376(docker监听端口)端口被转发到
192.168.0.12:8500,consul收集存储并使用这些信息实现网络一致。
docker0主机修改/usr/lib/systemd/system/docker.service文件,将文件中的ExecStart参数替换成如下参数(根据自己的环境修改consul地址)
[root@docker10 ~]# vim /usr/lib/systemd/system/docker.service
...
ExecStart=/usr/bin/dockerd \
-H unix:///var/run/docker.sock \
-H tcp://0.0.0.0:2376 \
--clusterstore=consul://192.168.0.12:8500 \
--clusteradvertise=ens32:2376
解释:
--cluster-store #指定consul地址
--clusteradvertise #指定本机网卡及端口
-----------------------------------------------------------------------------
或者修改docker配置文件,哪一种方式都可以
[root@test ~]#vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://4v9uc68t.mirror.aliyuncs.com"],
"insecure-registries": ["192..168.0.10:5000"],
"live-restore": true,
"hosts":["tcp://0.0.0.0:2376","unix:///var/run/docker.sock"],
"cluster-store": "consul://192..168.0.12:8500", #consul在哪一台主机就写那一台
"cluster-advertise": "192..168.0.12:2376" #本地宿主机的监听端口
}
加载配置并重启服务
[root@docker0 ~]# systemctl daemon-reload
[root@docker0 ~]# systemctl restart docker
直接将配置文件拷贝到docker1与consul主机即可
#拷贝到docker1主机
[root@docker0 ~]# scp /usr/lib/systemd/system/docker.service root@192.168.1.11:/usr/lib/systemd/system/docker.service
#拷贝到consul主机
[root@docker0 ~]# scp /usr/lib/systemd/system/docker.service root@192.168.1.12:/usr/lib/systemd/system/docker.service
docker1重启docker服务
[root@docker1 ~]# systemctl daemon-reload
[root@docker1 ~]# systemctl restart docker
consul重启docker服务
[root@consul ~]# systemctl daemon-reload
[root@consul ~]# systemctl restart docker
6. 访问consul
最后我们可以通过浏览器访问consul服务:http://192.168.0.12:8500/
不同主机的docker已经添加到了一起。
7. 创建Overlan网络
在任意一个节点创建一个网络,我们在docker0创建一个网络
[root@docker0 ~]# docker network create -d overlay myovernet
提示:网络默认使用的10.0.0.0/24网段,如果需要自定义网络地址通过下边命令创建。(别跟宿主机在同一个网络,容易发生地址冲突)
docker network create -d overlay --subnet 172.16.1.0/24 --gateway 172.16.1.254 myovernet
8. 验证Overlan网络
这时候每一个节点都会有这个网络
#docker10主机查看
#docker10主机查看
[root@docker10 ~]# docker network ls
myovernet overlay global
#docker11主机查看
[root@docker11 ~]# docker network ls
60210366228b myovernet overlay global
#consul主机查看
[root@consul ~]# docker network ls
60210366228b myovernet overlay global
Overlan默认的网段是10.0.0.0/24
[root@docker11 ~]# docker network inspect
myovernet
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
docker0、docker1、consul分别创建centos容器测试跨主机通信
[root@docker10 ~]# docker run -it --name=c10 --net=myovernet centos:7 /bin/bash
[root@docker11 ~]# docker run -it --name=c11 --net=myovernet centos:7 /bin/bash
[root@consul ~]# docker run -it --name=c12 --net=myovernet centos:7 /bin/bash
测试连通性:docker自定义的网落是自带域名解析的,所以直接ping名字
[root@097d21377fcc /]# ping c11
[root@097d21377fcc /]# ping c12
查看容器IP
[root@097d21377fcc /]# hostname -I
10.0.0.2 172.18.0.2
#注:10.0.0.2是容器内部的地址,172.18.0.2是容器与宿主机之间的网关,如果宿主机可以访问外网,容器借助该网关转换成宿主机IP访问外网。