1. Docker网络简介

  1. Docker网络架构方案是容器网络模型(Container Network Model,CNM),支持插接式连接。
  2. Libnetwork是Docker对CNM的一种实现,不同的驱动可以通过插拔的方式接入Libnetwork来提供定制化的网络拓扑。Libnetwork提供了本地服务发现和基础的容器负载均衡解决方案。
  3. Docker封装了一系列驱动(第三方只要通过提供驱动,就可以拓展Docker网络功能),覆盖了大部分常见的网络需求,包括单机桥接网络(Single-Host Bridge Network)、多机覆盖网络(Multi-Host Overlay)和支持接入现有VLAN。

    2. Docker网络详解

  • Docker网络设计理论
  • 单机桥接网络
  • 多机覆盖网络
  • 接入现有网络
  • 服务发现
  • Ingress网络

    2.1 Docker网络设计理论

    2.1.1 容器网络模型(CNM)

  1. Docker网络设计理论基于CNM,CNM三要素:沙盒(Sandbox)、终端(Endpoint)和网络(Network)
  2. 沙盒:沙盒是一个独立的网络栈。其中包括以太网接口、端口、路由表以及DNS配置
  3. 终端:虚拟网络接口。就像普通网络接口一样,终端主要职责是负责创建连接。在CNM中,终端负责将沙盒连接到网络。
  4. 网络:网络是802.1d网桥(交换机)的软件实现。因此,网络就是需要交互的终端的集合,并且终端之间相互独立。
  5. 沙盒放置在容器内部,为容器提供网络连接,一个容器有一个沙盒,一个沙盒有多个终端(容器可以接到多个网络)

image.png

  1. 下图,容器A、B运行在同一主机,但其网络堆栈在操作系统层面是相互独立的(由沙盒保证)。

image.png

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的关系如下图:

image.png

  • 第三方也可以编写Docker网络驱动,叫作远程驱动,按照拔插规则成为一个网络标准。
  • Libnetwork支持同时激活多个网络驱动,则Docker环境可以支持一个庞大的异构网络。

    2.2 单机桥接网络

  1. 单机:该网络只能在单个Docker主机的容器间运行。
  2. 桥接:802.1.d桥接的一种实现(二层交换机)。
  3. 每个 Docker 主机都有一个默认的单机桥接网络,创建容器默认接入到该网络。在Linux中网络名称为 bridge,在Windows中叫作 nat。
  4. 由于linux的docker的bridge使用的是liunx自带的bridge,因此可以在liunx主机中使用原本可以查看bridge的工具,Docker 默认“bridge”网络和 Linux 内核中的“docker0”网桥之间的关系:

image.png

  1. 创建桥接网络localnet,并创建容器连入localnet网络: ```bash $ docker network create -d bridge localnet

$ docker container run -d —name c1 \ —network localnet \ alpine sleep 1d

  1. ![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)
  2. 6. 同一个网络中的不同容器,可以通过容器名来ping通,因为新容器都注册到了指定的Docker DNS服务(Linux上默认的Bridge网络是不支持通过Docker DNS服务进行域名解析)。网桥不能与其他网络连接,但可以使用容器的端口映射(Port Mapping)来绕开这个限制。
  3. 6. DNS 服务器中记录了容器启动时通过 --name 或者 --net-alias 参数指定的名称与容器之间的映射关系。
  4. <a name="bu67F"></a>
  5. ### 2.3 多机覆盖网络
  6. > 覆盖网络下一章详解。
  7. 1. 覆盖网络允许单个网络包含多个主机,所以不同主机上的容器间可以在链路层实现通信。
  8. 1. 创建覆盖网络: `docker network create` 时,添加 `--d overlay` 参数即可。
  9. <a name="7SR2S"></a>
  10. ### 2.4 接入现有网络
  11. > 部分容器化的应用如何与那些运行在物理网和VLAN上的为容器化部分进行通信?
  12. >
  13. > Docker内置的MacvlanLiunx)和TransparentWindows),通过为容器提供MACIP地址,让容器在物理网络上成为“一等公民”,来解决该问题。
  14. 1. Macvlan需要主机网卡(NIC)设置为混杂模式(Promiscuous Mode)(公有云一般不允许)。下层网络(VLAN 100)对 Macvlan 的魔法毫不知情,只能看到容器的 MAC IP 地址。在该基础之上的容器可以 ping 通任何加入 VLAN 100 的系统,并进行通信。
  15. 1. Macvlan驱动在连接到目标网络前,需要设置:(1)子网信息。(2)网关。(3)可分配给容器的IP范围。(4)主机使用的接口或子网接口。
  16. 1. Macvlan 采用标准 Linux 子接口,需要为其打上目标 VLAN 网络对应的 ID。在本例中目标网络是 VLAN 100,所以将子接口标记为 .100etho.100)。通过 `--ip-range` 参数告知 Macvlan 网络在子网中有哪些 IP 地址可以分配给容器。这些地址必须被保留,不能用于其他节点或者 DHCP 服务器,因为没有任何管理层功能来检查 IP 区域重合的问题。如下命令会创建 macvlan100 网络以及 eth0.100 子接口:
  17. ```bash
  18. $ docker network create -d macvlan \
  19. --subnet=10.0.0.0/24 \
  20. --ip-range=10.0.00/25 \
  21. --gateway=10.0.0.1 \
  22. -o parent=eth0.100 \
  23. macvlan100
  1. 例子:现有两个VLAN——VLAN100:10.0.0.0/24和VLAN200:192.168.3.0/24,添加Docker主机(网卡是eth0)并连接到网络VLAN100。当前配置如下图:

image.png
将容器部署到该网络中:

  1. $ docker container run -d --name mactainer1 \
  2. --network macvlan100 \
  3. alpine sleep 1d

Docker网络 - 图6

  1. Macvlan 也支持 VLAN 的 Trunk 功能,可以在相同的 Docker 主机上创建多个 Macvlan 网络,并且将容器按照下图的方式连接起来:

Docker网络 - 图7

2.4.1 用于故障排除的容器和服务日志

  1. 可以通过查看 daemon日志以及容器日志。
  2. 设置 daemon 日志的详细程度。(修改配置文件之后,需要重启 Docker 才会生效。)
    • debug:最详细的日志级别。
    • info:默认值,次详细日志级别。
    • warn:第三详细日志级别。
    • error:第四详细日志级别。
    • fatal:最粗略的日志级别。
  3. docker container logs 命令查看单独的容器日志;docker service logs 可以查看 Swarm 服务日志。但是,Docker 支持多种日志驱动,并不是每种都能通过 docker logs 命令查看的。就像引擎日志的驱动和配置一样,每个 Docker 主机也为容器提供了默认的日志驱动以及配置。其中包括 json-file(默认)、journald(只在运行 systemd 的 Linux 主机中生效)、syslog、splunk 和 gelf。

    2.5 服务发现

  4. 服务发现(Service Discovery):允许容器和 Swarm 服务通过名称互相定位(要求处于同一个网络当中)。其底层实现是利用了Docker内置的 DNS 服务器,为每个容器提供 DNS 解析(每个 Docker 容器都有本地 DNS 解析器)功能(Swarm 服务原理相同)。

  5. 每个启动时使用了 —name 参数的 Swarm 服务或者独立的容器,都会将自己的名称和 IP 地址注册到 Docker DNS 服务。这意味着容器和服务副本可以通过 Docker DNS 服务互相发现。
  6. 用户可以为 Swarm 服务和独立容器进行自定义的 DNS 配置。举个例子,—dns 参数允许读者指定自定义的 DNS 服务列表,以防出现内置的 Docker DNS 服务器解析失败的情况。此外也可以使用 —dns-search 参数指定自定义查询时所使用的域名(例如当查询名称并非完整域名的时候)。在 Linux 上,上述工作都是通过在容器内部 /etc/resolve.conf 文件内部增加条目来实现的。

    2.6 Ingress网络

  7. Dokcer Swarm 支持两种服务发布模式,两种模式均保证服务从集群外可访问。Ingress 模式发布的服务,可以保证 Swarm 集群内任一节点(即使没有运行服务的副本)都能访问该服务;以 Host 模式发布的服务只能通过运行服务副本的节点来访问(通常使用Ingress模式)。

    • Ingress模式(默认,可用简单格式)
    • Host模式(完整格式)
      1. # 指定Host模式
      2. $ docker service create -d --name svc1 \
      3. --publish published=5000,target=80,mode=host \
      4. nginx
  8. 在底层,Ingress模式采用名为Service Mesh或Swarm Mode Service Mesh的四层路由网络来实现。如下解释外部请求流转到服务的过程:

    1. $ docker service create -d --name svc1 --network overnet \
    2. --publish published=5000,target=80 nginx

    image.png

    • 集群确保到达 Ingress 网络中任意节点的 5000 端口的流量,都会被路由到 80 端口的“svc1”服务。
    • 当前“svc1”服务只部署了一个副本,集群中有一条映射规则:“所有访问 Ingress 网络 5000 端口的流量都需要路由到运行了“svc1”服务副本的节点之上”(如红线展示了访问 Node1 的 5000 端口的流量,通过 Ingress 网络,被路由到了 Node2 节点正在运行的服务副本之上)。
  9. 如果存在多个运行中的副本,流量会平均到每个副本之上,如下:
    1. $ docker service create -d --name svc1 --network overnet \
    2. --replicas 4 \
    3. --publish published=5000,target=80 nginx
    image.png