[基于树莓派]深入剖析Kubernetes - 2

[基于树莓派]深入剖析Kubernetes
上篇的续集

15.自己编写存储插件

FlexVolume…

CSI…

16.容器网络

# 声明该运行的容器直接使用宿主的网络栈
# 通过该方式,我们可以直接在宿主机上进行不同容器间的通信,因为所有容器都使用的为宿主机的网络;
docker run –d –net=host --name nginx-host nginx

16.1.Veth Pair虚拟设备

Veth Pair被创建后会以两张虚拟网卡的形式成对出现;从一张网卡发出的数据包,会直接出现在与它对应的另一张网卡上,哪怕这两张网卡在不同Network Namespace中;

# 如下图,我们可以看到该运行的容器的默认网卡为 eth0

docker run -it --rm busybox /bin/sh

在这里插入图片描述
该网卡eth0为Veth Pair形式,其另一端为宿主机的docker0网卡
在这里插入图片描述

16.2.同一主机容器间通信

由docker0充当网桥

在这里插入图片描述
两个容器间是如何通信的呢?

  • (1) 容器0 ping 容器1
  • (2) 按照容器0的路由表,会将该包转发至默认网关 172.17.0.1
    在这里插入图片描述
  • (3) 由于该虚拟网卡为Veth Pair形式,因此该包会被转发至在宿主机生成的对应的网卡上
    在这里插入图片描述
  • (4) 由于该虚拟网卡插入到了docker0网桥上,因此该数据包会被转发至docker0网桥上
  • (5)docker0扮演二层交换机角色,将ARP广播转发到其他被插在docker0上的虚拟网卡上
  • (6)容器1响应该请求,将自己的MAC地址回复给容器0;

16.2. 不同主机容器间通信

由overlay虚拟网络层充当网桥

在这里插入图片描述

16.2.1.Flannel UDP模式
nodecontaineripdocker0
node 1container 1192.168.31.175172.17.0.1/16
node 2container 2192.168.31.174172.17.0.1/16
  • (1) container1 ping container2
    在这里插入图片描述

    - TIP: 不同Node上docker0的地址需为flannel分配的子网
FLANNEL_SUBNET=10.244.0.1/24
dockerd --bip=$FLANNEL_SUBNET

flannel UDP模式为一个三层Overlay网络;
Flannel UDP模式效率低下,尽管采用该模式仅仅多了UDP封装这一步,但完成这一步进行了三次用户态与内核态之间的数据拷贝;
在这里插入图片描述
系统编程:减少用户态和内核态之间切换的次数,并将核心处理逻辑放在内核态中进行;

16.2.2.Virtual Extensible LAN

在现有的三层网络之上,覆盖一层由内核VXLAN模块负责的二层网络,使得连接在这个VXLAN二层网络上的主机之间,可以像在同一个局域网中自由通信。
VXLAN会在宿主机上设置一个特殊的网络设备作为隧道的两端,VTECP (VXLAN Tunnel End Point)
在这里插入图片描述

16.2.3.CNI网络插件

网络插件的目的是将不同宿主机上的特殊设备连通,实现宿主机之间的通信。

# 查看cni插件所需的基础可执行文件
ls -al /opt/cni/bin

在这里插入图片描述

16.2.3.1.Main插件

用于创建具体网络设备的二进制文件,如bridge,ipvlan,loopback,macvlan,ptp,vlan;

16.2.3.2.IPAM(IP Address Management)插件

负责分配IP地址的二进制文件;如dhcp

16.2.3.3.内置CNI插件
插件解释
flannel专门为flannel项目提供的CNI插件
tuning通过sysctl调整那个网络设备参数的二进制文件
portmap通过iptables配置端口映射的二进制文件
bandwidth使用token bucket filter来进行限流的二进制文件
# flanneld启动后会为每台宿主机生成CNI配置文件
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
      }
    }
  ]
}

处理网络相关的逻辑并不在kubelet主干代码里执行,而是会在具体的CRI(Container Runtime Interface)中实现;
对于Docker项目的的CRI为dockershim

16.3. 若出现容器连不通外网

  • 检查能否ping通docker0网桥
  • 检查和docker0和Veth Pair设备相关的iptables路由规则

16.3. Kubernetes三层网络模型

16.3.1.Flannel host-gw 模式

host-gw 是将每个flannel子网的下一跳地址设置为该子网对应的宿主机的IP地址;这些子网和主机的信息都保存在etcd种;flannel会watch这些数据并实时更新路由表;
在这里插入图片描述

16.3.2.Calico

Calico实现原理和flannel host-gw 几乎一样,不同之处在于Calico使用BGP在集群中分发维护路由信息;

BGP(Border Gateway Protocol): 边界网关协议,为linux内核原生支持,专门用于大规模数据中心维护不同自治系统之间的路由信息的,无中心的路由协议;

边界网关: 将若干个自治系统连接在一起的路由器;

Calico共分为3个部分,CNI插件,Felix,BIRD;

  • CNI插件:在宿主机上为每个容器的Veth Pair设备配置路由规则;
  • Felix:DaemonSet,通过FIB维护节点路由规则;
  • BIRD:BGP客户端,负责在集群中分发路由规则信息;

calico BGP 协议会自动维护同一集群内所有节点的路由规则,自动为所有节点添加路由到其他节点的下一跳地址规则 ,见下图
目标子网网段/24 via 目标节点ip地址 eth0
在这里插入图片描述

按照上述理论,Calico将集群里所有的节点都当做边界路由器来处理,各个边界路由器之间通过BGP协议交换路由规则。
在默认配置下,Calico维护的BGP模式为 Node-to-Node Mesh,每台宿主机上的BGP Client都需跟其他所有节点的BGP Client相互交换信息,交换链路共有 (n(n-1))/2; n为集群的节点数量;

若节点数量大于100,通常使用Route Reflector模式,在该模式下,Calico会专门会指定一个或几个专门的节点来负责为所有节点建立BGP连接从而学习到路由规则;

16.3.2.1.IPIP模式

flannel host-gw 和 Calico默认情况下要求集群宿主机之间是2层连通的,即如上图所示,这些节点处在同一个局域网网段内;假设有这样一种情况;
在这里插入图片描述

# pod-0(10.233.1.2)需要传输数据到pod-0(10.233.2.2)
# 目前路由表有的规则为
10.233.2.0/16 via 192.168.2.2 eth0
10.233.1.2 dev cali0 scope link
10.233.1.3 dev cali0 scope link

# 按照路由规则 10.233.2.0/16 via 192.168.2.2 eth0
# pod-0(10.233.1.2) -> 192.168.2.2,下一跳地址应该是 192.168.2.2, 但由于宿主机从eth0(192.168.1.1)无法找到该路由目标,因此会舍弃该包

IPIP模式:Felix会将上述
10.233.2.0/16 via 192.168.2.2 eth0
规则修改为
10.233.2.0/16 via 192.168.2.2 tunl0
tunl0是一个IP隧道设备,通过该设备,会将该包直接封装在一个宿主机网络的IP包中,通过网络传输给目标地址;
在这里插入图片描述

16.3.容器网络隔离

kubernetes里的Pod默认都是允许所有"Accept All",即对Pod的网络通信没有任何限制;Kubernetes使用NetworkPolicy来实现不同Pod之间的网络隔离;

qosClass解释
GuaranteedPod里每一个Contaniner同时都被设置了requests和limits,且requests和limits值相等
BurstablePod至少一个Container设置了requests
BestEffortPod既没设置requests,也没设置limits

cgroup cpuset: 为Pod绑定到某个固定的CPU核上,减少 CPU上下文切换的次数;
实现方式:将requests.cpu和limits.cpu 设置为相同的值;

kubernetes 调度器

调度器用户为新创建的Pod寻找一个最合适的节点;

Informer Path: 监听Etcd种Pod,Node,Service等API对象的变化,并将这些资源加入Priority Queue种;
Scheduling Path: 持续从Priority Queue中取出资源,执行Predicates算法过滤出一组Node节点,然后调用Priorities算法为为这些Node进行打分,取出分值最高的Node作为当前资源将要被调度的结果;

Predicates

过滤出所有符合Pod的节点;

(1) GeneralPredicates - PodFitsResources: 检查宿主机CPU和内存资源是否足够
(2) GeneralPredicates - PodFitsHostPorts: 检查Pod的spec.NodeName 和 spec.nodePort;
(3) GeneralPredicates - PodMatchNodeSelector: 检查Pod的nodeSelector, nodeAffinity指定的节点是否匹配;

(4) NoDiskConflict: 检查多个Pod声明挂载的持久化Volume是否有冲突;
(5) MaxPDVolumeCountPredicate: 检查节点声明的Volume数目是否超过一定数目;
(6) VolumeZonePredicate: 检查Volume的Zone标签是否和节点的Zone标签匹配;
(7) VolumeBindingPredicate: 检查Pod对应的PV的nodeAffinity字段是否和某个节点的标签匹配;

(8) NodeMemoryPressurePredicate: 检查当前节点的内存是否充分;

(9) PodAffinityPredicate: 检查当前Pod和Node上的Pod之间的亲密和反亲密关系是否符合;

Priorities

为Predicates中过滤出的所有节点进行打分;

# LeastRequestedPriority
# 选出剩余memory和cpu最多的宿主机
score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2

# BalancedResourceAllocation
#选出某个资源使用量最均匀的节点

score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10

https://time.geekbang.org/column/article/70519

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值