系统学习Docker 践行DevOps理念 笔记(三)|Docker的网络
Docker的网络,是课程第四章的内容
1.本章概述和实验环境介绍
实验环境使用vagrant创建虚拟机,Vargantfile可以去docker-labs里面查看
2.网络基础回顾
一些基本的网络知识,略
3.Linux网络命名空间
3.1Linux网络命名空间
相关命令:
ip netns list
,列出现在有多少network namespace(netns)ip netns add test1
,添加一个netns,name是test1ip netns delete test1
,删除一个netnsip netns exec test1 ip a
,在test1这个netns下,执行ip a命令ip a
显示现在的网络设置ip link
,类似ip a,但是信息略少ip netns exec test1 ip link set dev lo up
,设置设备lo的状态为up,但是会变成unknown,因为要变成up需要满足两端是连起来的这个条件
3.2Network namespace连通
要在两个之间加上veth,veth就是一对pair,要把一个放到eth0里面,另一个放到eth1里面。这样eth0和eth1就会连通了。
3.3创建veth
netns add test1
,创建名为test1的network namespace(netns)netns add test2
,创建test2ip link add veth-test1 type veth peer name veth-test2
,创建veth,一端是veth-test1,一端是veth-test2ip link
,查看创建的vethip link set veth-test1 netns test1
,把veth-test1添加到test1这个netns里面,运行完成之后test1里面会多一个veth,但是本机里面的veth就会没有了。相当于移动到test1里面ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1
,给veth-test1这个设备添加ip地址ip netns exec test1 ip link set dev veth-test1 up
,设置veth-test1这个设备的状态为upip link set veth-test2 netns test2
ip netns exec test2 ip addr add 192.168.1.2/24 dev veth-test2
ip netns exec test2 ip link set dev veth-test2 up
,对test2进行相同操作ip netns exec test1 ping 192.168.1.2
,在test1下ping test2的ip,要是设置正确的话,因为已经有了veth,所以两边是会通的
4.Docker bridge0详解
4.1Docker Network的相关命令
docker network ls
,查看docker的网络情况docker network inspect network_id
,可以查看有哪个容器是在这个network里面的
4.2查看bridge的情况
可以使用brctl这个工具来查看bridge的情况
安装:yum install -y bridge-utils
使用:brctl show
4.3Bridge Network的情况
- 我们创建了一个docker容器之后,使用
ip a
,会看到多了一个网络设备,这个设备就是veth的一端,另一端是在创建的容器里面的。这样容器就可以和我们本机连通了 - 在本机这一边的所有veth又是都连接到docker0的,是通过bridge的方式。我们可以通过
brctl show
这个命令来查看。那么所有的docker容器之间就可以互相访问了 - docker0又使用NAT的方式和eth0连接,这样docker容器就可以访问互联网了
NOTICE
有的时候我们需要测试网络情况等等,会需要启动一个docker容器,但是不需要什么功能,只要是个容器就行了,那我们肯定希望这个容器越简单越好,我们可以使用busybox来创建
sudo docker run -d --name test busybox /bin/sh -c "while true; do sleep 3600; done"
5.容器之间的link
5.1docker link
docker容器启动的时候带上link参数:
|
|
启动test2容器,link了test1。因为test1和test2都是连接到docker0上的,所以test1和test2之间是互通的,我们只要ping双方的ip就可以了。但是现在test2已经link到test1了,那么我们在test2里面ping test1(注意是ping test1,不用ping test1的ip),也是可以的。但是要注意,test1里面用ping test2是不可以的,因为link有一个方向的概念。
5.2docker network相关命令
docker network ls
,可以查看现在的networkdocker network create -d bridge my-bridge
,创建一个名为my-bridge的network,-d指定类型为bridgedocker run -d --name test3 --network my-bridge busybox /bin/sh -c "while true; do sleep 3600; done"
,在创建容器的时候指定–network,那么容器就会连接到这个network上,可以使用brctl show来查看docker network inspect my-bridge
,也是可以查看连接到network的容器docker network connect my-bridge test2
,指定已经存在的容器连接到my-bridge这个network,但是容器还是会连接原本连接的那个network
NOTICE
我们用docker network connect my-bridge test2
这个命令之后,那么原本就在my-bridge这个network里面的容器,可以直接ping test2(注意这里是直接ping test2就可以了,不用ping test2的ip也是可以的),也是会成功的。这是因为所有连接在自己创建的bridge上面的容器,相互之间都是可以默认用name来ping的。test2一旦加入my-bridge,也是可以直接ping这个网络内的其他容器的,比如ping test3
6.容器的端口映射
docker run --name web -d -p 80:80 nginx
,这样在docker容器启动起来之后,我们在本机curl 127.0.0.1,访问的就是docker容器里面的nginxdocker run --name web -d -p 81:80 nginx
,注意,这里是本机的81端口和docker容器的80端口,也就是说这时候在本机要访问 curl http://127.0.0.1:81 ,这样才会访问到docker容器里面
7.容器网络之host和none
7.1none网络
docker run -d --name test1 --network none busybox /bin/sh -c "while true; do sleep 3600; done"
,使用–network指定连接到none这个networkdocker network inspect none
,可以查看none的网络情况
none网络里面的容器,只有一个回环地址,没有其他的网络设备,也就是除了docker exec -it这种方式进入内部,外部是根本没有办法访问到这个容器的。我们可能会问用了none网络的容器有什么用?可能这个容器是一种工具,比如生成密码的,需要安全性,所以就用none网络,限制外部访问。
7.2host网络
docker run -d --name test1 --network host busybox /bin/sh -c "while true; do sleep 3600; done"
,指定连接到host网络docker network inspect host
,可以查看host的网络情况
host网络里面的容器,我们使用docker exec -it进入内部之后,可以看到ip a的结果和我们本机的ip a的结果是一样的。也就是容器和本机是用相同的网络的。这样的方式可能出现的问题是端口的占用,比如本机已经有其他软件使用了80端口,那么容器就没有办法使用80端口了
8.多容器复杂应用的部署演示
8.1部署演示
- 先启动redis容器
docker run -d –name redis redis,不用使用-p参数把端口绑定到本机,因为这个redis只是给之后的flask-redis容器使用的,不是给本机使用的。 - 启动我们的flask程序
docker run -d –link redis –name flask-redis -p 5000:5000 -e REDIS_HOST=redis liguoqinjim/flask-redis,首先是使用–link连接到redis容器,那么flask-redis这个容器里面ping redis得到的就是redis容器的ip,-p把5000端口映射到本机,-e给这个容器设置环境变量REDIS_HOST。那么我们程序里面会去取这个环境变量,得到的就是redis,那因为已经link过了,所以redis就相当于redis容器的ip了。
8.2docker env
docker run -d --name test1 -e ENV_TEST=123 busybox /bin/sh -c "while true; do sleep 3600; done"
,-e设置容器的环境变量。docker exec test1 env
,查看test1容器的环境变量,可以看到ENV_TEST这个变量
9.Overlay和Underlay的通俗解释
不同机器上的docker容器之间的通信,是靠VXLAN来实现的。VXLAN又需要overlay和underlay来完成整个过程。
VXLAN的大致实现的思路是:本来我们两个机器之前ping,最简单包里面的数据就是有一个src有一个dst,分别是自己的地址和目的地址。那么现在不同机器里面的容器,要去向别的机器的容器。我们把这个数据包整个加载到之前的机器的ping数据包里面。在机器间数据包到达目标机器的时候,解包之后再去向目标容器
10.Docker Overlay网络和etcd实现多机容器通信
在多个机器上的容器要相互通信,要有一个大前提,也就是每个容器的ip不能一样,不同机器的不同容器的ip都是不能一样的。因为要是一样,那数据包肯定是无法到达目标机器的。
所以我们为了保证每个容器的ip是不一样的,我们要使用一个第三方的分布式工具来保证ip不一样。这个实验里面我们使用etcd这个分布式工具
10.1多机容器通信
- 首先要在不同机器之间创建一个etcd的集群
- 要重启docker,参数里面要带上集群的参数
- 创建overlay的docker网络,我们在一台机器上创建一个overlay网络就可以了,因为有了etcd,每个机器上的docker都已经自动同步了,其他机器上也会有一个overlay网络。比如我们在机器1上面创建一个name为test1的容器,这个时候我们在机器2上面创建一个name为test1的容器时,docker是会报错的。因为docker不允许有两个name一样的容器。机器2的docker会知道已经有test1就是因为etcd的关系
- 运行容器,注意要使用–network命令,把容器连接到overlay的network里面。当两个容器都在overlay网络里面的时候,我们就可以相互ping了
- 这个时候我们使用docker network ls,我们会发现多了一个network,类型为bridge,name应该是docker_gwbridge。这个network是干什么的呢?这个network给容器访问外网的。具体可以查看下面的图片。
10.2启动参数
|
|