K8s 的网络

 

Kubernetes 的网络模型

Container Network Interface (CNI) 容器网络接口,由 Google 和 CoreOS 主导。是由 CoreOS 提出的一个容器网络规范。已采纳规范的包括 Apache Mesos,Cloud Foundry,Kubernetes,Kurma 和 RKT。

K8s 网络模型设计的级别要求是:

  • 一个 Pod 一个 IP。
  • 每个 Pod 独立 IP, Pod 内所有容器共享网络 (同一个 IP)。
  • 所有容器都可以与其他容器通信。
  • 所有结点都可以与其他容器通信。

简而言之,所有 IP 都是可以通信的。

所有容器之间无需 NAT 就可以直接互相访问;所有 Node 和所有容器之间无需 NAT 就可以直接互相访;容器自己看到的 IP 跟其他容器看到的一样。

K8S 网络规范

CNI 规定了一个容器 Runtime 和网络插件之间的简单的契约。这个契约通过 JSON 的语法定义了 CNI 插件所需要提供的输入和输出。

CNI 插件提供两个功能:

  • 一个用来将网络接口加入到指定网络。
  • 另一个用来将其移除。

这两个接口分别在容器被创建和销毁的时候被调用。容器 Runtime 首先需要获得一个网络命名空间以及一个容器 ID,然后连同一些 CNI 配置参数传给网络驱动。

接着网络驱动会将该容器连接到网络并将分配的 IP 地址以 JSON 的格式返回给容器 Runtime。

K8S 网络插件要求

K8S 对网络插件的要求总的来讲主要有两个最基本的,分别是:

  • 要能够为每一个 Node 上的 Pod 分配互相不冲突的 IP 地址。
  • 要所有 Pod 之间能够互相访问。

K8S 网络实现方案

K8S网络实现方案有如下几种:

隧道方案

隧道方案在 IaaS 层的网络中应用也比较多,将 Pod 分布在一个大二层的网络规模下。网络拓扑简单,但随着节点规模的增长复杂度会提升。

代表方案:

  • Weave:UDP 广播,本机建立新的 BR,通过 PCAP 互通。
  • Open vSwitch:基于 VxLan 和 GRE 协议,但是性能方面损失比较严重。
  • Flannel:UDP 广播,VxLan。
  • Racher:IPsec。

路由方案

路由方案一般是从 3 层或者 2 层实现隔离和跨主机容器互通的,出了问题也很容易排查。

代表方案:

  • Calico:基于 BGP 协议的路由方案,支持很细致的 ACL 控制,对混合云亲和度比较高。
  • Macvlan:从逻辑和 Kernel 层来看隔离性和性能优的方案,基于二层隔离,所以需要二层路由器支持,大多数云服务商不支持,所以混合云上比较难以实现。

K8S Pod 的网络创建流程

K8S Pod 的网络创建流程如下:

  • 每个 Pod 除了创建时指定的容器外,都有一个 Kubelet 启动时指定的基础容器。
  • Kubelet 创建基础容器,生成 Network Namespace。
  • Kubelet 调用网络 CNIdriver,根据配置调用具体的 CNI 插件。
  • CNI 插件给基础容器配置网络。
  • Pod 中其他的容器共享基础容器的网络。

Pod 中的网络

Pod 是 K8S 的最小工作单元。每个 Pod 包含一个或多个容器。K8S 管理的也是 Pod 而不是直接管理容器。Pod 中的容器会作为一个整体被 Master 调度到一个 Node 上运行。

Pod 的设计理念是支持多个容器在一个 Pod 中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。

一个 Pod 中可以包含多个容器,而一个 Pod 只有一个 IP 地址。那么多个容器之间互相访问和访问外网是如何使用这一个 IP 地址呢?

答案是:多个容器共享同一个底层的网络命名空间 Net (网络设备、网络栈、端口等)。

下面以一个小例子说明,创建一个 Pod 包含两个容器,yaml 文件如下:

apiVersion: apps/v1beta1 
kind: Deployment 
metadata: 
  name: Pod-two-container 
spec: 
  replicas: 1 
  template: 
    metadata: 
      labels: 
        app: nginx 
    spec: 
      containers: 
      - name: busybox 
        image: busybox 
        command: 
        - "/bin/sh" 
        - "-c" 
        - "while true;do echo hello;sleep 1;done" 
      - name: nginx 
        image: nginx 

EOF