Docker 容器技术 — 容器网络

目录

容器网络的发展趋势

在这里插入图片描述

CNI

CNI(Container Network Interface,容器网络接口)是 Google 和 CoreOS 主导制定的容器网络标准,它是在 RKT 网络提议的基础上发展起来的,综合考虑了灵活性、扩展性、IP 分配、多网卡等因素。

CNI 旨在为容器平台提供网络的标准化,不同的容器平台(e.g. Kubernetes、Mesos 和 RKT)能够通过相同的接口调用不同的网络组件。这个协议连接了两个组件:

  1. 容器管理系统
  2. 网络插件

具体的事情都是插件来实现的,包括:创建容器网络空间(network namespace)、把网络接口(interface)放到对应的网络空间、给网络接口分配 IP 等。

目前采用 CNI 提供的方案一般分为两种

  1. 隧道方案
  2. 路由方案

具体为:Flannel,Callico,Weave 和 macvlan 网络方案。从难易度上来讲,Callico 最简单,其次 Flannel,Weave 最复杂,从网络技术来看,Weave 和 Flannel 都是网络封装隧道技术,区别在于封装的位置在网络设备上还是主机上。

在这里插入图片描述

Flannel

在这里插入图片描述

Flannel 是 CoreOS 提出用于解决容器集群跨主机通讯的网络解决方案。Flannel 实质上是一种 Overlay 网络,也就是将 TCP 数据包装在另一种网络包里面进行路由转发和通信,目前已支持 UDP、VXLAN、AWS VPC、GCE 路由等数据转发方式,其中以 VXLAN 技术最为流行,很多数据中心在考虑引入容器时,也考虑将网络切换到 Flannel 的 VXLAN 网络中来。

Flannel 为每个主机分配一个 Subnet,容器从此 Subnet 中分配 IP,这些 IP 可在主机间路由,容器间无需 NAT 和端口映射就可以跨主机通讯。Flannel 让集群中不同节点主机创建容器时都具有全集群唯一虚拟 IP 地址,并连通主机节点网络。Flannel 可为集群中所有节点重新规划 IP 地址使用规则,从而使得不同节点上的容器能够获得 “同属一个内网” 且 “不重复的” 的 IP 地址,让不同节点上的容器能够直接通过内网 IP 通信,网络封装部分对容器是不可见的。源主机服务将原本数据内容 UDP 封装后根据自己的路由表投递给目的节点,数据到达以后被解包,然后直接进入目的节点虚拟网卡,然后直接达到目的主机容器虚拟网卡,实现网络通信目的。

Flannel 虽然对网络要求较高,要引入封装技术,转发效率也受到影响,但是却可以平滑过渡到 SDN 网络,VXLAN 技术可以和 SDN 很好地结合起来,值得整个网络实现自动化部署,智能化运维和管理,较适合于新建数据中心网络部署。

Callico

在这里插入图片描述

Callico 容器网络和其他虚拟网络最大的不同是:它没有采用 Overlay 网络做报文转发,提供了纯三层网络模型。三层通信模型表示每个容器都通过 IP 直接通信,要想路由工作能够正常,每个容器所在的主机节点必须有某种方法知道整个集群的路由信息,Callico 采用 BGP 路由协议,使得全网所有的 Node 和网络设备都记录到全网路由。

然而这种方式会产生很多的无效路由,对网络设备路由规格要求较大,整网不能有路由规格低的设备。另外,Callico 实现了从源容器经过源宿主机,经过数据中心路由,然后到达目的宿主机,最后分配到目的容器,整个过程中始终都是根据 BGP 协议进行路由转发,并没有进行封包,解包过程,这样转发效率就会快得多,这是 Callico 容器网络的技术优势。

Weave

在这里插入图片描述

Weave 实质上也是 Overlay 网络,Weave 可以把不同主机上容器互相连接的网络虚拟成一个类似于本地网络的网络,不同主机之间都使用自己的私有 IP 地址,当容器分布在多个不同的主机上时,通过 Weave 可以简化这些容器之间的通信。

Weave 网络中的容器使用标准的端口提供服务(e.g. MySQL 默认使用 3306),管理微服务是十分直接简单的。每个容器都可以通过域名来与另外的容器通信,也可以直接通信而无需使用 NAT,也不需要使用端口映射或者复杂的联接。

部署 Weave 容器网络最大的好处是无需修改你的应用代码。Weave 通过在容器集群的每个主机上启动虚拟路由器,将主机作为路由器,形成互联互通的网络拓扑,在此基础上,实现容器的跨主机通信。

要部署 Weave 需要确保主机 Linux 内核版本在 3.8 以上,Docker1.10 以上,主机间访问如果有防火墙,则防火墙必须彼此放行 TCP 6783 和 UDP 6783/6784 这些端口号,这些是 Weave 控制和数据端口,主机名不能相同,Weave 要通过主机名识别子网。

Weave 网络类似于主机 Overlay 技术,直接在主机上进行报文流量的封装,从而实现主机到主机的跨 Underlay 三层网络的互访,这是和 Flannel 网络的最大区别,Flannel 是一种网络 Overlay 方案。

Macvlan

Macvlan 是 Linux Kernel 比较新的特性,允许在主机的一个网络接口上配置多个虚拟的网络接口,这些网络 interface 有自己独立的 MAC 地址,也可以配置上 IP 地址进行通信。macvlan 下的虚拟机或者容器网络和主机在同一个网段中,共享同一个广播域。macvlan 和 bridge 比较相似,但因为它省去了 bridge 的存在,所以配置和调试起来比较简单,而且效率也相对高。除此之外,macvlan 自身也完美支持 VLAN。

ServiceMesh + CNI

在这里插入图片描述

ServiceMesh 和 CNI 是组合的关系,ServiceMesh 并不会替代 CNI,他们工作在不同的 SDN 层次,CNI 更多工作在 L2-4 层,ServiceMesh 在 L5-7 层 Application SDN。ServiceMesh 不能独立于 CNI 部署,与 CNI 一起提供层次化微服务应用所需要的网络服务。根据 Gartner 报告指出,在 2020 年,几乎 100% 容器云都将内置 ServiceMesh 技术。而目前开源的Istio 仅提供单一 Kubernetes 集群内部微服务治理,缺失异构容器云,跨云能力。

CNI 需要交付给容器云 L2-4 层细化至微服务内部的每个 POD 容器。应用终端交付所需要的 L2 网络连接,L3 路由,L2-4 层安全隔离,容器云整体安全,负载均衡等。

ServiceMesh 更多的致力于微服务应用层面的服务治理,致力于 L5-7 层网络服务,服务网格在每一个应用容器前部署一个 Sidecar Envoy 应用代理,提供微服务间的智能路由,分布式负载均衡,流量管理,蓝绿,金丝雀发布,微服务弹性,限流熔断,超时重试,微服务间的可视化,安全等等。
·

Docker 容器网络

Docker 提供几种类型的网络,它决定容器之间、容器与外界之前的通信方式。

  • 基础网络类型
    在这里插入图片描述

  • 查看所有容器网络类型:

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
c79756cf9cde        bridge              bridge              local
204025a5abbc        host                host                local
9b9024f5ac40        macvlan             macvlan             local
6478888548d8        none                null                local
p2e02u1zhn8x        overlay             overlay             swarm

bridge 模式

bridge 模式的 Docker 网络基于 Linux 的虚拟网络技术来实现。Docker Container 的网络接口默认都是虚拟接口,可以充分发挥数据在不同 Container 之间或跨主机的 Container 之间的转发效率。这是因为 Linux 虚拟网络技术通过在内核中的数据复制来实现虚拟接口之间的数据转发,即:发送接口的发送缓存中的数据包将被直接复制到接收接口的接收缓存中,而无需通过外部物理网络设备进行交换。

当 Docker Daemon 启动后,会在宿主机上创建一个名为 docker0 的 Linux Bridge,在此宿主机上启动的 Docker Container 都会连接到这个虚拟网桥上。Docker Daemon 会从 docker0(一个虚拟的 L2 网络)子网中分配一个 IP 给 Container 使用,并设置 docker0 的 IP 地址为 Container 的默认网关。同时,在宿主机上创建一对 veth pair 虚拟网线设备,Docker Daemon 将 veth pair 设备的一端插入新建的 Container 中,并命名为eth0(容器的网卡),另一端插入 docker0 Linux Bridge 中,以 vethxxx 格式命名。

在这个网络的容器之间可以相互通信,外界想要访问到这个网络中的 Containers 也同样需要接入 bridge 网络并通过 iptables 做了 DNAT 规则,实现内外部地址转换。

在这里插入图片描述

$ ip a
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:46:c3:00:eb brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:46ff:fec3:eb/64 scope link
       valid_lft forever preferred_lft forever

$ docker run -itd --name box1 busybox

$ docker exec -it box1 sh

/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever

/ # ip r
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 scope link  src 172.17.0.2

$ brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.024246c300eb	no		vethd4ae072

host 模式

如果启动 Container 的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。也就是说 Container 不会虚拟出自己的网卡,配置自己的 IP 等,而是直接使用宿主机的 IP 和端口。

当然,Container 的其他方面,如:文件系统、进程列表等还是和宿主机隔离的。只用这种网络的容器会使用主机的网络,这种网络对外界是完全开放的,能够访问到主机,就能访问到容器。

$ docker run -itd --network host --name box2 busybox

$ docker exec -it box2 sh

/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether fa:16:3e:94:84:10 brd ff:ff:ff:ff:ff:ff
    inet 172.18.22.204/24 brd 172.18.22.255 scope global dynamic eth0
       valid_lft 48054sec preferred_lft 48054sec
    inet6 fe80::f816:3eff:fe94:8410/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
    link/ether 02:42:46:c3:00:eb brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:46ff:fec3:eb/64 scope link
       valid_lft forever preferred_lft forever
7: vethd4ae072@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0
    link/ether ce:95:19:64:d0:d4 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::cc95:19ff:fe64:d0d4/64 scope link
       valid_lft forever preferred_lft forever

macvlan 模式

对于某些应用程序,比如需要监视网络流量,期望直接连接到物理网络,这种情况下,可以使用 macvlan 的网络模式,macvlan 驱动程序不仅将 IP 地址分配给容器,而且还将物理 MAC 地址分配给容器。通过 macvlan 还可以实现跨主机容器之前的通信。

  1. 创建一个 macvlan 网络:
docker network create -d macvlan --subnet=172.16.86.0/24 --gateway=172.16.86.1 -o parent=eth0 macvlan1
  1. 设置网卡为混杂模式:
ip link set eth0 promisc on
  1. 创建使用 macvlan 网络的容器:
docker run -it --network macvlan1  --ip=172.16.86.2 busybox /bash

Container 模式

Container 模式,又称为 Docker links,是一种 Docker Container 之间的通信机制。如果一个新容器链接到一个已有容器,新容器将会通过环境变量获得已有容器的链接信息。通过提供给信任容器有关已有容器的链接信息,实现容器间的通信。

Container 模式和 host 模式很类似,只是 Container 模式创建容器共享的是其他容器的 IP 和 Port 而不是物理机的,此模式容器自身是不会配置网络和端口,创建此模式的容器进去后会发现里边的 IP 是你所指定的那个容器 IP 并且 Port 也是共享的。当然,其它还是互相隔离的,如进程等。

docker run -it --network container:<container ID>

在这里插入图片描述

none 模式

使用 none 模式 Container 会拥有自己的 Network Namespace,但是,并不为 Container 进行任何网络配置。也就是说,这个 Container 不会具有网卡、IP、路由等信息。需要手动的为 Container 添加网卡、配置 IP 等。使用此种网络的容器会完全隔离。

使用的 none 模式后,这个容器就是封闭的,不会去参与网络通信,这样就能够保证容器的安全性。

$ docker run -itd --network none --name box3 busybox

$ docker exec -it box3 sh

/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever

Overlay 模式

Overlay 模式使用在 Swarm 集群中,用于连接跨主机 Docker Container,允许不同宿主机上的容器相互通信。Overlay 模式在 Docker 集群节点间加入了一层虚拟网络,它有独立的虚拟网段,因此 Container 发送的内容,会先发送到虚拟子网,再由虚拟子网包装为宿主机的真实网址进行发送。

在这里插入图片描述

# 初始化 manager node。
$ docker swarm init

# 添加 worker node 到 manager。
$ docker swarm join --token <token> <manager_host>:2377

# 新建一个 Overlay 网络
$ docker network create --driver=overlay --attachable overlay

# 分别在不同的 worker node 上启动一个 busybox 容器,并连接到 Overlay 网络
$ docker run -it --network overlay --name box4 sh

如此的,在同一个 Overlay 网络上的跨主机 Container 就可以互相通信了。

基于 Swarm 我们还可以管理 Containers 集群服务,例如:创建一个具有五副本的连接到 Overlay 网络的 Nginx Cluster,暴露端口为 80:

$ docker service create --name my-nginx --publish target=80,published=80 --replicas=5 --network overlay nginx

在这个 Nginx Cluster 中,如果任一节点结束一个副本,那么集群服务就会重启一个新的副本,以此保持所有 Worker Node 中的 Nginx 副本数量为五个。

容器端口映射

核心选项:

  • -p 宿主机端口:将容器内应用监听端口映射到物理宿主机的特定端口上。

示例:

  • 自定义映射:
docker run -d -p 8888:80  nginx:latest 

在这里插入图片描述

  • 随机映射
# 需要镜像支持
docker run -P

猜你喜欢

转载自blog.csdn.net/Jmilk/article/details/108900394