Docker的网络概念
CNM、Libnetwork和驱动
CNM容器网络模型
Docker的网络构架源自一种叫做容器网络模型(CNM)的方案,该方案是开源的并且支持插接式连接。
CNM中规定了Docker网络的基础构成要素:沙盒(Sandbox)、终端(Endpoint)和网络(Network)。
沙盒,是一个独立的网络栈。其中包括以太网接口、端口、路由表及DNS配置。
终端,就是虚拟网络接口。就像普通网络接口一样,终端的主要职责是创建连接。在CNM中,终端是负责将沙盒连接到网络。
网络,是802.1.d 网桥的软件实现。因此,网络就是需要交互的终端的集合,并且终端之间相互独立。
Libnetwork
Libnetwork是Docker对CNM的一种实现,提供了Docker核心网络架构的全部功能。不通的驱动可以通过插拔式的方式接入Libnetwork来提供定制化的网络拓扑。
Libnetwork通过Go语言编写,并实现了CNM中列举的核心组件。Libnetwork是从deamon中拆分出来的外部类库。
Libnetwork实现了CNM中规定的全部3个组件,此外它还实现了本地服务发现(Service Discovery)、基于Ingress的容器负载均衡,以及网络控制层和管理层功能。
驱动
如果说Libnetwork实现了控制层和管理层功能,那么驱动就负责实现数据层。比如,网络连续性和隔离型是由驱动来处理的,驱动层实际创建网络对象也是如此。
Docker封装了若干内置驱动,通常被称作原生驱动或本地驱动。在Linux上包括Bridge、Overlay以及Macvlan。
第三方也可以编写Docker网络驱动,这些驱动称为远程驱动。每个驱动都负责其上所有网络资源的创建和管理。
为了满足复杂且不固定的环境需求,Libnetwork支持同时激活多个网络驱动。这意味着Docker环境可以支持一个庞大的异构网络。
单机桥接网络
单机桥接网络只能在单个Docker节点上运行,并且只能与所在Docker主机上的容器进行连接。
桥接表示这是802.1.d桥接的一种实现(二层交换机)。
每个Docker主机都有一个默认的单机桥接网络。在Linux上网络名称名为bridge,在Windows上名为nat。除非通过命令行创建容器时指定参数--network,否则默认情况下,新创建的容器都会连接到该网络。
Docker网络命令
docker network ls
列出当前主机上的网络
docker network inspect <网络名称>
显示网络的详细信息
示例输出:
[root@localhost ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "141c791e674798ac0027623c2d2c564bcfe8b6aa88ed7e66fed7636d95918649",
"Created": "2020-07-25T09:06:00.876062816-04:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"94b4e0f51663da4bc34b577c2c6395e6d7ef03314fa4dbfeb46ef768e940d9aa": {
"Name": "nginx",
"EndpointID": "a9ca9e4dd8badaf077804b8f9e60ecd1361fc65a5008c8584076bc4b2c821928",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
在Linux主机上,Docker网络由Bridge驱动创建,而Bridge底层是基于Linux内核中的Linux Bridge技术,Bridge是高效而且稳定的。
默认的bridge网络被映射到内核中名为docker0的Linux网桥。
#Linux系统中的docker0网桥
[root@localhost ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:c6ff:fe6c:869d prefixlen 64 scopeid 0x20<link>
ether 02:42:c6:6c:86:9d txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5 bytes 446 (446.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
创建新的单机桥接网络
docker network create -d bridge <网络名称>
#创建新桥接网络命令
#-d 选择驱动创建了新的网络后,Linux主机内核中还会创建一个新的Linux网桥。
将容器接入网络
docker run -d --name nginx --network <网络名称> <镜像名称>
#将容器连接到网络,通过docker network inspect 查看网络信息,可以看到连接的容器列表。桥接网络中的容器只能与位于相同网络中的容器进行通信。但是可以使用端口映射(Port Mapping)来绕开这个限制。
端口映射将容器的某个端口映射到Docker主机的端口上,仍和发送到该端口上的流量都会转发到容器。但是这种方法比较笨重并且不能扩展。
多机覆盖网络
覆盖网络适用于多机环境。它允许单个网络包含多个主机,这样不同主机上的容器间就可以在链路层实现通信。覆盖网络是理想的容器间通信方式,支持完全容器化的应用,并且具备良好的伸缩性。
Docker为覆盖网络提供本地驱动。这使得创建覆盖网络非常简单,只需要在docker network create 命令中添加--d overlay参数。
Macvlan驱动
Macvlan驱动可以为容器提供MAC和IP地址,且因为无需端口映射或者额外桥接,可以通过主机接口(或者子接口)访问容器接口,性能优异。
但是Macvlan需要将主机网卡设置为混杂模式,这在大部分公有云上是不允许的。对于公司内部的数据中心网络来说Macvlan是很棒的。但是在公有云上并不可行。
用于故障排除的容器和服务日志
服务日志
journalctl -u docker.service
#查看daemon日志
通过编辑daemon配置文件(daemon.json)将debug设置为true,并同时设置log-level为下面的某个值.
- debug:最详细的日志级别
- info:默认值,次详细日志级别
- warn: 第三详细日志级别
- error:第四详细日志级别
- fatal:最粗略日志级别
修改完配置文后,需要重启Docker。容器日志
docker logs
#查看单独容器日志
docker service logs
查看Swarm服务日志服务发现
作为核心网络架构,Libnetwork还提供服务发现(Service Discovery)功能,允许容器和Swarm服务通过名称互相定位。唯一的要求就是需要处于同一网络当中。
---待完善---