Docker网络详解
容器、微服务
我们知道,Docker的核心是资源隔离,Docker相当于是运行在Host 主机上的一个进程,但是这些进程是如何实现彼此的互不干扰,独立运行呢?这个就要说到Docker的CGroup 和 Namespace了。
CGroup全称是Control Group,是用来设置进程使用CPU,内存和IO资源的限额。所以CGroup相当于是用来做资源的控制。Docker的CGroup配置是放在 /sys/fs/cgroup/路径下配置文件里,通过这些配置文件,来设置Docker进程的资源配置。
Namespace是实现Docker的资源隔离,分别对应了6种资源: Mount, UTS, IPC, PID,Network和 User。
- Mount Namespace,是可以让容器能独立的拥有自己的文件系统
- UTS Namespace, 是让容器有自己的hostname
- IPC Namespace, 是让自己有自己独享的内存和信号量来实现进程间的通信,而不会与host和其他的容器IPC混在一起
- PID,进程ID
- Network namespace, 让容器拥有自己独立的网卡,IP,路由等资源。
- User Namespace, 让容器可以管理自己的用户。
好了,说了这么多的废话,这章来讲解下容器的网络。
容器的网络实际上是分为三种,none,bridge和host。可以通过命令方式看下容器的网络配置。
那个 my_next 是我自己配置的一个bridge网络。这个是在host docker上看到的容器网络几种类型。
1. none 网络
none网络就是什么都没有的网络,挂在这个网络下的就是IO,没有任何其他的网卡。可以看下。
就是通过 –network=none 来配置,可以看下ifconfig就是只有local 的network。
可能有人会问,这种网络有什么作用呢,也不能和外面通信,其实还是有作用的,比如涉及到的一些隐私等可以通过这种方式配置,可以通过这个docker来生成和密钥相关的一些东西,还是非常有作用。
2.host 网络
这种网络配置是和Docker host共享它的网络栈,容器的网络配置与host完全一样,可以看下。
可以看下,是通过–network=host 来配置网络模式是host模式。可以看到,它的网络配置主机的网络配置完全一致。
使用场景是什么呢,就是如果容器对网络传输效率有较高的要求,可以选择这种模式,但是缺点也很明显,就是不太灵活,要考虑端口冲突问题。
3. bridge 网络
这种是用的最多的,默认情况下就是创建的bridge网络模式。
可以看到,有两个桥接网络,第一个是我手动创建的一个桥接,第二个是Docker host默认的一个桥接网络,当每用默认网络模式创建一个docker实例时,就会在默认的Docker桥接下增加一个interface。
可以创建一个桥接模式的docker试试看。
我创建了一个Docker实例,然后在docker0的桥接下多了一个interface。
可以看下这个网络配置, 网络名称是if48.
这个是bridge的网络参数。同时Docker Host的ip是172.17/0.1,整个的网络模型如下所示:
这个就是一个bridge模式。
4. User-defined 网络
这个是指根据自己的需要配置docker的网络,这种就比较灵活了,docker提供了三种user-defined的网络驱动:bridge, overlay 和 macvlan。
以bridge网络为例,如果两个docker是在不同的bridge下,互相通信是肯定不行的;如果它们是属于同一个网桥下,这个时候肯定是可以的,如下图。
怎么样可以让httpd和busybox的网桥通信呢,可以在httpd容器下添加一块net_my2的网卡,通过下面的方法进行连接。
之后网络模型就如下所示了:
5. 容器间的通信
我们知道,如果两个容器是在一个bridge下,可以互相通信,如果不在一个bridge下,可以通过docker network connect将现有容器加入到指定网格中。但是有个问题啊,我们知道容器的IP是动态变化的,不能光靠ip的方式来访问容器,可以通过网络名称方式来访问。但是这种方式只能在user-defined网络中使用,不能在默认的bridge中。
6. joined 容器
Joined容器是另外一种实现容器通信的方式。它是使两个或多个容器共享一个网络栈,共享网卡和配置信息。
我用一个实例来演示下。
我先创建一个httpd的容器。
然后再创建一个busybox的容器加入到web1这个容器里。
同时看下它的网络配置。我比较下web1的网络配置。
它们的网络是完全一样的。
现在在busybox的容器里直接通过127.0.0.1来访问web容器,发现是可以直接访问的,也证明了这两个容器是网络互通。
7. 容器访问外部世界
我们知道,我们运行的容器是可以直接访问外网的。
看这个,可以直接访问的。这个是怎么实现的呢。
它是通过nat转换,将内部的网络地址转换为host的网络地址发送出去。整个过程如下图所示:
这个图非常清晰的说明了整个过程。
8. 外部网络访问Docker容器
外部网络访问Docker容器是通过端口映射的方式实现的,就是启动容器后,将端口映射到host的某一个端口。
这个就是将docker的80端口映射到了host的32768端口上,可以通过host的ip加32768端口来访问容器。
也可以在创建容器时,静态的指定端口。
整个过程可以用下图来表示。
整个过程是从左到右,通过docker-proxy转发给容器172.17.0.2.