Life is too bug

Kubernetes 中的网络结构

2019.02.12

Kubernetes 采用的是基于扁平地址空间的网络模型,集群中的每个 Pod 都有自己的 IP 地址,Pod 之间不需要配置 NAT 就能直接通信。另外,同一个 Pod 中的容器共享 Pod 的 IP,能够通过 localhost 通信。

  • IP-per-Pod,每个 Pod 都拥有一个独立 IP 地址,Pod 内所有容器共享一个网络命名空间

  • 集群内所有 Pod 都在一个直接连通的扁平网络中,可通过 IP 直接访问

    • 所有容器之间无需 NAT 就可以直接互相访问
    • 所有 Node 和所有容器之间无需 NAT 就可以直接互相访问
    • 容器自己看到的 IP 跟其他容器看到的一样
  • Service cluster IP 尽可在集群内部访问,外部请求需要通过 NodePort、LoadBalance 或者 Ingress 来访问

  • 网络的命名空间:Linux在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命令空间中,彼此间无法通信;docker利用这一特性,实现不容器间的网络隔离。

  • Veth设备对:Veth设备对的引入是为了实现在不同网络命名空间的通信。

  • Iptables/Netfilter:Netfilter负责在内核中执行各种挂接的规则(过滤、修改、丢弃等),运行在内核 模式中;Iptables模式是在用户模式下运行的进程,负责协助维护内核中Netfilter的各种规则表;通过二者的配合来实现整个Linux网络协议栈中灵活的数据包处理机制。

  • 网桥:网桥是一个二层网络设备,通过网桥可以将linux支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信。

  • 路由:Linux系统包含一个完整的路由功能,当IP层在处理数据发送或转发的时候,会使用路由表来决定发往哪里

下面介绍几种网络实现

flannel

Flannel 是一个为 Kubernetes 提供 overlay network 的网络插件,它基于 Linux TUN/TAP,使用 UDP 封装 IP 包来创建 overlay 网络,并借助 etcd 维护网络的分配情况。

如何工作

Flannel 需要在集群中的每台主机上运行一个名为 flanneld 的代理程序,负责从预配置地址空间中为每台主机分配一个网段。Flannel 直接使用 Kubernetes API 或 ETCD 存储网络配置、分配的子网以及任何辅助数据(如主机的公网 IP)。数据包使用几种后端机制之一进行转发,包括 VXLAN 和各种云集成。

backend

Flannel 可以与几种不同的后端搭配。一旦后端设置完成,就不应在运行时更改。 VXLAN 是推荐的选择。对于有经验的用户,如果希望提高性能和基础架构支持(通常不能在云环境中使用),建议使用 host-gwUDP 建议仅用于调试,或者用于不支持 VXLAN 的非常旧的内核。 另外,还有实验性的 AWS、GCE 和 AliVPC,所有支持的后端可以 参考这里

VXLAN

使用内核的 VXLAN 封装数据包。 Type 和选项: - Type:字符串,vxlan - VNI:数字,要使用的 VXLAN Identifier (VNI) 。默认是 1。 - Port:数字,用于发送封装的数据包 UDP 端口。默认值由内核决定,目前是 8472。 - GBP:布尔值,启用 基于 VXLAN 组的策略。默认是 false。 - DirectRouting:布尔值,当主机位于同一子网时,启用直接路由(类似 host-gw)。VXLAN 将仅用于将数据包封装到不同子网上的主机。默认为 false。

 ip r
default via 192.168.12.1 dev enp0s3
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 linkdown
192.168.12.0/24 dev enp0s3  proto kernel  scope link  src 192.168.12.102
host-gw
 ip r
default via 192.168.12.1 dev enp0s3
10.244.0.0/24 dev cni0  proto kernel  scope link  src 10.244.0.1
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 linkdown
192.168.12.0/24 dev enp0s3  proto kernel  scope link  src 192.168.12.102
default via 192.168.12.1 dev enp0s3
10.244.0.0/24 dev cni0  proto kernel  scope link  src 10.244.0.1
10.244.2.0/24 via 192.168.12.107 dev enp0s3
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 linkdown
192.168.12.0/24 dev enp0s3  proto kernel  scope link  src 192.168.12.102
ip r
default via 192.168.12.1 dev enp0s3
10.244.0.0/24 via 192.168.12.102 dev enp0s3
10.244.2.0/24 dev cni0  proto kernel  scope link  src 10.244.2.1
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 linkdown
192.168.12.0/24 dev enp0s3  proto kernel  scope link  src 192.168.12.107
cat /etc/cni/net.d/10-flannel.conflist
{
  "name": "cbr0",
  "plugins": [
    {
      "type": "flannel",
      "delegate": {
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    },
    {
      "type": "portmap",
      "capabilities": {
        "portMappings": true
      }
    }
  ]
}

10: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
    link/ether 3e:99:d6:c1:e9:bb brd ff:ff:ff:ff:ff:ff
    inet 10.244.0.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
ip r
default via 192.168.12.1 dev enp0s3
10.244.0.0/24 dev cni0  proto kernel  scope link  src 10.244.0.1
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 linkdown
192.168.12.0/24 dev enp0s3  proto kernel  scope link  src 192.168.12.102

host-gw

使用 host-gw 通过远程计算机 IP 创建到子网的 IP 路由。运行 flannel 的主机之间需要直接连接第 2 层(数据链路层)。(Use host-gw to create IP routes to subnets via remote machine IPs. Requires direct layer2 connectivity between hosts running flannel.) host-gw 性能好,依赖少,并且易于设置。 Type: - Type:字符串,host-gw 下面对 host-gw 和 vxlan 这两种 backend 做个简单比较。 1. host-gw 把每个主机都配置成网关,主机知道其他主机的 subnet 和转发地址。vxlan 则在主机间建立隧道,不同主机的容器都在一个大的网段内(比如 10.2.0.0/16)。 2. 虽然 vxlan 与 host-gw 使用不同的机制建立主机之间连接,但对于容器则无需任何改变,bbox1 仍然可以与 bbox2 通信。 3. 由于 vxlan 需要对数据进行额外打包和拆包,性能会稍逊于 host-gw。 host-gw只支持二层互通的网络

UDP

不可用于生产环境。仅在内核或网络无法使用 VXLAN 或 host-gw 时,用 UDP 进行 debug。 Type 和选项:

  • Type:字符串,udp
  • Port:数字,用于发送封装数据包的 UDP 端口号,默认是 8285

    Logging

  • 从容器运行 flannel 时,将安装 Strongswan 工具。swanctl 可用于与 charon 交互,并提供日志命令..

  • Charon 的日志也会写入 flannel 进程的标准输出。

    Troubleshooting

  • ip xfrm state 可以用来与内核的安全关联数据库进行交互。这可以用来显示当前安全关联(SA)以及主机是否成功建立到其他主机的 IPsec 连接。

  • ip xfrm policy 可以用来显示已安装的策略。Flannel 为每个连接的主机安装三个策略。 Flannel 不会恢复手动删除的策略(除非重新启动 Flannel)。它也不会在启动时删除陈旧的策略。可以通过重新启动主机或通过 ip xfrm state flush && ip xfrm policy 策略刷新和重新启动 flannel 来删除所有 ipsec 状态来删除它们。 Flannel 可以被添加到任何已经存在的 Kubernetes 集群中。但是在 Pod 使用网络之前添加 Flannel 是最简单的。 对于 Kubernetes v1.7+:

    Ref

Kubernetes: Flannel networking

https://blog.laputa.io/kubernetes-flannel-networking-6a1cb1f8ec7c

kubernetes flannel代码解析

https://ieevee.com/tech/2017/08/12/k8s-flannel-src.html

GCE 理解k8s的网络 https://medium.com/google-cloud/understanding-kubernetes-networking-pods-7117dd28727

comments powered by Disqus