Kubernetes(十二)--网络模型和网络策略

一、Kubernetes网络模型和CNI插件

在Kubernetes中设计了一种网络模型,要求无论容器运行在集群中的哪个节点,所有容器都能通过一个扁平的网络平面进行通信,即在同一IP网络中。需要注意的是:在K8S集群中,IP地址分配是以Pod对象为单位,而非容器,同一Pod内的所有容器共享同一网络名称空间。
1、Kubernetes网络模型

容器间的通信:同一个Pod内的多个容器间的通信,它们之间通过lo网卡进行通信。

Pod之间的通信:通过Pod IP地址进行通信。

Pod和Service之间的通信:Pod IP地址和Service IP进行通信,两者并不属于同一网络,实现方式是通过IPVS或iptables规则转发。

Service和集群外部客户端的通信,实现方式:Ingress、NodePort、Loadbalance

K8S网络的实现不是集群内部自己实现,而是依赖于第三方网络插件----CNI(Container Network Interface)

flannel、calico、canel等是目前比较流行的第三方网络插件。

这三种的网络插件需要实现Pod网络方案的方式通常有以下几种:

​虚拟网桥
多路复用(MacVLAN)
硬件交换(SR-IOV)

​ 无论是上面的哪种方式在容器当中实现,都需要大量的操作步骤,而K8S支持CNI插件进行编排网络,以实现Pod和集群网络管理功能的自动化。每次Pod被初始化或删除,kubelet都会调用默认的CNI插件去创建一个虚拟设备接口附加到相关的底层网络,为Pod去配置IP地址、路由信息并映射到Pod对象的网络名称空间。

​ 在配置Pod网络时,kubelet会在默认的/etc/cni/net.d/目录中去查找CNI JSON配置文件,然后通过type属性到/opt/cni/bin中查找相关的插件二进制文件,如下面的"portmap"。然后CNI插件调用IPAM插件(IP地址管理插件)来配置每个接口的IP地址:

[root@master dashboard]# cat /etc/cni/net.d/10-flannel.conflist
{
   
   
  "name": "cbr0",
  "cniVersion": "0.3.1",
  "plugins": [
    {
   
   
      "type": "flannel",
      "delegate": {
   
   
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    },
    {
   
   
      "type": "portmap",
      "capabilities": {
   
   
        "portMappings": true
      }
    }
  ]
}

CNI主要是定义容器网络模型规范,链接容器管理系统和网络插件,两者主要通过上面的JSON格式文件进行通信,实现容器的网络功能。CNI的主要核心是:在创建容器时,先创建好网络名称空间(netns),然后调用CNI插件为这个netns配置网络,最后在启动容器内的进程。

​ 常见的CNI网络插件包含以下几种:

Flannel:为Kubernetes提供叠加网络的网络插件,基于TUN/TAP隧道技术,使用UDP封装IP报文进行创建叠 加网络,借助etcd维护网络的分配情况,缺点:无法支持网络策略访问控制。
Calico:基于BGP的三层网络插件,也支持网络策略进而实现网络的访问控制;它在每台主机上都运行一个虚拟路由,利用Linux内核转发网络数据包,并借助iptables实现防火墙功能。实际上Calico最后的实现就是将每台主机都变成了一台路由器,将各个网络进行连接起来,实现跨主机通信的功能。
Canal:由Flannel和Calico联合发布的一个统一网络插件,提供CNI网络插件,并支持网络策略实现。
其他的还包括Weave Net、Contiv、OpenContrail、Romana、NSX-T、kube-router等等。而Flannel和Calico是目前最流行的选择方案。

2、Flannel网络插件
​ 在各节点上的Docker主机在docker0上默认使用同一个子网,不同节点的容器都有可能会获取到相同的地址,那么在跨节点通信时就会出现地址冲突的问题。并且在多个节点上的docker0使用不同的子网,也会因为没有准确的路由信息导致无法准确送达报文。

​ 而为了解决这一问题,Flannel的解决办法是,预留一个使用网络,如10.244.0.0/16,然后自动为每个节点的Docker容器引擎分配一个子网,如10.244.1.0/24和10.244.2.0/24,并将分配信息保存在etcd持久存储。

Flannel是采用不同类型的后端网络模型进行处理。其后端的类型有以下几种:

VxLAN:使用内核中的VxLAN模块进行封装报文。也是flannel推荐的方式,其报文格式如下:
在这里插入图片描述

host-gw:即Host GateWay,通过在节点上创建目标容器地址的路由直接完成报文转发,要求各节点必须在同一个2层网络,对报文转发性能要求较高的场景使用。
UDP:用普通 UDP 报文封装完成隧道转发 ,其性能较前两种方式要低很多,仅应
该在不支持前两种方式的环境中使用。

flannel 的配置参数

为了跟踪各子网分配信息等, flannel 使用 etcd 来存储虚拟 IP 和主机 IP 之间的映射,298 今 Kubernetes 进阶实战
各个节点上运行的 flanneld 守护进程负责监视 etcd 中的信息并完成报文路由 。 默认情况下,
flannel 的配置信息保存于 etcd 的键名 Icoreos .com/network/config 之下,可以使用 etcd 服务
的客户端工具来设定或修改其可用的相关配置 。 config 的值是一个 JSON 格式的字典数据结
构,它可以使用的键包含以下几个 。
I ) Network: flannel 于全局使用的 CIDR 格式的 IPv4 网络,字符串格式, 此为必选键,
余下的均为可选 。
2 ) SubnetLen :将 Network 属性指定的 IPv4 网络基于指定位的掩码切割为供各节点使
用的子网,此网络的掩码小于 24 时(如 16 ),其切割子网时使用的掩码默认为 24 位 。
3 ) SubnetMin :可用作分配给节点使用 的起始子网,默认为切分完成后的第一个子网;
字符串格式 。
4 )SubnetMax : 可用作分配给节点使用的最大子网,默认为切分完成后最大的一个子网;
字符串格式 。
5 ) Backend : flannel 要使用的后端类型,以及后端的相关配置,字典格式; VxLAN 、
host-gw 和 UDP 后端各有其相关的参数 。

flannel 默认使用 VxLAN 后端,但 VxLAN direct routing 和 host-gw 却有着更好的性能表现,接下来分析这几种网络模型 。

2.1、VxLAN后端和direct routing
​ VxLAN(Virtual extensible Local Area Network)虚拟可扩展局域网,采用MAC in UDP封装方式,具体的实现方式为:

1、将虚拟网络的数据帧添加到VxLAN首部,封装在物理网络的UDP报文中
2、以传统网络的通信方式传送该UDP报文
3、到达目的主机后,去掉物理网络报文的头部信息以及VxLAN首部,并交付给目的终端
跨节点的Pod之间的通信就是以上的一个过程,整个过程中通信双方对物理网络是没有感知的。如下网络图:
在这里插入图片描述

flannel的部署可以直接在官方上找到其YAML文件,如下:

[root@master ~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
##查看flannel的相关信息
[root@master dashboard]#  docker image ls |grep flannel
quay.io/coreos/flannel                                            v0.12.0-amd64       4e9f801d2217        10 months ago       52.8MB
[root@master dashboard]# kubectl get daemonset -n kube-system
NAME                      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-flannel-ds-amd64     3         3         3       3            3           <none>                   256d
kube-flannel-ds-arm       0         0         0       0            0           <none>                   256d
kube-flannel-ds-arm64     0         0         0       0            0           <none>                   256d
kube-flannel-ds-ppc64le   0         0         0       0            0           <none>                   256d
kube-flannel-ds-s390x     0         0         0       0            0           <none>                   256d
kube-proxy                3         3         3       3            3           kubernetes.io/os=linux   256d

flannel运行后,在各Node宿主机多了一个网络接口

#master节点的flannel.1网络接口,其网段为:10.244.0.0
[root@master kube_manifest]# ifconfig
......
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.0.0  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::f8b8:bff:fee4:4ebe  prefixlen 64  scopeid 0x20<link>
        ether fa:b8:0b:e4:4e:be  txqueuelen 0  (Ethernet)
        RX packets 24320  bytes 7363502 (7.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 29731  bytes 11204091 (10.6 MiB)
        TX errors 0  dropped 31 overruns 0  carrier 0  collisions 0
......
#node1节点的flannel.1网络接口,其网段为:10.244.1.0
[root@node1 ~]# ifconfig
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.1.1  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::4f0:55ff:fedf:ff77  prefixlen 64  scopeid 0x20<link>
        ether 06:f0:55:df:ff:77  txqueuelen 1000  (Ethernet)
        RX packets 383408  bytes 26505509 (25.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 405269  bytes 146719628 (139.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.1.0  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::f803:67ff:fecf:d005  prefixlen 64  scopeid 0x20<link>
        ether fa:03:67:cf:d0:05  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 8 overruns 0  carrier 0  collisions 0

.....
#node2节点的flannel.1网络接口,其网段为:10.244.2.0
[root@node2 ~]# ifconfig
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.2.1  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::8a4:d3ff:fedf:6222  prefixlen 64  scopeid 0x20<link>
        ether 0a:a4:d3:df:62:22  txqueuelen 1000  (Ethernet)
        RX packets 1172649  bytes 115975893 (110.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1261882  bytes 376854639 (359.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.2.0  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::f8d3:d4ff:fe99:fc09  prefixlen 64  scopeid 0x20<link>
        ether fa:d3:d4:99:fc:09  txqueuelen 0  (Ethernet)
        RX packets 28429  bytes 6632331 (6.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 22146  bytes 7280132 (6.9 MiB)
        TX errors 0  dropped 26 overruns 0  carrier 0  collisions 0
......

从上面的结果可以知道 :

flannel创建了一个flannel.1接口,它是专门用来封装隧道协议的,默认分给集群的Pod网段为10.244.0.0/16。
flannel给master节点配置的Pod网络为10.244.0.0段,给node1节点配置的Pod网络为10.244.1.0段,给node2节点配置的Pod网络为10.244.2.0段,如果有更多的节点,以此类推。

[root@master kube_manifest]# cat deploy-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec: 
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata: 
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v2
        ports:
        - name: http
          containerPort: 80
[root@master kube_manifest]# kubectl apply -f  deploy-demo.yaml 
deployment.apps/myapp-deploy created
[root@master kube_manifest]# kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
myapp-deploy-559ff5c66-2wftq   1/1     Running   0          39s   10.244.2.58   node2   <none>           <none>
myapp-deploy-559ff5c66-jxrl6   1/1     Running   0          39s   10.244.1.89   node1   <none>           <none>

可以看到,2个Pod都分别运行在两个node节点之上,在两个node节点上查看网络接口可以发现在各个节点上多了一个虚拟接口cni0。它是由flannel创建的一个虚拟网桥叫cni0,在Pod本地通信使用。 注意:cni0虚拟网桥,仅作用于本地通信。

##node1节点
[root@node1 ~]# ifconfig
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.1.1  netmask 255.255.255.0  broadcast 0.0.0.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值