17.K8S网络

一、k8s网络模型和CNI插件

  K8S中IP是分给pod的,而不是容器。

1.1.Dokcer网络模型

  Bridge:--network=bridge,默认设置,容器IP桥接到宿主机的虚拟网桥上docker0(通过NAT方式)

    docker在启动时会创建天体战士docker0网络,默认地址为172.17.0.1/16。

  Host:--network=host,与物理主机共享一个network namespace,没有自已独立的网络命名空间,共享物理机的IP与端口

  none:--network=none,不为容器配置任何网络参数。

  container:联合网络,两个容器共享一个网络名称空间,--network=container,类似host模式,但共享的是其它容器的ip、端口。

1.1.1.Bridge

#ip addr show docker0

 

 

 这个vethxxxxx网卡会桥接到docker0上。容器内会有一张eth0xxx的网卡与vethxxx是一对veth pair,这综合部是成对出现的特殊网络设备(好像有一虚拟网线进行连接一样)。

修改docker默认网络配置

1.用命令修改,临时生效

systemctl stop docker.service

ip addr del 172.17.0.1/16 dev docker0

ip addr add 192.168.10.1//24 dev docker0

systemctl start docker.service

2.修改配置文件

vim /etc/docker/daemon.json

{
  "graph": "/data/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io","harbor.od.com"],
  "registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"],
  "bip": "172.2.200.1/24",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true
}


重启docker服务生效。

3.也可以修改/lib/systemd/system/docker.service

cp /lib/systemd/system/docker.service /etc/systemd/system/docker.service

vim /etc/systemd/system/docker.service



[Unit]                  
Description=Docker Application Container Engine ##一段描述这个Unit文件的文字,通常只是简单的一句话
Documentation=https://docs.docker.com       ##指定服务的文档,可以使一个或多个文档的URL路径
After=network.target docker.socket      ##会在后面列出的所有模块全部启动完成以后,才会启动当前的服务
Requires=docker.socket              ##依赖的其他 Unit 列表,列在其中的 Unit 模块会在这个服务启动的同时被启动,并且如果其中有任意一个服务启动失败,这个服务也会被终止。

[Service]                   
##这个段是 .service 文件独有的,也是对于服务配置最重要的部分
Type=notify                 ##服务的类型
ExecStart=/usr/bin/docker daemon -H fd:// --bip="172.2.200.1/24" --insecure-registry 172.25.254.66:5000        ##指定服务启动的主要命令,--bip="172.2.200.1/24"设定网桥地址
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0

[Install]                   
##这部分配置需要通过 systemctl enable 命令来激活,并且可以通过 systemctl disable 命令禁用
WantedBy=multi-user.target          ##列出依赖当前服务的模块
systemctl daemon-reload   ##重新加载

在Bridge模式下,连接在同一网桥上的容器可以相互通信,容器也可以与外部通信。这种方式不能跨主机通信,仅能在宿主机本地进行,可以用NAT解决。一般用第三方网络插件实现跨主机通信的网络策略。

 

 

在iptables中会与容器的转发规则

docker run -d --name web2 -p 1514:10514 myapp

1.1.2.Host

docker run -it --rm --net=host myalpine /bin/sh

容器中的ip与宿主机的ip相同,容器中运行ip addr结果与宿主机相同。

1.1.3.container--联合网络

  两个容器共享一个网络名称空间,两个容器的ip addr内容相同。

docker run -it --rm --net=container:其它容器ID apline /bin/sh

1.2.K8S网络模型

  K8S上的网络通信包含:

    • 容器间的通信:同一个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

  在配置Pod网络时,kubelet动作过程:

  在默认的/etc/cni/net.d/目录中查找CNI JSON配置文件---->通过type属性到/opt/cni/bin中查找插件二进制文件,如portmap----->CNI插件调用IPAM插件(IP地址管理插件)配置每个接口的IP地址。

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

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

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

  • Flannel:为K8S提供叠加网络的网络插件,基于TUN/TAP隧道技术,使用UDP封装IP报文进行创建叠加网络,借助etcd维护网络的分配情况,缺点:无法支持网络策略访问控制。
  • Calico:基于BGP的三层网络插件,也支持网络策略而实现网络的访问控制;
  • Canal:由Flannel和Calico联合发布的一个统一网络插件,提供CNI网络插件,并支持网络策略实现。

1.3.Flannel网络插件

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

  Flannel解决方法:

    • IP冲突问题:预留一个使用网络,如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报文封装完成隧道转发。

1.4.VxLAN后端和direct routing

  VxLAN(Virtual extensible Local Area Network),采用MAC  in UDP封装:

    • 将虚拟网络的数据帧添加到VxLAN首部,封装在物理网络的UDP报文中。
    • 以传统网络的通信方式传送该UDP报文。
    • 到达目的主机后,去掉物理网络报文的头部信息以及VxLAN首部,并交付给目的终端。

  跨节点的Pod之间的通信就是上面的过程,整个过程对物理网络是无感知的:

  

 

 

   VxLAN的部署在官网上有YAML文件,部署完成后会在/etc/cni/net.d目录下生成flanneld配置文件,kubelet将会调用它。

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml

kubecctl get daemonset -n kube-system

  各Node多一个网络接口:

ifconfig flannel1.1    ##node1的IP:10.244.0.0;node2的IP:10.244.1.0  都是10.244.0.0/16子网

 

posted @ 2022-01-04 16:00  天涯160  阅读(138)  评论(0)    收藏  举报