1. Docker网络简介
- Docker网络架构方案是容器网络模型(Container Network Model,CNM),支持插接式连接。
- Libnetwork是Docker对CNM的一种实现,不同的驱动可以通过插拔的方式接入Libnetwork来提供定制化的网络拓扑。Libnetwork提供了本地服务发现和基础的容器负载均衡解决方案。
- Docker封装了一系列驱动(第三方只要通过提供驱动,就可以拓展Docker网络功能),覆盖了大部分常见的网络需求,包括单机桥接网络(Single-Host Bridge Network)、多机覆盖网络(Multi-Host Overlay)和支持接入现有VLAN。
2. Docker网络详解
- Docker网络设计理论基于CNM,CNM三要素:沙盒(Sandbox)、终端(Endpoint)和网络(Network)
- 沙盒:沙盒是一个独立的网络栈。其中包括以太网接口、端口、路由表以及DNS配置
- 终端:虚拟网络接口。就像普通网络接口一样,终端主要职责是负责创建连接。在CNM中,终端负责将沙盒连接到网络。
- 网络:网络是802.1d网桥(交换机)的软件实现。因此,网络就是需要交互的终端的集合,并且终端之间相互独立。
- 沙盒放置在容器内部,为容器提供网络连接,一个容器有一个沙盒,一个沙盒有多个终端(容器可以接到多个网络)
- 下图,容器A、B运行在同一主机,但其网络堆栈在操作系统层面是相互独立的(由沙盒保证)。
2.1.2 Libnetwork
Libnetwork是Docker对CNM的实现,替代早起混杂在daemon中的网络部分。Libnetwork实现了CNM的3个组件(沙盒、终端和网络),还实现了本地服务发现(Service Discovery)、基于Ingress的容器负载均衡,以及网络控制层和管理层功能。
2.1.3 驱动
驱动处理实现网络连通性和隔离性,Docker封装了若干内置驱动(称为内置驱动,Linux:Bridge、Overlay、Macvlan,Windows:NAT、Overlay、Transport、L2 Bridge)。驱动和Libnetwork的关系如下图:
- 单机:该网络只能在单个Docker主机的容器间运行。
- 桥接:802.1.d桥接的一种实现(二层交换机)。
- 每个 Docker 主机都有一个默认的单机桥接网络,创建容器默认接入到该网络。在Linux中网络名称为 bridge,在Windows中叫作 nat。
- 由于linux的docker的bridge使用的是liunx自带的bridge,因此可以在liunx主机中使用原本可以查看bridge的工具,Docker 默认“bridge”网络和 Linux 内核中的“docker0”网桥之间的关系:
- 创建桥接网络localnet,并创建容器连入localnet网络: ```bash $ docker network create -d bridge localnet
$ docker container run -d —name c1 \ —network localnet \ alpine sleep 1d
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1204927/1589276399990-eec75ae3-a2d5-4e48-8bd0-c7d87e41e57a.png#align=left&display=inline&height=286&margin=%5Bobject%20Object%5D&name=image.png&originHeight=286&originWidth=409&size=17250&status=done&style=shadow&width=409)
6. 同一个网络中的不同容器,可以通过容器名来ping通,因为新容器都注册到了指定的Docker DNS服务(Linux上默认的Bridge网络是不支持通过Docker DNS服务进行域名解析)。网桥不能与其他网络连接,但可以使用容器的端口映射(Port Mapping)来绕开这个限制。
6. DNS 服务器中记录了容器启动时通过 --name 或者 --net-alias 参数指定的名称与容器之间的映射关系。
<a name="bu67F"></a>
### 2.3 多机覆盖网络
> 覆盖网络下一章详解。
1. 覆盖网络允许单个网络包含多个主机,所以不同主机上的容器间可以在链路层实现通信。
1. 创建覆盖网络: `docker network create` 时,添加 `--d overlay` 参数即可。
<a name="7SR2S"></a>
### 2.4 接入现有网络
> 部分容器化的应用如何与那些运行在物理网和VLAN上的为容器化部分进行通信?
>
> Docker内置的Macvlan(Liunx)和Transparent(Windows),通过为容器提供MAC和IP地址,让容器在物理网络上成为“一等公民”,来解决该问题。
1. Macvlan需要主机网卡(NIC)设置为混杂模式(Promiscuous Mode)(公有云一般不允许)。下层网络(VLAN 100)对 Macvlan 的魔法毫不知情,只能看到容器的 MAC 和 IP 地址。在该基础之上的容器可以 ping 通任何加入 VLAN 100 的系统,并进行通信。
1. Macvlan驱动在连接到目标网络前,需要设置:(1)子网信息。(2)网关。(3)可分配给容器的IP范围。(4)主机使用的接口或子网接口。
1. Macvlan 采用标准 Linux 子接口,需要为其打上目标 VLAN 网络对应的 ID。在本例中目标网络是 VLAN 100,所以将子接口标记为 .100(etho.100)。通过 `--ip-range` 参数告知 Macvlan 网络在子网中有哪些 IP 地址可以分配给容器。这些地址必须被保留,不能用于其他节点或者 DHCP 服务器,因为没有任何管理层功能来检查 IP 区域重合的问题。如下命令会创建 macvlan100 网络以及 eth0.100 子接口:
```bash
$ docker network create -d macvlan \
--subnet=10.0.0.0/24 \
--ip-range=10.0.00/25 \
--gateway=10.0.0.1 \
-o parent=eth0.100 \
macvlan100
- 例子:现有两个VLAN——VLAN100:10.0.0.0/24和VLAN200:192.168.3.0/24,添加Docker主机(网卡是eth0)并连接到网络VLAN100。当前配置如下图:
将容器部署到该网络中:
$ docker container run -d --name mactainer1 \
--network macvlan100 \
alpine sleep 1d
- Macvlan 也支持 VLAN 的 Trunk 功能,可以在相同的 Docker 主机上创建多个 Macvlan 网络,并且将容器按照下图的方式连接起来:
2.4.1 用于故障排除的容器和服务日志
- 可以通过查看 daemon日志以及容器日志。
- 设置 daemon 日志的详细程度。(修改配置文件之后,需要重启 Docker 才会生效。)
- debug:最详细的日志级别。
- info:默认值,次详细日志级别。
- warn:第三详细日志级别。
- error:第四详细日志级别。
- fatal:最粗略的日志级别。
docker container logs
命令查看单独的容器日志;docker service logs
可以查看 Swarm 服务日志。但是,Docker 支持多种日志驱动,并不是每种都能通过docker logs
命令查看的。就像引擎日志的驱动和配置一样,每个 Docker 主机也为容器提供了默认的日志驱动以及配置。其中包括 json-file(默认)、journald(只在运行 systemd 的 Linux 主机中生效)、syslog、splunk 和 gelf。2.5 服务发现
服务发现(Service Discovery):允许容器和 Swarm 服务通过名称互相定位(要求处于同一个网络当中)。其底层实现是利用了Docker内置的 DNS 服务器,为每个容器提供 DNS 解析(每个 Docker 容器都有本地 DNS 解析器)功能(Swarm 服务原理相同)。
- 每个启动时使用了 —name 参数的 Swarm 服务或者独立的容器,都会将自己的名称和 IP 地址注册到 Docker DNS 服务。这意味着容器和服务副本可以通过 Docker DNS 服务互相发现。
用户可以为 Swarm 服务和独立容器进行自定义的 DNS 配置。举个例子,—dns 参数允许读者指定自定义的 DNS 服务列表,以防出现内置的 Docker DNS 服务器解析失败的情况。此外也可以使用 —dns-search 参数指定自定义查询时所使用的域名(例如当查询名称并非完整域名的时候)。在 Linux 上,上述工作都是通过在容器内部 /etc/resolve.conf 文件内部增加条目来实现的。
2.6 Ingress网络
Dokcer Swarm 支持两种服务发布模式,两种模式均保证服务从集群外可访问。Ingress 模式发布的服务,可以保证 Swarm 集群内任一节点(即使没有运行服务的副本)都能访问该服务;以 Host 模式发布的服务只能通过运行服务副本的节点来访问(通常使用Ingress模式)。
- Ingress模式(默认,可用简单格式)
- Host模式(完整格式)
# 指定Host模式
$ docker service create -d --name svc1 \
--publish published=5000,target=80,mode=host \
nginx
在底层,Ingress模式采用名为Service Mesh或Swarm Mode Service Mesh的四层路由网络来实现。如下解释外部请求流转到服务的过程:
$ docker service create -d --name svc1 --network overnet \
--publish published=5000,target=80 nginx
- 集群确保到达 Ingress 网络中任意节点的 5000 端口的流量,都会被路由到 80 端口的“svc1”服务。
- 当前“svc1”服务只部署了一个副本,集群中有一条映射规则:“所有访问 Ingress 网络 5000 端口的流量都需要路由到运行了“svc1”服务副本的节点之上”(如红线展示了访问 Node1 的 5000 端口的流量,通过 Ingress 网络,被路由到了 Node2 节点正在运行的服务副本之上)。
- 如果存在多个运行中的副本,流量会平均到每个副本之上,如下:
$ docker service create -d --name svc1 --network overnet \
--replicas 4 \
--publish published=5000,target=80 nginx