Kubernetes

Kubernetes 的网络模型

Posted on 2020-10-12,6 min read

K8S 的网络特征:

  1. 每个POD 一个IP (IP peer POD)
  2. 所有POD 通过IP 直接访问其他POD 而不管POD 是否在同一台物理机上
  3. POD 内的所有容器共享一个LINUX NET NAMESPACE (网络堆栈), POD 内的容器, 都可以使用localhost 来访问pod 内的其他容器.

K8S 对集群网络的要求:

  1. 所有容器都可以在不用NAT 的方式下访问其他容器
  2. 所有节点都可以在不用NAT的方式下同所有容器通信,反之亦然
  3. 容器的地址和别人看到的地址是同一个地址

kubernetes 网络实现

POD 间通信网络模型

image.png

NODE 间通信网络模型

image.png

ip1 ip2 都存在 etcd中

K8S 不同node 中pod 相互通信需要满足的条件如下

  1. 整个K8S集群中的POD IP 分配不能有冲突
  2. 找到一种办法,将 POD 的 IP 和所在的 NDOE 的 IP 关联起来, 通过这个关联让 POD 相互访问

条件1 要求NODE 中的docker0 的网桥地址不能冲突

条件2 要求 POD 中的数据在出发时,需要有一个机制能够知道对方 POD 的 IP 地址在哪个NODE上

满足条件的扁平化网络拓扑如下

image.png

默认docker0 的网络为 172.17.0.0/16 的网段. 每个容器都在这个子网内获得 IP 并且将 docker0 作为网关

docker 宿主机不需要知道任何关于docker 0 的信息, 因为docker 宿主机对任何容器发出的数据,在物理卡上都做了 IP 伪装(masquerade 隐含nat),也就是说其他任何node看到的数据包来源都是宿主机的物理网卡IP

这个模型的缺点是, 需要使用nat技术

K8S 模型中,每个 NODE 上的 docker0 都是可以被路由到的, 也就是说, 在部署一个 POD 时, 在同一个集群内, 各个主机都可以访问其他主机上的 POD IP, 并不需要在主机上做端口映射.

我们可以把NODE 看作交换机网络模型看起来就是下面这个样子

image.png

在node中,我们目前采用直接路由的方式来实现.在每个node上配置讲台路由

例如在192.168.1.10 上配置

route add -net 10.1.20.0 netmask 255.255.255.0 gw 192.168.1.20
route add -net 10.1.30.0 netmask 255.255.255.0 gw 192.168.1.30
复制代码

当我们启动一个POD ,要求POD 下的所有容器都使用同一个网络命名空间,以及同一个IP,所以必须要使用容器网络的 container 模式. 如果将所有 pod 中的容器做成一个链的结构, 中间任何一个容器出问题, 都会引起连锁反映, 所以在每个 POD 中都引入一个 google_containers/pause 其他容器都链接到这个容器, 由 google_containers/pause 来负责端口规划和映射

POD 内部的网络模型为

image.png

pause 容器用于接管pod的endpoint.

通过docker inpsect <id> | grep NetworkMod 查看pause 容器的网络模式,可以看到使用的是bridge 而 业务容器 docker inpsect < 业务容器id> | grep NetworkMod 使用的是 container:<长ID>

Service 的网络信息

当在K8S中创建一个service(非 NODEPORT) 之后, K8S 会为每个 service 分配一个cluster IP

roger@microk8s:~$ kubectl get service
NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
default-http-backend   ClusterIP   10.152.183.69    <none>        80/TCP    11d
http-svc               ClusterIP   10.152.183.164   <none>        80/TCP    11d

复制代码

IP 地址段为 apiserver 启动时, --server-cluster-ip-range 所指定的 IP 段,这个 IP 段不能和 docker0 的 IP 段冲突, 这个网段不会在 物理网络和 docker0 之间路由. 这个portal network 的意义是让容器流量都指向默认的网关,也就docker0

查看iptables-save 数据

:KUBE-POSTROUTING - [0:0]
...
-A KUBE-PORTALS-CONTAINER -d 10.152.183.69/32 -p tcp -m comment --comment "default/default-http-backend:" -m tcp --dport 80 -j REDIRECT --to-ports 37853
-A KUBE-PORTALS-CONTAINER -d 10.152.183.164/32 -p tcp -m comment --comment "default/http-svc:http" -m tcp --dport 80 -j REDIRECT --to-ports 35667
-A KUBE-PORTALS-CONTAINER -d 10.152.183.1/32 -p tcp -m comment --comment "default/kubernetes:https" -m tcp --dport 443 -j REDIRECT --to-ports 40441
...
-A KUBE-PORTALS-HOST -d 10.152.183.69/32 -p tcp -m comment --comment "default/default-http-backend:" -m tcp --dport 80 -j DNAT --to-destination 192.168.10.5:37853
-A KUBE-PORTALS-HOST -d 10.152.183.164/32 -p tcp -m comment --comment "default/http-svc:http" -m tcp --dport 80 -j DNAT --to-destination 192.168.10.5:35667
-A KUBE-PORTALS-HOST -d 10.152.183.1/32 -p tcp -m comment --comment "default/kubernetes:https" -m tcp --dport 443 -j DNAT --to-destination 192.168.10.5:40441


可以发现, 到三个服务的流量都被重定向到一个随机端口, 37853, 35667, 40441 . 这几个端口都是由kube-proxy 创建的, kube-proxy 服务会为每个创建的service 都关联一个随机端口,并监听那个特定的端口, 为服务创建相关联的负载均衡.

image.png

注意, node3 的kubeproxy 并未参与此次交互. node1 的kube-proxy 起到了负载均衡的作用

下一篇: K8s 持久化存储流程→