设为首页 收藏本站
查看: 1252|回复: 0

[经验分享] Kubernetes & Docker 容器网络终极之战(十四)

[复制链接]

尚未签到

发表于 2019-2-20 09:08:13 | 显示全部楼层 |阅读模式
  与 Docker 默认的网络模型不同,Kubernetes 形成了一套自己的网络模型,该网络模型更加适应传统的网络模式,应用能够平滑的从非容器环境迁移到 Kubernetes 环境中。
  自从 Docker 容器出现,容器的网络通信一直是众人关注的焦点,而容器的网络方案又可以分为两大部分:


  • 单主机的容器间通信;
  • 跨主机的容器间通信。

一、单主机 Docker 网络通信
  利用 Net Namespace 可以为 Docker 容器创建隔离的网络环境,容器具有完全独立的网络栈,与宿主机隔离。也可以使 Docker 容器共享主机或者其他容器的网络命名空间。
  我们在使用docker run创建 Docker 容器时,可以使用--network=选项指定容器的网络模式,Docker 有以下 4 种网络模式:


  • host 模式,使用--network=host指定,不支持多主机;
  • bridge 模式,使用--network=bridge指定,默认设置,不支持多主机;
  • container 模式,使用--network=container:NAME_or_ID指定,即joiner 容器,不支持多主机;
  • none 模式,使用--network=none指定,不支持多主机。

1.1、host 模式
  连接到 host 网络的容器共享 Docker host 的网络栈,容器的网络配置与 host 完全一样。
  我们先查看一下主机的网络。

[root@datanode03 ~]# ifconfig
docker0: flags=4099  mtu 1500
inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
ether 02:42:44:8d:48:70  txqueuelen 0  (Ethernet)
RX packets 0  bytes 0 (0.0 B)
RX errors 0  dropped 0  overruns 0  frame 0
TX packets 0  bytes 0 (0.0 B)
TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
enp1s0: flags=4163  mtu 1500
inet 192.168.1.203  netmask 255.255.255.0  broadcast 192.168.1.255
inet6 fe80::2e0:70ff:fe92:4779  prefixlen 64  scopeid 0x20
ether 00:e0:70:92:47:79  txqueuelen 1000  (Ethernet)
RX packets 46093  bytes 66816291 (63.7 MiB)
RX errors 0  dropped 1  overruns 0  frame 0
TX packets 24071  bytes 1814769 (1.7 MiB)
TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73  mtu 65536
inet 127.0.0.1  netmask 255.0.0.0
inet6 ::1  prefixlen 128  scopeid 0x10
loop  txqueuelen 0  (Local Loopback)
RX packets 170  bytes 107720 (105.1 KiB)
RX errors 0  dropped 0  overruns 0  frame 0
TX packets 170  bytes 107720 (105.1 KiB)
TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  然后创建 host 网络的容器,再查看容器的网络信息。

[root@datanode03 ~]# docker run -it --network=host busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
90e01955edcd: Pull complete
Digest: sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812
Status: Downloaded newer image for busybox:latest
/ # ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:44:8D:48:70  
inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
UP BROADCAST MULTICAST  MTU:1500  Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
enp1s0    Link encap:Ethernet  HWaddr 00:E0:70:92:47:79  
inet addr:192.168.1.203  Bcast:192.168.1.255  Mask:255.255.255.0
inet6 addr: fe80::2e0:70ff:fe92:4779/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:45850 errors:0 dropped:1 overruns:0 frame:0
TX packets:23921 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:66794758 (63.7 MiB)  TX bytes:1783655 (1.7 MiB)
lo        Link encap:Local Loopback  
inet addr:127.0.0.1  Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING  MTU:65536  Metric:1
RX packets:170 errors:0 dropped:0 overruns:0 frame:0
TX packets:170 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:107720 (105.1 KiB)  TX bytes:107720 (105.1 KiB)
  在容器中可以看到 host 的所有网卡,并且连 hostname 也是 host 的,可以直接使用宿主机 IP 地址与外界通信,无需额外进行 NAT 转换。由于容器通信时,不再需要通过 Linux Bridge 等方式转发或者数据包的封装,性能上有很大的优势。

  当然,Host 模式有利也有弊,主要包括以下缺点:


  • 容器没有隔离、独立的网络栈:容器因与宿主机共用网络栈而争抢网络资源,并且容器崩溃也可能导致主机崩溃,这再生产环境中是不允许发生的。
  • 端口资源:Docker host 上已经使用的端口就不能再用了。

1.2 Bridge 模式
  Bridge 模式是 Docker 默认的网络模式,也是开发者最常用的网络模式。在这种模式下,Docker 为容器创建独立的网络栈,保证容器内的进行使用独立的网络环境,实现容器之间,容器与宿主机之间的网络栈隔离。同时,通过宿主机上的 Docker0 网桥,容器可以与宿主机乃至外界进行网络通信。

  从上图可以看出,容器是可以与宿主机以及外界的其他机器通信的,同一宿主机上,容器之间都是桥接在 Docker0 这个网桥上,Docker0 作为虚拟交换机使容器间互相通信。但是,由于宿主机的 IP 地址与容器 veth pair 的 IP 地址均不在同一个网段,故仅仅依靠 veth pair 和 NameSpace 的技术并不足以使宿主机以外的网络主动发现容器的存在。Docker 采用了端口绑定的方式(通过 iptables 的 NAT),将宿主机上的端口流量转发到容器内的端口上,这样一来,外界就可以与容器中的进程进行通信。

1.3 Container 模式
  Container 模式是一种特殊的网络模式。该模式下的容器使用其他容器的网络命名空间,网络隔离性会处于 Bridge 模式与 Host 模式之间。也就是说,当容器与其他容器共享网络命名空间时,这两个容器间不存在网络隔离,但他们与宿主机机器其他容器又存在网络隔离。
  Container 模式的容器可以通过 localhost 来与同一网络命名空间下的其他容器通信,传输效率高。这种模式节约了一定数量的网络资源,但并没有改变容器与外界的通信方式。在 Kubernetes 体系架构下引入 Pod 概念,Kubernetes 为 Pod 创建一个基础设施容器,同一 Pod 下的其他容器都以 Container 模式共享这个基础设施容器的网络命名空间,相互之间以 localhost 访问,构成一个统一的整体。


1.4、None 模式
  与前几种不同,None 模式的 Docker 容器拥有自己的 Network Namespace,但并不为 Docker 容器进行网络配置。也就是说,该 Docker 容器没有网卡、IP、路由等信息。需要用户为 Docker容器添加网卡、配置 IP 等。


二、跨主机 Docker 网络通信分类

2.1 通信方案
  常见的跨主机通信方案主要有以下几种:


  • Host 模式:容器直接使用宿主机的网络,这样天生就可以支持跨主机主机通信。这种方式虽然可以解决跨主机通信问题,但应用场景很有限,容易出现端口冲突,也无法做到隔离网络环境,一个容器崩溃很可能引起整个宿主机的崩溃;
  • 端口模式:通过绑定容器端口到宿主机端口,跨主机通信时使用主机 IP + 端口的方式访问容器中的服务。显然,这种方式仅能支持网络栈的 4 层及以上的应用,并且容器与宿主机紧耦合,很难灵活地处理问题,可扩展性不佳;
  • 定义容器网络:使用 Open vSwitch 或 Flannel 等第三方 SDN 工具,为容器构建可以跨主机通信网络环境。这一类方案一般要求各个主机上的 Docker0 网桥的 cidr 不同,以避免出现 IP 冲突的问题,限制容器在宿主机上可获取的 IP 范围。并且在容器需要对集群外提供服务时,需要比较复杂的配置,对部署实施人员的网络技能要求比较高。

2.2、容器网络规范
  容器网络发展到现在,形成了两大阵营:


  • Docker 的 CNM;
  • Google、CoreOS、Kubernetes 主导的 CNI。
  CNM 和 CNI 是网络规范或者网络体系,并不是网络实现,因此不关心容器的网络实现方式,CNM 和 CNI 关心的只是网络管理。


  • CNM(Container Network Model):CNM 的优势在于原生,容器网络和 Docker 容器生命周期结合紧密;缺点是被 Docker “绑架”。支持 CNM 网络规范的容器网络实现包括:Docker Swarm overlay、Macvlan & IP networkdrivers、Calico、Contiv、Weave等。
  • CNI(Container Network Interface):CNI 的优势是兼容其他容器技术(rkt)以及上层的编排系统(Kubernetes&Mesos)、而且社区活跃势头迅猛;缺点是非 Docker 原生。支持 CNI 的网络规范的容器网络实现包括:Kubernetes、Weave、Macvlan、Calico、Flannel、Contiv、Mesos CNI,因为它们都实现了 CNI 规范,用户无论选择哪种方案,得到的网络模型都一样,即每个 Pod 都有独立的 IP,可以直接通信。区别在于不同方案的底层实现不同,有的采用基于 VxLAN 的 Overlay 实现,有的则是 Underlay,性能上有区别。再有就是是否支持 Network Policy。

2.3、网络通信实现方案
  但从网络实现角度,又可分为:
隧道方案:隧道方案在 IaaS 层的网络中应用也比较多,它的主要缺点是随着节点规模的增长复杂度会提升,而且出了网络问题后跟踪起来比较麻烦,大规模集群情况下这是需要考虑的一个问题。


  • Weave:UDP 广播,本机建立新的 BR,通过 PCAP 互通。
  • Open vSwitch(OVS):基于 VxLAN 和 GRE 协议,但是性能方面损失比较严重。
  • Flannel:UDP 广播,VxLAN。
  • Racher:IPSec。
  路由方案:一般是基于3层或者2层实现网络隔离和跨主机容器互通的,出了问题也很容易排查。
Calico:基于 BGP 协议的路由方案,支持很细致的 ACL 控制(Nerwork Policy),对混合云亲和度比较高。
Macvlan:从逻辑和 Kernel 层来看,是隔离性和性能最优的方案。基于二层隔离,所以需要二层路由器支持,大多数云服务商不支持,所以混合云上比较难以实现。

2.4、Kubernetes 网络模型
  Kubernetes 采用的是基于扁平地址空间的网络模型,集群中的每个 Pod 都有自己的 IP 地址,Pod 之间不需要配置 NAT 就能直接通信。另外,同一个 Pod 中的容器共享 Pod 的 IP,能够通过 localhost 通信。
  这种网络模型对应用开发者和管理员相当友好,应用可以非常方便地从传统网络迁移到 Kubernetes。每个 Pod 可被看作是一个个独立的系统,而 Pod 中的容器则可被看做同一系统中的不同进程。
  Pod 内容器之间的通信
当 Pod 被调度到某个节点,Pod 中的所有容器都在这个节点上运行,这些容器共享相同的本地文件系统、IPC 和网络命名空间。
  不同 Pod 之间不存在端口冲突的问题,因为每个 Pod 都有自己的 IP 地址。当某个容器使用 localhost 时,意味着使用的是容器所属 Pod 的地址空间。
  比如 Pod A 有两个容器 container-A1 和 container-A2,container-A1 在端口 1234 上监听,当 container-A2 连接到 localhost:1234,实际上就是在访问 container-A1。这不会与同一个节点上的 Pod B 冲突,即使 Pod B 中的容器 container-B1 也在监听 1234 端口。
  Pod 之间的通信
Pod 的 IP 是集群可见的,即集群中的任何其他 Pod 和节点都可以通过 IP 直接与 Pod 通信,这种通信不需要借助任何的网络地址转换、隧道或代理技术。Pod 内部和外部使用的是同一个 IP,这也意味着标准的命名服务和发现机制,比如 DNS 可以直接使用。
  Pod 与 Service 的通信
Pod 间可以直接通过 IP 地址通信,但前提是 Pod 得知道对方的 IP。在 Kubernetes 集群中, Pod 可能会频繁的销毁和创建,也就是说 Pod 的 IP 不是固定的。为了解决这个问题,Service 提供了访问 Pod 的抽象层。无论后端的 Pod 如何变化,Service 都作为稳定的前端对外提供服务。同时,Service 还提供了高可用和负载均衡功能,Service 负责将请求转发给正确的 Pod。
  外部访问
无论是 Pod 的 IP 还是 Service 的 Cluster IP,它们只能在 Kubernetes 集群中可见,对集群之外的世界,这些 IP 都是私有的。

三、跨主机 Docker 网络

3.1 Flannel 网络方案
  Kubernetes 安装方式。

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml
  flannel 是 CoreOS 开发的容器网络解决方案。flannel 为每个 host 分配一个 subnet,容器从此 subnet 中分配 IP,这些 IP 可以在 host 间路由,容器间无需 NAT 和 port mapping 就可以跨主机通信。
  每个 subnet 都是从一个更大的 IP 池中划分的,flannel 会在每个主机上运行一个叫 flanneld 的 agent,其职责就是从池子中分配 subnet。为了在各个主机间共享信息,flannel 用 etcd(与 consul 类似的 key-value 分布式数据库)存放网络配置、已分配的 subnet、host 的 IP 等信息。
  数据包如何在主机间转发是由 backend 实现的。flannel 提供了多种 backend,有 UDP、vxlan、host-gw、aws-vpc、gce 和 alloc 路由,最常用的有 vxlan 和 host-gw。
  Flannel 实质上是一种叠加网络(Overlay Network),也就是将 TCP 数据包装在另一种网络包里面进行路由转发和通信。



  • 容器直接使用目标容器的 IP 访问,默认通过容器内部的 eth0 发送出去;
  • 报文通过 veth pair 被发送到 vethXXX;
  • vethXXX 是直接连接到 cni0,报文通过虚拟 bridge cni0 发送出去;
  • 查找路由表,外部容器 IP 的报文都会转发到 flannel.1 的虚拟网卡,这是一个 P2P 的虚拟网卡,然后报文就被转发到监听在另一端的 flanneld;
  • flanneld 通过 etcd 维护了各个节点之间的路由表,把原来的报文 UDP 封装一层,通过配置的 iface 发送出去;
  • 报文通过主机之间的网络栈找到目标主机;
  • 报文继续往上送,到达传输层,交给监听的 flanneld 程序处理;
  • 数据被解包,然后发送给 flannel.1 虚拟网卡;
  • 查找路由表,发现对应容器的报文要交给 cni0;
  • cni0 连接到自己的容器,把报文发送过去。
  我们使用 kubectl apply 安装的 flannel 默认的 backend 为 vxlan,host-gw 是 flannel 的另一个 backend,我们将前面的 vxlan backend 切换成 host-gw。
  与 vxlan 不同,host-gw 不会封装数据包,而是在主机的路由表中创建到其他主机 subnet 的路由条目,从而实现容器跨主机通信。要使用 host-gw 首先修改 flannel 的配置 flannel-config.json:

kubectl edit cm kube-flannel-cfg -o yaml -n kube-system
  找到如下字段进行修改。

  net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "host-gw"
}
}

  host-gw 把每个主机都配置成网关,主机知道其他主机的 subnet 和转发地址,由于 vxlan 需要对数据包进行额外的打包和拆包,性能会比 vxlan 强一些。

3.2、Calico 网络方案
  Kubernetes 安装方式。

kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
  Calico 把每个操作系统的协议栈当做一个路由器,然后认为所有的容器是连在这个路由器上的网络终端,在路由器之间运行标准的路由协议——BGP,然后让他们自己去学习这个网络拓扑该如何转发,所以Calico 是一个纯三层的虚拟网络方案,Calico 为每个容器分配一个 IP,每个 host 都是 router,把不同 host 的容器连接起来。与 VxLAN 不同的是,Calico 不对数据包做额外封装,不需要 NAT 和端口映射,扩展性和性能都很好。
  与其他容器网络方案相比,Calico 还有一大优势:network policy。用户可以动态定义 ACL 规则,控制进出容器的数据包,实现业务需求。



  • Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等;
  • Orchestrator Plugin:编排插件,并不是独立运行的某些进程,而是设计与 k8s、OpenStack 等平台集成的插件,如 Neutron’s ML2 plugin 用于用户使用 Neutron API 来管理 Calico,本质是要解决模型和 API 间的兼容性问题;
  • Etcd:Calico 模型的存储引擎;
  • BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。在 Calico 的角色是监听 Host 上由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉剩余 Host 节点,从而实现网络互通;
  • BGP Route Reflector(BIRD):在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。


3.3、Canal 网络方案
  Network Policy
Network Policy 是 Kubernetes 的一种资源。Network Policy 通过 Label 选择 Pod,并指定其他 Pod 或外界如何与这些 Pod 通信。
  默认情况下,所有 Pod 是非隔离的,即任何来源的网络流量都能够访问 Pod,没有任何限制。当为 Pod 定义了 Network Policy,只有 Policy 允许的流量才能访问 Pod。
  不过,不是所有的 Kubernetes 网络方案都支持 Network Policy。比如 Flannel 就不支持,Calico 是支持的。我们接下来将用 Canal 来演示 Network Policy。Canal 这个开源项目很有意思,它用 Flannel 实现 Kubernetes 集群网络,同时又用 Calico 实现 Network Policy。

kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/canal/canal.yaml
3.4、Docker overlay 网络方案
  请查看我的博文 http://blog.运维网.com/wzlinux/2112061 。

3.5、Docker macvlan 网络方案

docker network create -d macvlan --subnet=172.16.86.0/24 --gateway=172.16.86.1 -o parent=enp0s9 mac_net1
  macvlan 本身是 linxu kernel 模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP。macvlan 本质上是一种网卡虚拟化技术,Docker 用 macvlan 实现容器网络就不奇怪了。
  macvlan 的最大优点是性能极好,相比其他实现,macvlan 不需要创建 Linux bridge,而是直接通过以太 interface 连接到物理网络。
  macvlan 会独占主机的网卡,也就是说一个网卡只能创建一个 macvlan 网络:

但主机的网卡数量是有限的,如何支持更多的 macvlan 网络呢?

docker network create -d macvlan -o parent=enp0s9 mac_net2
  好在 macvlan 不仅可以连接到 interface(如 enp0s9),也可以连接到 sub-interface(如 enp0s9.xxx)。
  VLAN 是现代网络常用的网络虚拟化技术,它可以将物理的二层网络划分成多达 4094 个逻辑网络,这些逻辑网络在二层上是隔离的,每个逻辑网络(即 VLAN)由 VLAN ID 区分,VLAN ID 的取值为 1-4094。
  Linux 的网卡也能支持 VLAN(apt-get install vlan),同一个 interface 可以收发多个 VLAN 的数据包,不过前提是要创建 VLAN 的 sub-interface。
  比如希望 enp0s9 同时支持 VLAN10 和 VLAN20,则需创建 sub-interface enp0s9.10 和 enp0s9.20。
  在交换机上,如果某个 port 只能收发单个 VLAN 的数据,该 port 为 Access 模式,如果支持多 VLAN,则为 Trunk 模式,所以接下来实验的前提是:
  enp0s9 要接在交换机的 trunk 口上。不过我们用的是 VirtualBox 虚拟机,则不需要额外配置了。




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-674671-1-1.html 上篇帖子: 配置docker××× 下篇帖子: docker 实践(六)docker 资源隔离及限制
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表