K8S网络详解

K8S网络详解

按照我自己的理解,k8s网络分三个层面(由里到外):

  1. 容器网络(不同容器之间怎么相互访问)
  2. 集群内网络(不同节点之间怎么相互访问)
  3. 集群外网络(集群外怎么访问到集群内的服务)

容器网络


熟悉docker的同学会知道,docker创建的容器之间会通过一张docker0的网卡相互通信。而k8s社区为了方便用户适应各自的网络情况,暴露出一套api接口------cni,用户只要实现了这套接口就可以自定义容器网络配置策略。

CNI(Container Network Interface)是由一组用于配置Linux容器的网络接口的规范和库组成,同时还包含了一些插件。CNI仅关心容器创建时的网络分配,和当容器被删除时释放网络资源。通过此链接浏览该项目:https://github.com/containernetworking/cni。

  1. cni设计考量点
    • 容器运行时必须在调用任何插件之前为容器创建一个新的网络命名空间。
    • 然后,运行时必须确定这个容器应属于哪个网络,并为每个网络确定哪些插件必须被执行。
    • 网络配置采用JSON格式,可以很容易地存储在文件中。网络配置包括必填字段,如name和type以及插件(类型)。网络配置允许字段在调用之间改变值。为此,有一个可选的字段args,必须包含不同的信息。
    • 容器运行时必须按顺序为每个网络执行相应的插件,将容器添加到每个网络中。
    • 在完成容器生命周期后,运行时必须以相反的顺序执行插件(相对于执行添加容器的顺序)以将容器与网络断开连接。
    • 容器运行时不能为同一容器调用并行操作,但可以为不同的容器调用并行操作。
    • 容器运行时必须为容器订阅ADD和DEL操作,这样ADD后面总是跟着相应的DEL。 DEL可能跟着额外的DEL,但是,插件应该允许处理多个DEL(即插件DEL应该是幂等的)。
    • 容器必须由ContainerID唯一标识。存储状态的插件应该使用(网络名称,容器ID)的主键来完成。
    • 运行时不能调用同一个网络名称或容器ID执行两次ADD(没有相应的DEL)。换句话说,给定的容器ID必须只能添加到特定的网络一次。
  2. cni插件
    • bridge:创建网桥,并添加主机和容器到该网桥
    • ipvlan:在容器中添加一个ipvlan接口
      ipvlan类似于macvlan,区别在于端点具有相同的mac地址。 ipvlan支持L2(链路层)和L3(网络层)模式。 在ipvlan L2模式下,每个端点获得相同的mac地址但不同的ip地址。 在ipvlan l3模式下,数据包在端点之间路由,提供了更好的可伸缩性。
    • loopback:创建一个回环接口
    • macvlan:创建一个新的MAC地址,将所有的流量转发到容器
      以往,我们只能为一块以太网卡添加多个IP地址,却不能添加多个MAC地址,因为MAC地址正是通过其全球唯一性来标识一块以太网卡的,即便你使用了创建ethx:y这样的方式,你会发现所有这些“网卡”的MAC地址和ethx都是一样的,本质上,它们还是一块网卡,这将限制你做很多二层的操作。有了MACVLAN技术,你可以这么做了。
      MACVLAN技术是一种将一块以太网卡虚拟成多块以太网卡的极简单的方案。
    • ptp:创建veth对
    • vlan:分配一个vlan设备
      VLAN 技术主要就是在二层数据包的包头加上tag 标签,表示当前数据包归属的vlan 号。VLAN的主要优点: (1)广播域被限制在一个VLAN内,节省了带宽,提高了网络处理能力。 (2)增强局域网的安全性:VLAN间不能直接通信,即一个VLAN内的用户不能和其它VLAN内的用户直接通信,而需要通过路由器或三层交换机等三层设备。 (3)灵活构建虚拟工作组:用VLAN可以划分不同的用户到不同的工作组,同一工作组的用户也不必局限于某一固定的物理范围,网络构建和维护更方便灵活。
  3. ip分配
    作为容器网络管理的一部分,CNI插件需要为接口分配(并维护)IP地址,并安装与该接口相关的所有必要路由。这给了CNI插件很大的灵活性,但也给它带来了很大的负担。众多的CNI插件需要编写相同的代码来支持用户需要的多种IP管理方案(例如dhcp、host-local)。
    为了减轻负担,使IP管理策略与CNI插件类型解耦,我们定义了IP地址管理插件(IPAM插件)。CNI插件的职责是在执行时恰当地调用IPAM插件。 IPAM插件必须确定接口IP/subnet,网关和路由,并将此信息返回到“主”插件来应用配置。 IPAM插件可以通过协议(例如dhcp)、存储在本地文件系统上的数据、网络配置文件的“ipam”部分或上述的组合来获得信息。

集群内网络


k8s定义了一种资源Service,Kubernetes Service 定义了这样一种抽象:一个 Pod 的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。 这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector实现的。

对 Kubernetes 集群中的应用,Kubernetes 提供了简单的 Endpoints API,只要 Service 中的一组 Pod发生变更,应用程序就会被更新。 对非 Kubernetes 集群中的应用,Kubernetes 提供了基于 VIP(虚拟IP) 的网桥的方式访问 Service,再由 Service 重定向到相应的 Pod。

在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy(服务代理) 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式,而不是 ExternalName 的形式。

服务代理模式主要分三种:

  1. userspace 代理模式
    kube-proxy 会监视 Kubernetes master 对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会在本地 Node 上打开一个端口(随机选择)。 任何连接到“代理端口”的请求,都会被代理到 Service 的 Pods 中的某个上面。 使用哪个 Pod,是基于 Service 的 SessionAffinity 来确定的。 最后,它安装 iptables 规则,捕获到达该 Service 的 clusterIP(是虚拟 IP)和 Port 的请求,并重定向到代理端口,代理端口再代理请求到 backend Pod。
    K8S网络详解_第1张图片
  2. iptables代理模式
    kube-proxy 会监视 Kubernetes master 对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会安装 iptables 规则,从而捕获到达该 Service 的 clusterIP(虚拟 IP)和端口的请求,进而将请求重定向到 Service 的一组 backend 中的某个上面。 对于每个 Endpoints 对象,它也会安装 iptables 规则,这个规则会选择一个 backend Pod。
    K8S网络详解_第2张图片
  3. ipvs代理模式
    kube-proxy会监视Kubernetes Service对象和Endpoints,调用netlink接口以相应地创建ipvs规则并定期与Kubernetes Service对象和Endpoints对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被重定向到其中一个后端Pod。
    K8S网络详解_第3张图片

集群外网络


Ingress 是从Kubernetes集群外部访问集群内部服务的入口。

通常情况下,service和pod仅可在集群内部网络中通过IP地址访问。所有到达边界路由器的流量或被丢弃或被转发到其他地方。Ingress是授权入站连接到达集群服务的规则集合。

你可以给Ingress配置提供外部可访问的URL、负载均衡、SSL、基于名称的虚拟主机等。用户通过POST Ingress资源到API server的方式来请求ingress。 Ingress controller负责实现Ingress,通常使用负载平衡器,它还可以配置边界路由和其他前端,这有助于以HA方式处理流量。

你可能感兴趣的:(k8s)