自学内容网 自学内容网

了解 k8s 网络基础知识

了解

Docker 网络模式

在使用 Docker run 创建 Docker 容器时,可以使用 --net 选项指定容器的网络模式,Docker 可以有4种网络模式。

  1. host 模式。–net=host 指定和宿主机共用一个 NetWork Namespace,容器中的网络环境(ip 地址、路由等)和宿主机的网络环境一致。
  2. none 模式。使用 --net=none 指定关闭网络功能。
  3. bridge 模式。–net=bridge 指定默认设置,容器使用独立的 Network Namespace,并连接到 Docker0 虚拟网桥,通过 iptables nat 表配置和宿主机进行通信。
  4. container 模式,–net=container:NAME_or_ID 指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡、配置IP,而是和一个指定的容器共享IP、端口范围等等。

Flannel 支持三种后端实现,分别是:VXLAN、host-gw、UDP。

理解容器 “跨主通信” 的原理,从 Flannel 插件讲起

第一种:UDP 模式

Flannel 的 UDP 模式,该模式是 Flannel 最原始使用解决容器跨主机网络的实现方法之一。

栗子:

  • 宿主机 Node 1 上有一个容器 container-1,它的 IP 地址是 100.96.1.2,对应的 docker0 网桥的地址是:100.96.1.1/24。
  • 宿主机 Node 2 上有一个容器 container-2,它的 IP 地址是 100.96.2.3,对应的 docker0 网桥的地址是:100.96.2.1/24。

现在的任务,就是让 container-1 访问 container-2。

flanneld 在收到 container-1 发给 container-2 的 IP 包之后,就会把这个 IP 包直接封装在一个 UDP 包里,然后发送给 Node 2。不难理解,这个 UDP 包的源地址,就是 flanneld 所在的 Node 1 的地址,而目的地址,则是 container-2 所在的宿主机 Node 2 的地址。

第二种:VXLAN 模式(虚拟可扩展局域网)

Agenda

k8s NetWork Components

  • Pod NetWorking within and between nodes
  • Service abstractions (service registraton & discovery)
  • DNS
  • Ingress (L7 HTTP routing)
  • NetWork Policies access control (Application “Firewall”)

二层网络:假如两个 Pod 的IP 地址分为为 10.170.2.2 和 10.170.2.3 它们的网断都是相同的,叫 二层网络通信。

三层网络:两个 Pod 的IP 地址分为为 10.170.2.2 和 10.170.3.2 不同网断或者说跨网卡通信的叫三层

假设两个 Pod 的IP 地址分为为 10.170.2.2 和 10.170.3.2 ,网段不同但是属于一个网卡,怎么解决它们之间通信呢,可以使用 VXLAN 的解决方案,他可以在三层网络作二层传输。

k8s Network Model

  • All Pods can reach all other Pods, without NAT 。Implementaions :
    • Flat
    • Overlays(e.g:VXLAN)
    • Routing(e.g:BGP)
  • All Nodes can reach all other Nodes,without NAT
  • IPAM-IP Address Management

Services : Problem

services 将一组 Pod 抽象成一个 Service,后面做个负载均衡

让 Pod 能够 ping 外网解决 DNS

Ingress

和 Service 区别:

  • Service 是 4 层网络模型,只能提供到 (IP + 端口)OSI
  • Ingress 是 7 层网络模型,HTTP 代理和路由

/etc/cni/net.d 该目录是k8s使用那种网络插件

k8s CNI Introduction

k8s CNI Canal Lab Demo

K8s 与 Linux 网络

Linux Namespace 机制

Linux namespace 实现了 6 项资源隔离,基本上涵盖了一个小型操作系统的运行要素,包括主机名、用户权限、文件系统、网络、进程号、进程间通信。

namespace系统调用参数隔离内容内核版本
UTSCLONE_NEWUTS主机名和域名2.6.19
IPCCLONE_NEWIPC信号量、消息队列和共享内存2.6.19
PIDCLONE_NEWPID进程编号2.6.24
NetworkCLONE_NEWNET网络设备、网络栈、端口等2.6.29
MountCLONE_NEWNS挂载点(文件系统)2.4.19
UserCLONE_NEWUSER用户和用户组3.8

在这里插入图片描述

Docker 网络模式

在使用 Docker run 创建 Docker 容器时,可以使用 --net 选项指定容器的网络模式,Docker 可以有4种网络模式。

  1. host 模式。–net=host 指定和宿主机共用一个 NetWork Namespace,容器中的网络环境(ip 地址、路由等)和宿主机的网络环境一致。
  2. none 模式。使用 --net=none 指定关闭网络功能。
  3. bridge 模式。–net=bridge 指定默认设置,容器使用独立的 Network Namespace,并连接到 Docker0 虚拟网桥,通过 iptables nat 表配置和宿主机进行通信。
  4. container 模式,–net=container:NAME_or_ID 指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡、配置IP,而是和一个指定的容器共享IP、端口范围等等。

Overlay 网络

Overlay 网络时建立在实际物理网络(Underlay网络)之上的虚拟网络。underlay 网络和 设备都是真正存在的实体,而 Overlay网络时依赖 Underlay网络虚拟出来的。

比如两个设备之间通过TCP或UDP通信,那么这就是underlay网络。但在TCP或UDP协议上可以承载应用数据,如果应用数据承载了IP协议,那么这个 Overlay网络是三层网络;而如果应用数据承载了数据链路层协议,那么这个 overlay网络时二层网络。

在这里插入图片描述

这个装置如何实现呢?在Linux里有个隧道技术

  • linux tun:在三层网络之上构建三层网络,Overlay网络通信协议位于IP层及以上。(IP、tcp/udp、ftp/http)overlay网络中不支持arp协议。
  • linux vxlan:在三层网络(tcp/ip)之上构建二层网络。overlay 网络通信协议位于数据链路层及以上。overlay网络支持arp协议(Ethernetll,ip,tcp/udp,ftp/http等)

iptables

  • filter:过滤数据包,实现软件防火墙的功能
  • nat:网络地址转换(改变源IP、 目的IP、 源端口、目的端口)
  • mangle:修改数据包的服务类型、TTL、 并且可以配置路由实现Q0S内核模块
  • raw:决定数据包是否被状态跟踪机制处理

iptables链的匹配原则:
从序列号为1的开始匹配,直到匹配到第一条合适的规则并执行, 后续规则即使能够匹配也不再执行,所以将经常会被匹配到的规则放在表前面。

iptables 五链

在这里插入图片描述

容器技术之网络

容器隔离技术:

  • namespace,也即每个 namespace 中的应用看到的是不同的 IP 地址、用户空间、程号等。
  • cgroup,也即明明整台机器有很多的 CPU、内存,而一个应用只能用其中的一部分。

1、单机下,Linux 容器网络(网桥模式)

Docker 项目会默认在宿主机上创建一个名叫 docker0 的网桥,凡是连接在 docker0 网桥上的容器,就可以通过它来进行通信。可是,我们又该如何把这些容器“连接”到 docker0 网桥上呢?这时候,我们就需要使用一种名叫 Veth Pair 的虚拟设备了。

同一个宿主机上的不同容器通过 docker0 网桥进行通信的流程:

在这里插入图片描述

当你遇到容器连不通“外网”的时候,你都应该先试试 docker0 网桥能不能 ping 通,然后查看一下跟 docker0 和 Veth Pair 设备相关的 iptables 规则是不是有异常,往往就能够找到问题的答案了。

2、容器“跨主机通信”问题

如果在另外一台宿主机(比如:10.168.0.3)上,也有一个 Docker 容器。那么,我们的 在另一台宿主机上的容器之间又该如何访问它呢?

容器的“跨主通信”问题

在 Docker 的默认配置下,一台宿主机上的 docker0 网桥,和其他宿主机上的 docker0 网桥,没有任何关联,它们互相之间也没办法连通。所以,连接在这些网桥上的容器,自然也没办法进行通信了。

构建这种容器网络的核心在于:我们需要在已有的宿主机网络上,再通过软件构建一个覆盖在已有宿主机网络之上的、可以把所有容器连通在一起的虚拟网络。所以,这种技术就被称为:Overlay Network(覆盖网络)。

从 Flannel 说起,目前 Flannel 支持三种后端实现,分别是:VXLAN、host-gw、UDP;

2.1、Flannel UDP 模式

当 IP 包从容器经过 docker0 出现在宿主机,然后又根据路由表进入 flannel0 设备后,宿主机上的 flanneld 进程(Flannel 项目在每个宿主机上的主进程),就会收到这个 IP 包。然后,flanneld 看到了这个 IP 包的目的地址,是 100.96.2.3,就把它发送给了 Node 2 宿主机。

flanneld 又是如何知道这个 IP 地址对应的容器,是运行在 Node 2 上的呢?子网(Subnet)

事实上,在由 Flannel 管理的容器网络里,一台宿主机上的所有容器,都属于该宿主机被分配的一个“子网”。在我们的例子中:

  • Node 1 的子网是 100.96.1.0/24,container-1 的 IP 地址是 100.96.1.2;
  • Node 2 的子网是 100.96.2.0/24,container-2 的 IP 地址是 100.96.2.3。

所以,flanneld 进程在处理由 flannel0 传入的 IP 包时,就可以根据目的 IP 的地址(比如 100.96.2.3),匹配到对应的子网(比如 100.96.2.0/24),从 Etcd 中找到这个子网对应的宿主机的 IP 地址是 10.168.0.3

而接下来 flanneld 的工作就非常简单了:flanneld 会直接把这个 IP 包发送给它所管理的 TUN 设备,即 flannel0 设备。根据我前面讲解的 TUN 设备的原理,这正是一个从用户态向内核态的流动方向(Flannel 进程向 TUN 设备发送数据包),所以 Linux 内核网络栈就会负责处理这个 IP 包,具体的处理方法,就是通过本机的路由表来寻找这个 IP 包的下一步流向。

docker0 网桥会扮演二层交换机的角色,将数据包发送给正确的端口,进而通过 Veth Pair 设备进入到 container-2 的 Network Namespace 里。

2.2、Virtual Extensible LAN(虚拟可扩展局域网)

VXLAN 是 Linux 内核本身就支持的一种网络虚似化技术。所以说,VXLAN 可以完全在内核态实现上述封装和解封装的工作,从而通过与前面相似的“隧道”机制,构建出覆盖网络(Overlay Network)。

2.3、CNI 插件工作原理

CNI 插件的工作原理:

当 kubelet 组件需要创建 Pod 的时候,它第一个创建的一定是 Infra 容器。所以在这一步,dockershim 就会先调用 Docker API 创建并启动 Infra 容器,紧接着执行一个叫作 SetUpPod 的方法。这个方法的作用就是:为 CNI 插件准备参数,然后调用 CNI 插件为 Infra 容器配置网络。

容器与容器之间要“通”,容器与宿主机之间也要“通”。并且,Kubernetes 要求这个“通”,还必须是直接基于容器和宿主机的 IP 地址来进行的。

2.4、host-gw

工作原理:

在这里插入图片描述

假设现在,Node 1 上的 Infra-container-1,要访问 Node 2 上的 Infra-container-2。

当你设置 Flannel 使用 host-gw 模式之后,flanneld 会在宿主机上创建这样一条规则,以 Node 1 为例:

可以看到,host-gw 模式的工作原理,其实就是将每个 Flannel 子网(Flannel Subnet,比如:10.244.1.0/24)的“下一跳”,设置成了该子网对应的宿主机的 IP 地址。

不难看出,host-gw 模式能够正常工作的核心,就在于 IP 包在封装成帧发送出去的时候,会使用路由表里的“下一跳”来设置目的 MAC 地址。这样,它就会经过二层网络到达目的宿主机。

Flannel host-gw 模式必须要求集群宿主机之间是二层连通的。

2.5、Calico 插件

实际上,Calico 项目提供的网络解决方案,与 Flannel 的 host-gw 模式,几乎是完全一样的。也就是说,Calico 也会在每台宿主机上,添加一个格式如下所示的路由规则:

<目的容器IP地址段> via <网关的IP地址> dev eth0

其中,网关的 IP 地址,正是目的容器所在宿主机的 IP 地址。三层网络方案得以正常工作的核心,是为每个容器的 IP 地址,找到它所对应的、“下一跳”的网关。

不过,不同于 Flannel 通过 Etcd 和宿主机上的 flanneld 来维护路由信息的做法,Calico 项目使用了一个“BGP”来自动地在整个集群中分发路由信息。BGP 的全称是 Border Gateway Protocol,即:边界网关协议。

Calico 项目的架构就非常容易理解了。它由三个部分组成:

  • Calico 的 CNI 插件。这是 Calico 与 Kubernetes 对接的部分。
  • Felix。它是一个 DaemonSet,负责在宿主机上插入路由规则(即:写入 Linux 内核的 FIB 转发信息库),以及维护 Calico 所需的网络设备等工作。
  • BIRD。它就是 BGP 的客户端,专门负责在集群里分发路由规则信息。

3、Cilium

在 5.10 内核以后,Cilium 新增了 eBPF Host-Routing 功能,该功能更加速了 eBPF 数据面性能,新增了 bpf_redirect_peer 和 bpf_redirect_neigh 两个 redirect 方式,bpf_redirect_peer 可以理解成 bpf_redirect 的升级版,其将数据包直接送到 veth pair Pod 里面接口 eth0 上,而不经过宿主机的 lxc 接口,这样实现的好处是少进入一次 cpu backlog queue 队列,该特性引入后,路由模式下,Pod -> Pod 性能接近 Node -> Node 性能,同时 Cilium 数据面路径发生了较大的变化。

文档链接:https://www.yuque.com/wei.luo/cni/vwtmwz

文档地址:https://www.yuque.com/wei.luo/cni/qubifn

文档地址:20210903-eBPF XDP TC介绍


原文地址:https://blog.csdn.net/realize_dream/article/details/144311944

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!