Docker第四篇Docker容器网络相关知识全解析
Posted 毛奇志
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker第四篇Docker容器网络相关知识全解析相关的知识,希望对你有一定的参考价值。
文章目录
- 一、前言
- 二、计算机网络
- 三、Network Namespace
- 四、其他两种类型的网络:host和null
- 五、两个机器/机器间 container运行在不同的centos中
- 六、总结全文学到的命令操作
- 七、尾声
一、前言
二、计算机网络
2.1 计算机网络理论知识
对于软件工程来说,只能接触到上层的网络协议,包括应用层和传输层,一般是 http dns tcp udp
对于网络工程来说,一般接触到下层的网络协议,包括网络层和数据链路层
网卡是计算机网络通信的基础,linux上,通过 ifconfig
或者 ip a
查看Linux上的网卡,查看网卡的ip
lo 本地网络
eth0 与互联网通信的网卡
eth1 与局域网通信的网卡
docker docker的网卡
2.2 Linux网卡灵活操作
2.2.1 网卡配置文件
各个网卡的作用:计算机能与外界通信的硬件支持,每个网卡有唯一的MAC地址。
各个网卡的配置文件(该配置文件可以修改):在Linux中网卡对应的其实就是文件,所以找到对应的网卡文件即可,比如:cat /etc/sysconfig/network-scripts/ifcfg-eth0
cd /etc/sysconfig/network-scripts/
2.2.2 网卡上增删IP地址
这里 lo 是本地网卡,ens33是与互联网通信的网卡,同一个网卡上可以挂多个IP地址的,现在我们在 ens33
cat /etc/sysconfig/network-scripts/ifcfg-ens33
# IP地址的查看、新增和删除操作
ip addr
ip addr add 192.168.100.251/24 dev ens33
ip addr delete 192.168.100.251/24 dev ens33
ip addr delete 192.168.100.251/24 dev ens33
2.2.3 网卡状态:UP DOWN UNKNOWN
ifdown ens33
ifup ens33
小结:关于Linux上网卡操作,包括
(1) 网卡配置文件
(2) 网卡绑定IP地址
(3) 网卡状态:UP DOWN UNKNOWN
三、Network Namespace
3.1 Network Namespace
docker = 网卡 + namespace
每个docker container 通过 namespace/cgroup 来实现隔离,network namespace的管理:
ip netns list # 查看本机docker的network namespace列表
ip netns add ns1 # 新增本机docker的network namespace
ip netns delete ns1 # 删除本机docker的network namespace
ip netns exec ns1 ip a # 查看本机docker的network namespace上面的IP列表
查看一下新建network namespace,这里发现会默认自带一个 lo 本地网卡
ip netns exec ns1 ip a
Docker中的network namespace 上面的本地网卡 lo 就是根据 linux 上的本地网卡 lo 创建的
所以,如下,网络隔离出来了(linux的网络隔离和 network namespace (ns1) 的网络隔离)
ip netns exec ns1 ip link show
无论是linux还是 docker network namespace ,lo 都是表示 回环地址/本地地址
network namespace 创建就默认带了一个 lo 本地回环地址
网卡是开发人员能接触的操作网络的单元,需要增加一个通信的网卡,将两个 network namespace , ns1 ns2 实现通信,即如下效果
这种技术就是 veth pair ,英文全称 Vitual Ethernet Pair ,使用这样创建出来就是默认能够连通的,表示一次创建成对的两个可以通信的网卡,分别给 ns1 ns2,即如下:
创建一对(两个)可以通信网卡,分别给ns1 和 ns2 ,这两个 network namespace 就可以通信了
创建一个pair 然后分配给ns
ip link add veth-ns1 type veth peer name veth-ns2
ip link show
创建好了,分配
ip link show
ip link set veth-ns1 netns ns1
ip link show
ip netns exec ns1 ip link
继续,将 veth-ns2 分配给 ns2
ip link show
ip link set veth-ns2 netns ns2
ip link show
ip netns exec ns2 ip link
完成了,pair技术
开始给ns1 ns2 新增的 veth-pair 网卡 新增 ip 地址,如下:
# 给network namespace ns1 添加 IP 地址 (IP地址和设备名/网卡名)
ip netns exec ns1 ip addr add 192.168.100.11/24 dev veth-ns1
ip netns exec ns1 ip a
# 给network namespace ns1 启用网卡 veth-ns1
ip netns exec ns1 ip link set veth-ns1 up
ip netns exec ns1 ip a
ip link # 查看简要IP信息
ip a # 查看详细IP信息
同样给 ns2 也加上
ip netns exec ns2 ip addr add 192.168.100.12/24 dev veth-ns2
ip netns exec ns2 ip a
ip netns exec ns2 ip link set veth-ns2 up
ip netns exec ns2 ip a
好了 ip地址有了
/24 前面就是具体的全的ip地址,不是三位
ip netns exec ns1 ping 192.168.100.12
ip netns exec ns2 ping 192.168.100.11
两个ip地址 ping ,ping通了
完成这个图片的需求,如下:
3.2 从 Network Namespace 转到 Docker Container
docker run -d --name tomcat01 -p 8081:8080 tomcat
docker run -d --name tomcat02 -p 8082:8080 tomcat
docker stop container-id # docker ps 查看 container-id
docker rm container-id # docker ps 查看 container-id
两个独立的容器可以ping通 底层是network namespace支持的
解释:创建的容器默认带了一个 network namespace
两个docker容器,虽然网络可以通,但是不是 pair 技术。
理由:两个容器内使用 ip a
查看,发现两个tomcat 的网卡不同,所以是两个network namespace ,如下图
这里使用的是 docker exec -it tomcat01 ifconfig 和 docker exec -it tomcat02 ifconfig ,查看到的是两个container的ip,也可以使用 docker exec -it tomcat01 ip a 和 docker exec -it tomcat02 ip a ,查看两个container的网卡
docker exec -it tomcat01 ip a
docker exec -it tomcat02 ip a
对于 veth-pair 技术来说,网卡一定名称是连续的才是一对,比如,这就是一对pair的组件
则两个container 建立计算机网络通信是通过linux中转的(而不是像两个network namespace一样,直接通信),如下:
我们开始验证一下上图,即 两个container 建立计算机网络通信是通过linux中转的 。
yum install bridge-utils
brctl show
ip a
所以,docker0 tomcat01 mysql tomcat02 四个的ip地址应该是同一网段的,下图是 Docker 通信的精髓
如果在增加一个 mysql或者tomcat03 ,那么 linux 的 docker0 上应该再增加一个网卡,一个 veth-pair 对
验证一下
docker run -d --name tomcat03 -p 8083:8080 tomcat # linux执行,运行tomcat03
docker exec -it tomcat03 bash # linux执行,进入tomcat03
apt-get update # tomcat03容器内执行,更新apt-get
apt-get install net-tools # tomcat03容器内执行,安装ifconfig命令
apt-get install iputils-ping # tomcat03容器内执行,安装ping命令
ifconfig # tomcat03容器内执行,查看tomcat03的ip地址
ping 172.17.0.2 # tomcat03容器内执行:ping tomcat01
ping 172.17.0.3 # tomcat03容器内执行:ping tomcat02
ip a # linux执行,查看linux上的网卡是不是增加了一个
brctl show # linux执行,查看linux的桥接docker0下面的网卡是不是增加了一个
docker network ls # linux执行,查看linux的network namespace
docker 各个container 通过这个docker0 通信,桥接两结果 (底层 veth-pair 技术)
(1) linux 到 container可以通
(2) container1 到 container2 可以通
3.3 自定义Network Namespace
docker0 使用的是 桥接的网络的,是桥接在linux上的打点
docker0 是一个bridge类型
docker network ls
docker network inspect bridge
也可以自己创建一个 bridge类型的
docker network ls
docker network create my-net
docker network ls
docker network inspect my-net
使用刚刚新建的自定义的network namespace,如下
docker network create tomcat-net
docker network ls
docker run -d --name custom-net-tomcat --network tomcat-net tomcat
docker exec -it custom-net-tomcat bash
apt-get update
apt-get install net-tools
apt-get install iputils-ping
exit
docker exec -it custom-net-tomcat ifconfig
docker network ls
docker network inspect tomcat-net
默认生成的docker0 是一个bridge类型的网络,如果 docker run 这里的 --network 不指定就是docker0
两个container不是同一个linux网卡,一个是默认网卡bridge,一个是自定义网卡 tomcat-net ,这种情况下相互ping不通
docker exec -it custom-net-tomcat ping 172.17.0.3
一个是docker0(即bridge) 一个custom-net-tomcat
3.4 不同network namespace通信
如果容器太多了,这个网段下面放满了, 一个 bridge 不够用,应该怎么办
重新创建另一个 bridge ,但是这个bridge 上的container 和 之前bridge 上的container 是网络不通的
ping ip 这种只有一行就是不通,control+c 会得到 100% loss
ping 域名 这种只有一行是域名解析对了,只是 ip 网络不同而已
上图中,两个红色的表示 linux 上的两个 bridge,白色表示 docker container 容器
# docker network connect 是 network 添加命令,写死 (docker network 是命令,加上connnet表示添加)
# 第一个参数 tomcat-net 表示network namespace,第二个参数 tomcat01 表示 containr-name
# 表示将 container-name 使用这个 network namespace
docker network connect tomcat-net tomcat01
docker network ls
docker network inspect tomcat-net
docker exec -it custom-net-tomcat ping 172.19.0.3
docker exec -it tomcat01 ifconfig
3.5 通过名称访问
不是网络不通,是域名解析不了,默认的桥接 bridge/docker0 是不带域名解析能力的,但是自定义/自己创建的network namespace是带有域名解析能力的
用 自定义的 network namespace 新建两个容器,发现可以根据名称 ping 通
同一桥接,docker0里面的两个container 名字解析不了
但是自定义的桥接,里面的两个container 名字可以解析 自定义的bridge默认增加一条dns解析
在默认的 docker0 里面,可以用 --link 这种单向的
小结:生产上更加推荐 自定义bridge ,而不是 docker0 + 单向link 来完成
自定义bridge 类似于 k8s 的namespace,可以按 名字 来访问
局限:所有的docker都在同一台 centos 机器上
一个容器可以绑定两个bridge ,完成与另一个 bridge 的container 通信
3.6 端口映射:容器的端口映射到的centos
现在所有的网络通信都是
(1) centos 与 容器container 的通信(ping)
(2) 容器container 与 容器container 的通信(ping)
现在还需要 外网windows 与 容器container 的通信,我们知道,外网windows和宿主机centos是可以通信的,要想和container通信,就是需要将container的端口映射到centos就可以了
实际上我们已经做了
docker run -d --name tomcat01 -p 8081:8080 tomcat
docker run -d --name tomcat02 -p 8082:8080 tomcat
docker run -d --name tomcat03 -p 8083:8080 tomcat
http://192.168.100.151:8081
http://192.168.100.151:8082
http://192.168.100.151:8083
四、其他两种类型的网络:host和null
host : 该容器的ip 直接将 宿主机的ip 抄袭过来
优点:不需要 端口映射了 host = bridge + 端口映射
缺点:centos 端口是有限的,不需要暴露出来的,就不要使用 host
null: 只有本地回环地址,这个docker container从来不与外界通信
五、两个机器/机器间 container运行在不同的centos中
需求:container运行在不同的centos中,两个机器/机器间 docker container的通信
同一机器:network namespace,三种网络方式 bridge host null
不同机器:NAT 网络地址转换 vxlan
vxlan
多机网络通信的问题,底层的一个实现技术是:overlay
docker 上第四种网络技术 overlay vxlan,如下图:
六、总结全文学到的命令操作
总结一下和计算机网络网络有关的linux命令和docker命令,如下:
6.1 linux操作 (ip和网卡)
# ip地址的查看、新增、删除
ifconfig
ip addr (也可以写成 ip a,ip a是简写)
ip addr add 192.168.100.251/24 dev ens33
ip addr delete 192.168.100.251/24 dev ens33
# 网卡配置文件(一个网卡一个配置文件)
cd /etc/sysconfig/network-scripts/ (查看配置文件,白色是文件,绿色可执行文件,蓝色目录)
# 网卡的启用和停止 (网卡三种状态 up down unknown)
ifdown ens33
ifup ens33
6.2 network namespace操作
docker ( 从network namespace 到 docker container 的桥接网络,底层技术都是 veth-pair 这种一对网卡的方式,前者network namespace之间是直接通,后者docker container之间是通过linux实现网络通信)
# network namespace
ip netns list # 查看本机docker的network namespace列表
ip netns add ns1 # 新增本机docker的network namespace
ip netns delete ns1 # 删除本机docker的network namespace
ip netns exec ns1 ip a # 查看本机docker的network namespace上面的IP列表(简要)(默认自带一个 lo 本地网卡)
ip netns exec ns1 ip link show # 查看本机docker的network namespace上面的IP列表(简要)(默认自带一个 lo 本地网卡)
小结:network namespace的命令都是 ip netns 固定开头,然后就是 list 查询列表,add 新增, delete 删除,还有 exec ns-name 表示查看某个网络命名空间的具体信息 (ip addr是详细(包含ip),ip link show是简要(不包含ip))
# 创建一个 veth-pair 对,包含两个网卡,这两个网卡可以相互通信,将这两个网卡分配给两个network namespace
# 在linux机器上,新建一个 veth-pair 关键字是 add xxx type xxx name xxx
ip link add veth-ns1 type veth peer name veth-ns2
ip link show # 查看linux上的网卡信息,ip addr (ip a)/ ip link show (ip link)/ ifconfig
ip link show # 查看linux上的网卡信息,ip addr (ip a)/ ip link show (ip link)/ ifconfig
ip link set veth-ns1 netns ns1 # 将linux的网卡 veth-ns1 使用到 网络命名空间 ns1 上
ip link show # 查看linux上的网卡信息,ip addr (ip a)/ ip link show (ip link)/ ifconfig
ip netns exec ns1 ip link # 查询指定命名网络命名空间的简要信息
ip link show # 查看linux上的网卡信息,ip addr (ip a)/ ip link show (ip link)/ ifconfig
ip link set veth-ns2 netns ns2 # 将linux的网卡 veth-ns2 使用到 网络命名空间 ns2 上
ip link show # 查看linux上的网卡信息,ip addr (ip a)/ ip link show (ip link)/ ifconfig
ip netns exec ns2 ip link # 查询指定命名网络命名空间的简要信息
# 给network namespace ns1 添加 IP 地址 (IP地址和设备名/网卡名)
ip netns exec ns1 ip addr add 192.168.100.11/24 dev veth-ns1 # 指定网络命名空间指定网卡上听添加IP地址
ip netns exec ns1 ip a # 查询指定命名网络命名空间的详细信息
# 给network namespace ns1 启用网卡 veth-ns1
ip netns exec ns1 ip link set veth-ns1 up # 指定网络命名空间启用网卡
ip netns exec ns1 ip a # 查询指定命名网络命名空间的详细信息
ip netns exec ns2 ip addr add 192.168.100.12/24 dev veth-ns2 # 指定网络命名空间指定网卡上听添加IP地址
ip netns exec ns2 ip a # 查询指定命名网络命名空间的详细信息
ip netns exec ns2 ip link set veth-ns2 up # 指定网络命名空间启用网卡
ip netns exec ns2 ip a # 查询指定命名网络命名空间的详细信息
小结:一个linux机器上,有多个网络命名空间 (网络命名空间可以新建删除查询列表,并可以查询每个网络命名空间的详细和简要信息);一个网络命名空间可以挂上多个网卡,一个 veth-pair 对是两个网卡,可以通信的两个网卡;一个网卡可以有多个IP地址。
小结:linux – 网络命名空间 – 网卡 – IP地址
6.3 docker container 的桥接网络相关操作
yum install bridge-utils
brctl show
ip a
# 命令是docker network,可以查询列表,可以新建和删除,还可以查询这个network里面有哪些container
docker network ls
docker network create my-net
docker network ls
docker network inspect my-net
docker run -d --name tomcat03 -p 8083:8080 tomcat # linux执行,运行tomcat03
docker exec -it tomcat03 bash # linux执行,进入tomcat03
apt-get update # tomcat03容器内执行,更新apt-get
apt-get install net-tools # tomcat03容器内执行,安装ifconfig命令
apt-get install iputils-ping # tomcat03容器内执行,安装ping命令
ifconfig # tomcat03容器内执行,查看tomcat03的ip地址
ping 172.17.0.2 # tomcat03容器内执行:ping tomcat01
ping 172.17.0.3 # tomcat03容器内执行:ping tomcat02
ip a # linux执行,查看linux上的网卡是不是增加了一个
brctl show # linux执行,查看linux的桥接docker0下面的网卡是不是增加了一个
docker network ls # linux执行,查看linux的network namespace
# 都是network namespace,只是前者是在docker里面的network namespace,后者是不在docker里面的network namespace
# 一个网络命名空间network namespace就是表示一个网关,下面可以有多个docker container
docker network list # 有实用性,表示的是网关列表/网络命名空间列表,每个网关下面可以有多个docker container
ip netns list # 无实用性,表示的网关列表/网络命名空间列表,与docker container关闭不紧密
network namespace 单独使用,不接入到docker container,没有三种网络类型之说
接入到docker container,就有了 bridge host null 三种类型
增加或删除一个桥接,其实就是增加或删除一个网络命名空间
同一桥接内可以通信,就是同一网络命名空间内可以通信,就是同一网关可以通信,就是同一子网内可以通信,这是可以解释的通的
一个linux机器上可以有多个桥接/多个网络命名空间,一个桥接可以有多个网卡,一个网卡可以有多个IP地址
linux – 桥接(网络命名空间) – 网卡 – IP
桥接增删查改 (就是网络命名空间的增删查改)
docker network ls
docker network create my-net
docker network ls
docker network inspect my-net
brctl show # 查看桥接列表(一个桥接可以有多个网卡)
网卡增删查改 (这里指linux上的网卡增删查改,主要是查)
查看linux上的网卡信息
ip addr (ip a)/ ip link show (ip link)/ ifconfig
每次增加一个容器 tomcat03 ,就会增加 一个 veth-pair ,两个网卡,一个在tomcat03上,一个在linux上,此时 brctl show
列表也可以看到多了一个网卡,就是linux上增加的那个网卡, ip addr 也可以看到多了一个网卡,就就是 linux 上增加的那个网卡 (但是不会增加一个桥接,所以 docker network list 不会增加,brctl show 也不会增加)
6.4 单机 docker container 的其他两种网络通信方式(host null)
host : 该容器的ip 直接将 宿主机的ip 抄袭过来
优点:不需要 端口映射了 host = bridge + 端口映射
缺点:centos 端口是有限的,不需要暴露出来的,就不要使用 host
null: 只有本地回环地址,这个docker container从来不与外界通信
七、尾声
Docker容器网络相关知识全解析,完成了。
以上是关于Docker第四篇Docker容器网络相关知识全解析的主要内容,如果未能解决你的问题,请参考以下文章