kube -scheduler

负责调度Pod到集群被的节点上,它监听kube-apiserver,查询还未分配的Node的pod,根据调度策略为pod分配直接点(本质是更新Pod的NodeName)

如果pod创建时指定了NodeName,则只会调回到指定node上

公平性
同一优先级的pod,先到的pod先调度;不同优先级,优先级高的先调度
资源高效利用
多维资源调度,寻求各种资源的平衡
空闲的CPU很少,调度后占满CPU,则剩余内存会造成浪费
Qos
允许超售,满足最基本需求,提高资源利用率
亲和性和反亲和性
紧密相关的业务调度到同一个节点后者区域
数据本地化(data locality)
比如节点有镜像,优先将pod调度到这个节点,提高磁盘使用率
内部负载干扰
deadlines

调度器的阶段(filter和score)

  • predicate:过滤掉不符合条件的节点
  • priority:优先级排序,选择优先级最高的节点

predicate策略
PodFitsHostPorts 和 PodFitsPort
如果使用主机端口,检查是否有端口冲突
PodFitsResource
检查node的资源是否充足,包括允许的pod数量、CPU、内存、GPU个数
HostName
检查pod.Spec.NodeName是否与候选节点一致
MatchNodeSelector
检查候选节点的pod.Spec.NodeSelector是否匹配
NoVolumeZoneConflict
检查volume zone是否冲突
NoVolumeNodeConflict
检查节点是否满足pod所引用的volume的条件
MatchInterrPodAffinity
检查匹配的pod的亲和性要求
NoDiskConflict
检查是否存在volume冲突,仅限于GCE PD,AWS EBS,Ceph RBD以及iSCSI
PodToleratesNodeTaint
检查pod是否容忍Node Taint
CheckNodeMemoryPressure
检查pod是否可以调度到MemoryPressure的节点上
CheckNodeDiskPressure
检查pod是否可以调度到DiskPressure节点上

predicate 插件工作原理
image.png

Priority策略
SelectorSpreadPriority
优先较少节点上数据同一个service或Replication Controller的pod数量
InterPodAffinityPriority
优先将pod调度到相同的拓扑上(比如同一节点,Rack,Zone)
LeastRequestedPriority
优先调度到请求资源少的节点上
BalancedResourceAllocation
优先平衡各个节点的资源使用
NodePreferAvoidPodsPriority
alpha.kunernetes.io/preferAvaoidPods字段判断,权重为10000,别比比面其他优先级策略影响

资源需求
CPU
requests
会判断当前节点上正在运行的pod的CPU requests总和,在加上当前调度的pod的CPU request,计算其是否超过节点的CPU的可分配资源
limit
配置Cgroup以限制资源上限
内存
requests
判断剩余内存是否满足pod的内存请求量,以确定是否可以将pod调度到该节点上
limit
配置Cgroup以限制资源上限

临时存储补充

init caontainer
用来加载资源,
当pod有多个init container时,request资源只计算init最大的不部分,并不是计算所有init之和。
多个init顺序执行,执行完即退出,所以申请最多的资源init容器中所需资源即可满足init容器需求
kube-scheduler 在计算资源占用时,init容量的资源依然会被纳入计算。因为init在特定情况下会被再次执行

LimitRange
为namespace定义默认的资源,pod创建时,如果未声明资源,则使用默认值
多个LImitRange规则会同时生效

把pod调度到指定node上
kubectl label node kubernetes-master disktype=ssd
kubectl label node kubernetes-master disktype=ssd1 —overwrite

NodeAffinity
PodAffinity
强亲和和弱亲和

Invalid value: “Equal”: not a valid selector operator

taints和tolerations

场景
用于区分不同类型节点,跑不同的业务,实现隔离
用于保证pod不被调度到不合适的Node上,Taint应用于Node上,Toleration用于pod上
Tain类型
NoSchedule
新的pod如果没有toleration这个taint,则不会被调度到节点。
不影响正在运行的pod
PreferNoScheduler
新的pod如果没有toleration这个taint,尽量不会被调度到节点。
不影响正在运行的pod
NoExecute
新的pod如果没有toleration这个taint,则不会被调度到节点。
正在运行的pod如果没有toleration,则会被驱逐

tolerationSeconds 定义多久后做驱逐

多租户kubernetes集群-计算资源隔离
kubernetes集群一般是通用集群,可以被所有用户共享,用户无需关心计算节点细节。
但往往自带计算资源的客户要求
带着计算资源加入集群
要求计算资源隔离
实现方案
将要隔离的节点上大Taints
在用户创建pod时,定义tolerations来指定要调度到node taint上,并且还需要通过亲和性或者标签选择器来调度到这些节点上

改方案的漏洞

  • 用户可以通过get nodes拿到taint信息
    • 禁止用户get node detail
    • 禁止用户get 其他人pod detail

优先级调度
v1.8开始,支持定义pod的优先级,从而保证高优先级的pod优先调度
开启方法
apiserver 配置
—feature-gates=PodPriority=true
—runtime-config=scheduling.k8s.io/v1alpha1=true
kube-scheduler配置
—feature-gates=PodPriority=true

PriorityClass
非namespace资源
高优先级可以插队优先调度
高优先级会抢占驱逐低优先级的pod

  1. apiVersion: v1
  2. kind: PriorityClass
  3. metadata:
  4. name: high-priority
  5. value: 10000 # 越大优先级越高
  6. globalDefault: true # 没有打PriorityClass的pod的默认优先级
  7. description: "This priority is used for xxx"

多调度器
如果默认的调度器并不能满足需求,还可以部署自定义的调度器,整个集群中可以运行多个调度器实例,通过pod.Spec.schedulerName选择一个调度器(默认使用内置调度器)

比如离线业务,1秒几百次调度需求,原生的无法满足,批处理调度器
腾讯 TKE
华为 Volcano

kube-scheduler 代码走读:https://cncamp.notion.site/kube-scheduler-0d45b37a5c9a46008aaf9f9e2088b3ce

kubelet

监听了3个端口
10248/healthz
10250 API
10255 只读API

主要职责

  • 通过监听,接收并执行apiserver发来的指令
  • 管理pod以及pod中的容器
  • 每个kubelet进程会在apiserver上注册自身节点信息,并定期汇报pod的监控状况(PLEG),通过cAdviser监控节点和容器的资源使用情况

ProbeManaget 探活
OOMWatch 进程OOM上报
GPUManger GPU卡管理
cAdvisor 独立开源软件,作为kubelet的一部分存在
DiskSpaceManger 管理磁盘空间,容量,申请磁盘
StatusManger 管理节点的状态
EvictionManger 监控node的内存水位,如果过高,则会驱逐优先级低的且占用较多内存的pod
VolumeManager 挂载存储卷
Image GC 不常用镜像清理
Container GC exit container清理
Image Manager 镜像管理
CertificateManager 管理证书

节点管理
—>
POD管理
文件:启动参数—config 指定的配置目录下的文件(默认/etc/kubernetes/manifests),该文件每20s检测一次(可配置)
HTTP endpoint(URL):启动参数 —manifest-url 设置,每20s检查一次这个端点
API Server:通过apiserver监听etcd目录,同步pod清单

syncloop

CSI

CNI

网络模型设计原则

  • 所有pod/节点不能通过nat就能互相访问
  • 容器内看见的ip和外部组件看见的容器ip是一致的

CNI插件涉及考量

  • 容器运行时必须在调用插件之前为容器创建新的网络空间
  • 容器运行时必须决定这个容器属于那个网络,针对每个网络,哪些插件必须执行
  • 容器运行时必须加载配置文件,并确定设置网络时哪些插件必须被执行
  • 网络配置采用json格式,可以容器存储在文件中
  • 容器运行时,必须按顺序执行配置文件里的响应插件
  • 容器生命周期结束后,容器运行时必须按照与执行顺序相反的顺序执行插件,一遍容器与网络断开连接
  • 容器运行时被同一容器调用时不能并行操作,但被不同容器调用时可以并行执行
  • 容器运行时针对同一个容器必须按照顺序执行ADD和DEL操作,ADD后面总跟着相应的DEL。DEL可能跟着额外的DEL,插件应该允许执行多个DEL
  • 容器必须由containerid来唯一标识,需要存储状态的插件需要使用网络名称,容器ID和网络接口组成的主key用于索引
  • 容器运行时针对同一网络,同一容器,同一个网络接口不能连续调用两次ADD命令

ip是以pod为单位进行分配的,每个pod拥有独立的ip
一个pod内所有容器共享一个网络栈,即宿主机的一个网络命名空间,包括ip,网络设备,配置都是共享的,即pod内所有容器都能通过localhost:port 来连接对方。

kubernetes提供了一个轻量级的通用容器网络接口CNI,专门用于设置和删除容器的网络连通性。

CNI常见插件
IPAM:IP地址分配
主插件:网卡设置

  • bridge:创建网桥,把主机端口和容器端口插入网桥
  • ipvlan:为容器添加ipvlan网口
  • loopback:设置loopback网口

Meta:附加功能

  • portmap 设置主机端口和容器端口的映射
  • bandwidth 利用linux traffic control限流
  • firewall 通过iptables或firewall为容器设置防火墙

CNI插件运行机制
当前节点有效的网络插件

  1. 2022-06-02 21:08:54.796 [ERROR][544824] plugin.go 160: Final result of CNI ADD was an error. error=error getting ClusterInformation: Get "https://10.96.0.1:443/apis/crd.projectcalico.org/v1/clusterinformations/default": net/http: TLS handshake timeout
  2. 2022-06-02 21:08:57.817 [ERROR][544869] plugin.go 577: Final result of CNI DEL was an error. error=error getting ClusterInformation: Get "https://10.96.0.1:443/apis/crd.projectcalico.org/v1/clusterinformations/default": net/http: TLS handshake timeout

关于容器网络配置,容器运行时一般需要配置以下两个参数;
特殊情况,kubelet内置的docker作为容器运行时,是由kubelet查找CNI插件,运行插件来为容器设置网络,这两个参数配置在kubelet处

  • 网络插件可执行文件目录 /opt/cni/bin,可以通过—cni-bin-dir修改
  • 网络插件配置文件/etc/cni/net.d,可以通过—cni-conf-dir修改

cniVersion
type 后的都是可执行文件
主插件式calico
ip地址插件式 ipam
附加插件

  • bandwidth
  • portmap
    1. {
    2. "name": "k8s-pod-network",
    3. "cniVersion": "0.3.1",
    4. "plugins": [
    5. {
    6. "type": "calico",
    7. "datastore_type": "kubernetes",
    8. "mtu": 0,
    9. "nodename_file_optional": false,
    10. "log_level": "Info",
    11. "log_file_path": "/var/log/calico/cni/cni.log",
    12. "ipam": { "type": "calico-ipam", "assign_ipv4" : "true", "assign_ipv6" : "false"},
    13. "container_settings": {
    14. "allow_ip_forwarding": false
    15. },
    16. "policy": {
    17. "type": "k8s"
    18. },
    19. "kubernetes": {
    20. "k8s_api_root":"https://10.96.0.1:443",
    21. "kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
    22. }
    23. },
    24. {
    25. "type": "bandwidth",
    26. "capabilities": {"bandwidth": true}
    27. },
    28. {"type": "portmap", "snat": true, "capabilities": {"portMappings": true}}
    29. ]
    30. }

flannel
由CoreOS开发,是CNI插件早期入门产品,简单易用

flannel 使用k8s现有的etcd存储状态信息,只需要在每个节点上运行flanneld守护进程
每个节点被分配一个子网,为该节点上的pod分配ip
同主机内的pod通过网桥进行通信,不同主机的pod通过flanneld将其流量封装在UDP包中,以路由到释放的目的地。
封装方式默认和推荐方法是使用vxlan,因为它具有良好的性能,并且比其他选项少些人为干预。虽然vxlan之类的技术封装的解决方案效果很好,但缺点解释该过程使流量跟踪变得困难,封包解包的效率较低。适合小型网络

image.png
vxlan是什么
tcp上加了udp包头(增加了宿主机地址和目标主机地址),可以在不同节点间传输。overlay技术
为什么用UDP,性能好吗?

calico
calico以其灵活性,性能和网络策略而闻名。不仅涉及在集合pod之间提供网络连接,还涉及网络安全和策略管理

对于同网段通信,基于3层,calico使用BGP路由协议在主机间路由数据包,意味不需要封包解包。
对于跨网段通信,基于IPinIP使用虚拟网卡设备tunl0,用一个ip数据包封装另一个ip数据包,外层ip数据包头的源地址为隧道入设备的IP地址,目标地址为隧道出口设备的IP地址。
网络策略是calico最受欢迎的功能之一,使用ACLs协议和kube-proxy来创建iptables过滤规则,从而实现隔离容器网络的目的。

felix 配置网络的插件,配置防火墙规则
BIRD Internet Routing Daemon,互联网路由交换协议,开源软件(路由交换),主机模拟为路由器
confd 配置推送
image.png

  1. root@kubernetes-master:/opt/cni/bin# kubectl get ippools.crd.projectcalico.org -o yaml
  2. apiVersion: v1
  3. items:
  4. - apiVersion: crd.projectcalico.org/v1
  5. kind: IPPool
  6. metadata:
  7. annotations:
  8. projectcalico.org/metadata: '{"uid":"c723cbdb-2d06-41a0-aaf4-97cae46ad685","creationTimestamp":"2022-05-13T02:32:37Z"}'
  9. creationTimestamp: "2022-05-13T02:32:37Z"
  10. generation: 1
  11. name: default-ipv4-ippool
  12. resourceVersion: "1464"
  13. uid: 6f01119d-2abc-45b7-8931-343aee8d7443
  14. spec:
  15. allowedUses:
  16. - Workload
  17. - Tunnel
  18. blockSize: 26 # 子网
  19. cidr: 192.168.0.0/16 # 集群IP段
  20. ipipMode: Never
  21. natOutgoing: true
  22. nodeSelector: all()
  23. vxlanMode: CrossSubnet
  24. kind: List
  25. metadata:
  26. resourceVersion: ""
  27. selfLink: ""
  1. root@kubernetes-master:/opt/cni/bin# kubectl get ipamblocks.crd.projectcalico.org -o yaml
  2. apiVersion: v1
  3. items:
  4. - apiVersion: crd.projectcalico.org/v1
  5. kind: IPAMBlock
  6. metadata:
  7. annotations:
  8. projectcalico.org/metadata: '{"creationTimestamp":null}'
  9. creationTimestamp: "2022-05-13T02:32:38Z"
  10. generation: 314
  11. name: 192-168-237-0-26
  12. resourceVersion: "3787214"
  13. uid: 5f07f34d-35d0-46e8-9a01-be6b3403a696
  14. spec:
  15. affinity: host:kubernetes-master # 绑定到主机
  16. attributes:
  17. - handle_id: k8s-pod-network.41f30c4f18f1619414708767656f7646ea5fc1313b9579d208db9d346e055731 # ip信息
  18. secondary:
  19. namespace: calico-apiserver # 哪个namespace
  20. node: kubernetes-master # 哪个节点
  21. pod: calico-apiserver-7fb988dc78-bwsmz # 哪个pod
  22. timestamp: 2022-06-02 02:52:54.142992997 +0000 UTC
  23. cidr: 192.168.237.0/26 # 主机子网