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报文封装完成隧道转发。
- VxLAN:使用内核中的VxLAN模块进行封装报文,是flannel推荐的方式。报文格式如下:
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子网

浙公网安备 33010602011771号