1、架构图

Kubernetes 系统架构遵循客户端/服务端(C/S)架构,系统架构分为 Master 和 Worker 两部分,Master 作为服务端,Worker 作为客户端。Kubernetes 系统具有多个 Master 服务端,可以实现高可用。

kubernetes-structure.png

1.1 Master

Master 服务端也被称为主控节点,它在集群中主要负责如下任务:

  1. 集群的中枢,负责管理所有节点(Node);

  2. 负责计算并调度 Pod 在哪些节点上运行;

  3. 负责控制管理集群运行过程中的所有状态。

其中,主要包含三个组件:

  • kube-apiserver:负责将 Kubernetes 资源组/资源版本/资源 以 RESTful 风格的形式对外暴露,提供了集群各组件的通信和交互功能,是唯一与 Etcd 数据直接交互组件。

  • kube-controller-manager:负责管理 Kubernetes 集群中的节点、副本、服务、端点、命名空间、服务账户、资源定额等,是集群中所有资源对象的自动化控制中心。

    负责确保 Kubernetes 系统的实际状态收敛到所需状态,默认提供了一些控制器,例如 DeploymentControllers 控制器、StatefulSet 控制器、Namespace 控制器及 PersistentVolume 控制器等,每个控制器通过 kube-apiserver 组件提供的接口实时监控整个集群每个资源对象的当前状态。

    作为控制节点,基于 Etcd 集群上的分布式锁实现领导者选举机制,保证高可用。通过 kube-apiserver 提供的资源锁进行选举竞争,抢先获取锁的实例被称为 Leader 节点,并运行主逻辑;而未获取锁的实例被称为 Candidate 节点,运行时处于阻塞状态。

  • kube-scheduler:负责在 Kubernetes 集群中为一个 Pod 资源对象找到合适的节点并在该节点上运行,组件监控整个集群的 Pod 资源对象和 Node 资源对象,当监控到新的 Pod 资源对象时,会通过调度算法为其选择最优节点。

    调度算法分为两种,预选调度算法和优选调度算法。

    1. 预选策略

      输入是所有节点,输出是满足预选条件的节点。调度器会同时开启多个协程并发进行 Predicates 过滤,每个协程按照固定的顺序进行过滤,最后返回过滤后可以运行 Pod 的 Node 列表。

      GeneralPredicates 规则 最基础的调度策略,这个接口也会被其它组件直接调用,比如 kubelet 在启动 Pod 前会再执行一遍 GeneralPredicates 用于二次确认。

      策略

      作用

      PodFitsResources

      计算 Node 的 CPU、内存、扩展资源(如 GPU)是否够用

      PodFitsHost

      检查 Node 的名字是否跟 Pod 的 spec.nodeName 匹配

      PodFitsHostPorts

      检查 Pod 申请的 Node 端口是否冲突

      PodMatchNodeSelector

      检查 Node 是否能匹配 Pod 的 nodeSelectornodeAffinity

      Volume 规则 负责与容器持久化 Volume 相关的调度策略。

      策略

      作用

      NoDiskConflict

      检查 Node 上所有的 Pods 是否与待调度 Pod 的 Volume 有冲突

      VolumeZonePredicate

      检查 Pod Volume 的 zone 标签是否与节点的 zone 标签匹配,如果 Node 没有 zone 标签就认定为匹配

      MaxPDVolumeCountPredicate

      检查 Node 上某种类型的 Volume 是否已经超过指定数目

      CSIMaxVolumeCountPredicate*

      检查 CSI Volume 相关的限制

      VolumeBindingPredicate*

      检查 Pod 对应的 Local PV 的 nodeAffinity 字段,是否跟某个 Node 标签相匹配。如果该 Pod PVC 还没有绑定 PV,调度器要检查所有待绑定的 PV,且该 PV 的 nodeAffinity 是否与 Node 标签匹配

      Node 规则 负责检查待调度 Pod 是否满足 Node 本身的一些条件。

      策略

      作用

      NodeConditionPredicate

      检查 Node 是否还未准备好或处于 NodeOutOfDisk、NodeNetworkUnavailable 状态,或者 Node 的spec.Unschedulable设置为 true,如果出现以上的情况,该 Node 都无法被调度

      PodTolerateNodeTaints

      检查 Node 的 taint(污点)机制,只有当 Pod 的 Toleration 与 Node 的 Taint 匹配时,Pod 才能调度到该 Node 上

      NodeMemoryPressurePredicate

      检查 Node 的内存是否不够使用

      NodeDiskPressurePredicate

      检查 Node 的磁盘是否不够使用

      NodePIDPressurePredicate

      检查 Node 的 PID 是否不够使用

      Pod 规则 负责检查待调度 Pod 与 Node 上已有 Pod 之间的亲和性关系。

      策略

      作用

      PodAffinityPredicate

      检查待调度 Pod 与 Node 上已有 Pod 之间的亲和性与反亲和性关系

    2. 优选策略

      通过前面预选策略过滤出来的 Node 列表,会再一次使用优选策略为这些 Node 打分,最终得分最高的 Node 会作为该 Pod 的调度对象。

      总分 = (打分函数1 权重1) +(打分函数2 权重2) + ... + (打分函数3 * 权重3)

      打分函数的打分范围为 [0, 10] 分,0 表示非常不合适,10 表示非常合适。每个打分函数都可以配置对应的权重,默认权重值为 1,如果某个打分函数特别重要就可以增加该权重值。

      策略

      作用

      LeastRequestedPriority

      选出空闲资源(CPU & Memory)最多的 Node

      BalancedResourceAllocation

      选出各项资源分配最均衡的 Node,避免出现某些 Node CPU 被大量分配,而 Memory 大量剩余的情况

      SelectorSpreadPriority

      对属于同一个 Service 或是 RC 的多个 Pod 副本,尽量调度到多个不同的 Node 上

      InterPodAffinityPriority

      优先将 Pod 调度到相同的拓扑上(如同一个节点、Rack、Zone 等)

      NodeAffinityPriority

      优先调度到匹配 NodeAffinity 的 Node 上

      TaintTolerationPriority

      优先调度到匹配 TaintToleration 的 Node 上

      ImageLocalityPriority

      优先选择已经存在 Pod 所需 Image 的 Node(已注册但默认未使用)

      MostRequestedPriority

      优先选择已经使用过的 Node,适用于 cluster-autoscaler(已注册但默认未使用)

    除调度策略外,Kubernetes还支持优先级调度、抢占机制亲和性调度等功能。

1.2 Worker

客户端也被称为工作节点,它在集群中主要负责如下任务。

  1. 负责管理所有容器(Container)。

  2. 负责监控、上报所有 Pod 的运行状态。

其中,也主要包含三个组件:

  • kubelet 组件:负责接收、处理、上报 kube-apiserver 组件下发的任务,启动时会向 kube-apiserver 注册节点自身信息,管理例如 Pod 资源对象的创建、修改、监控、删除、驱逐及 Pod 生命周期管理等。

    kubelet 组件实现了3种开放接口:容器运行时接口容器网络接口容器存储接口

    1. Container Runtime Interface:简称 CRI,提供容器运行时通用插件接口服务,定义了容器和镜像服务的接口,将 kubelet 组件与容器运行时进行解耦,将原来完全面向 Pod 级别的内部接口拆分成面向 Sandbox 和 Container 的 gRPC 接口,并将镜像管理和容器管理分离给不同的服务。

    2. Container Network Interface:简称 CNI,提供网络通用插件接口服务,定义了 Kubernetes 网络插件的基础,容器创建时通过 CNI 插件配置网络。

    3. Container Storage Interface:简称 CSI,提供存储通用插件接口服务,定义了容器存储卷标准规范,容器创建时通过 CSI 插件配置存储卷。

  • kube-proxy 组件:作为节点上的网络代理,运行在每个 Kubernetes 节点上。它监控 kube-apiserver 的服务和端点资源变化,并通过 iptables/ipvs 等配置负载均衡器,为一组 Pod 提供统一的 TCP/UDP 流量转发和负载均衡功能。

    该组件是参与管理 Pod-to-Service 和 External-to-Service 网络的最重要的节点组件之一,作用相当于代理模型,对于某个 IP:Port 的请求,负责将其转发给专用网络上的相应服务或应用程序。但是,kube-proxy 组件与其他负载均衡服务的区别在于,kube-proxy 代理只向 Kubernetes 服务及其后端 Pod 发出请求。

  • container 组件:负责容器的基础管理服务,接收kubelet组件的指令。

2、Kubernetes Project Layout 设计

源码目录

说明

cmd/

存放可执行文件的入口代码,每个可执行文件都会对应一个 main 函数

pkg/

存放核心库代码,可被项目内部或外部直接引用

vendor/

存放项目依赖的库代码,一般为第三方库代码(go mod vendor

api/

存放 OpenAPI/Swagger 的 spec 文件,包括 JSON、Protocol 的定义等

build/

存放与构建相关的脚本

test/

存放测试工具及测试数据

docs/

存放设计或用户使用文档

hack/

存放与构建、测试等相关的脚本

third_party/

存放第三方工具、代码或其他组件

plugin/

存放 Kubernetes 插件代码目录,例如认证、授权等相关插件

staging/

存放部分核心库的暂存目录

translations/

存放 i18n(国际化) 语言包的相关文件,可以在不修改内部代码的情况下支持不同语言及地区

main 结构中定义了进程运行的周期,包括从进程启动、运行到退出的过程。以 kube-apiserver 组件为例,初始化过程如下所示:

kube-apiserver-init.png

  1. rand.Seed:组件中的全局随机数生成对象;

  2. app.NewCommand:实例化命令行参数。通过 flags 对命令行参数进行解析并存储至 Options 对象中;

  3. logs.InitLogs:实例化日志对象,用于日志管理;

  4. command.Execute:组件进程运行的逻辑。运行前通过 Complete 函数填充默认参数,通过 Validate 函数验证所有参数,最后通过 Run 函数持久运行。只有当进程收到退出信号时,进程才会退出。