Kubernetes架构原则和对象设计

news2024/12/26 20:04:41

云原生学习路线导航页(持续更新中)

  • 快捷链接
    • Kubernetes常见问题解答

本文从 Google Borg系统的架构设计开始,深入讲解Kubernetes架构及组件的基本原理

1.什么是云计算

1.1.传统行业应用

  • 假设有10台服务器,两个应用。
  • 小规模管理下
    • 每个应用分别部署在5台服务器上,就ok了
    • 但是出现故障时,需要人工下掉节点,重新配置应用等,涉及大量人工手动操作
  • 微服务架构盛行之后
    • 一个中大型公司,可能会有数千上万个服务器,或数千上万的应用实例
    • 此时人工进行应用的部署将变得不可想象。一定会出现大量的纰漏
  • 为了满足需求,出现了云计算的概念

1.2.云计算到底是什么

  • 云计算是对 网络资源、存储资源的 一种抽象。
  • 假设有5000台机器,那么可以做以下操作:
    • 1.把这5000台机器从网络上打通,形成一个集群;
    • 2.维护一个控制平面,把所有机器的计算资源、存储资源等都抽象出来,比如有 1w个CPU、1wGB内存。
    • 3.控制平面还维护了所有机器的状态,哪些机器能参与计算,哪些不能,哪些是up,哪些是down等
    • 这样,就形成一个庞大的资源池
  • 对于业务来说,不用管自己的业务跑到哪台机器,业务只需要告诉 控制平面,业务需要多少CPU、多少Memory,控制平面就会自动选择合适的节点把应用跑起来。
  • 这个控制平面,就是云计算平台。

1.3.云计算平台的分类

在这里插入图片描述

  • 云计算平台 主要分为两类:
    • 以OpenStack为典型的虚拟化平台
    • 以谷歌Borg系统为典型的基于进程的作业调度平台

1.3.1.以OpenStack为典型的虚拟化平台

  • 虚拟化平台其实发展很平滑,最早大家都在做大型机、小型机,计算机的计算能力遵循摩尔定律,18个月会将芯片的性能提高一倍。此时应用架构都是单体的
  • 后来发现摩尔定律逐渐失效了,发展到一定阶段就达到瓶颈了,因为计算能力到了一定上限就很难突破了。
  • 另一方面,应用架构开始从单体变向微服务架构,就出现了一个问题:
    • 一台物理机,资源可能很多,但是软件的需求很少。
    • 因此一台机器就会跑很多个应用,来提高服务器的使用效率
    • 可是这么做,应用的隔离性就变得很差
  • 为解决这个问题,就出现了虚拟化技术,将一台物理机切割为不同的虚拟机,在不同虚拟机中去部署应用
  • OpenStack是虚拟化云平台的代表,它是一个云平台管理的项目,它不是一个软件,而是由几个主要的组件组合起来,为公有云、私有云和混合云的建设与管理提供软件。
  • 目前依旧有很多公司在用OpenStack

1.3.2.以谷歌Borg系统为典型的基于进程的作业调度平台

  • 谷歌Borg系统完全没有走虚拟化的路,而是基于进程去做调度。
  • Borg也是利用容器相关技术实现,比如利用cgroups实现资源限制,早期Borg使用了Chroot技术做隔离,当然现在也可以利用namespace技术了

2.什么是Borg

在这里插入图片描述

2.1.Borg简介

  • Borg是谷歌最主要的集群管理系统,拥有数十万台机器,运行着数以万计的作业。
  • Borg通过将准入控制、高效的任务打包、过度承诺和机器共享与流程级性能隔离结合起来,实现了高利用率。
  • 它支持具有运行时特性的高可用性应用程序,这些运行时特性可以最小化故障恢复时间,并且调度策略可以降低相关故障的概率。
  • Borg通过提供声明性作业规范语言、名称服务集成、实时作业监控以及分析和模拟系统行为的工具,简化了用户的使用。
  • Kubernetes 直接继承自 Borg。 在 Google 的很多从事 Kubernetes 的开发人员以前都是 Borg 项目的开发人员。 他们在 Kubernetes 中结合了 Borg 的最佳创意,并试图解决用户多年来在 Borg 中发现的一些痛点。

2.2.Borg支持两类应用

  • Borg支持两类应用:
    • Production应用:LongRunningService,即长时间在线的应用,比如Gmail、GoogleDocs、WebSearch
    • NonProduction应用:离线作业

2.2.1.Production应用

  • Production应用,指长时间在线的应用,即我们日常接触的在线服务,如Gmail、GoogleDocs、WebSearch
  • 对在线服务来说,高可用性是命根子,必须保证任何时候都是可访问、可使用的
  • 因此在任何时候,都要满足Production应用的资源需求,保障可用性

2.2.2.NonProduction应用

  • NonProduction应用:即离线作业,不需要长时间在线
  • 比如:
    • 电信业务,白天会有很多的支付账单,电信需要把订单数据和收费数据做对账。所以每天半夜就会在Linux上使用Cron job的方式开启离线作业做统计。
    • 这种离线作业,可以按定时、按资源的需求、资源的利用率等情况来自行决定。有些离线作业,可以在有资源的时候跑一下,没有资源的时候先暂停。
  • NonProduction应用的目标:
    • 把整体的资源利用率提上去
    • 因为既然上了云,从公司经营角度来说,就一定要给公司降本,因此混部才是唯一出路

2.3.Borg系统的特性

在这里插入图片描述

  • 关于Google Borg,有一篇论文,论文中详细解释了Borg的特性。
    • Large-scale cluster management at Google with Borg
  • Borg为什么开源成为Kubernetes
    • Google为什么会发那篇paper,是想把这份技术公开出来,希望自己内部也能去做技术迭代,把Borg系统不能解决的一些问题解决掉
    • 因此Borg也是kubernetes的一个指导原则

2.3.1.Borg的特性

  • 资源利用高
    • 资源的额外开销少:类似容器技术,没有虚拟化,所有计算资源全部
    • 有混部:在线作业一般都会有资源需求的波峰波谷,机器在请求波谷时资源其实是浪费的,所以Borg通过混部实现在波谷时跑一些短时离线作业,进而提高资源利用率。(空的时候跑,跑完再把资源还回来,或者在线业务激增时直接抢占non-prod应用的资源)
  • 服务器共享,在进程级别做隔离
    • Borg早期用的 chroot jail做隔离,现在基本上也是通过namespace
      那还有就是
  • 应用高可用,故障恢复时间短
    • 后面会详细讲 borg和kubernetes 如何保证应用高可性
  • 调度策略灵活
    • 后面会详细讲 Borg和kubernetes有哪些调度策略
  • 应用接入和使用方便
    • 提供了完备的 job 描述语言(声明式API),服务发现,实时状态监控和诊断工具

2.3.2.Borg的优势

  • 对外隐藏了资源管理、调度和故障处理这些细节,也是云平台的一个优势
    • 声明式API特性,使得一切的业务需求都定义一个对象,这个对象发给控制平面,由控制平面去执行。
  • 实现应用的高可靠和高可用
  • 足够弹性,支持应用跑在成千上万的机器上

2.4.Borg基本概念

在这里插入图片描述

  • Workload
    • prod应用:在线任务
    • non-prod应用:离线任务
  • Cell,即集群
    • 在Borg中,一个集群就叫一个Cell
  • Job 和 Task
    • 一个Job是一个基本的调度单位,相当于kubernetes的Pod
    • 一个Task就是Job内部的一个作业,相当于kubernetes的Container
  • Naming
    • Borg系统的 服务注册、服务发现的机制。
    • 任何的微服务平台肯定要负责提供服务之间的调用关系,就需要服务注册、服务发现的机制
    • Borg系统 通过Borg Name Service 为 Borg 系统中的每个应用提供一个域名,那么 Borg 系统的所有应用都可以使用域名进行互相访问了

2.5.Borg系统架构

学习Borg的架构,会发现和kuebrnetes有很多的共通性。
假设有一天我希望做一套自己的云平台,那它的架构基本上也是八九不离十的

在这里插入图片描述
在这里插入图片描述

  • 如上图,即为Borg系统的架构图
    • Cell:就是这个集群,假设这个集群有5000台机器
    • BorgMaster
      • BorgMaster就是集群的管理节点,接收用户的指令,然后去做调度,把作业发到每个计算节点上面去
      • 假设从5000台机器中选5台作为master,则剩下的4995台就是它的计算节点
      • 在管理节点上面,需要安装额外的管理组件
        • persistent store:基于Paxos协议的数据库。Paxos是分布式键值对存储的一种协议,用于确保分布式一致性
        • UI组件:负责接收请求
        • Scheduler 调度器:负责将作业调度到具体的计算node上运行
      • 因此,BorgMaster整个运作流程即为:UI组件接收到请求,存储起来后,通过调度器下发到计算节点去运行。
    • Mini Node
      • 下面的每个蓝色立方体,就是一个Mini Node,它们参与计算。
      • 集群初始化的时候,这些节点上面都是空的,没有任何的作业,但他们每个都安装了一个叫 Borglet 的组件。
      • Borglet 是在每台机器上的一个代理,负责把BorgMaster下发到本节点的进程跑起来,并汇报应用状态
  • 调度策略
    • Worst Fit(最差适应):
      • Worst Fit 即 永远找最空闲 的节点来运行任务。
      • 即在所有可用节点中选择剩余资源最多的节点,以便能够容纳更多的任务。
      • 这种策略可以减少资源碎片化,但可能导致资源利用率不高。
    • Best Fit(最佳适应):
      • Best Fit 策略是选择最佳匹配的节点来运行任务。
      • 即在所有可用节点中选择剩余资源最接近任务需求的节点,以便能够最大程度地利用资源。
      • 这种策略可以提高资源利用率,但可能导致资源碎片化。
      • 简单来说,Best Fit就是把尽量多的应用往一个节点上叠,叠满了再去做下一个。这样的话,整个集群里面就永远是在理想状况下一半忙的一半闲的。公有云中,闲的那些可以通过收缩节点,踢出集群来降低费用,节省成本;私有云中,甚至可以把那些节点关机。
    • Hybrid(混合):
      • Hybrid 策略是一种综合利用 Worst Fit 和 Best Fit 的调度策略。
      • 它根据任务的资源需求和集群中的资源情况,动态选择使用 Worst Fit 或 Best Fit 策略来分配任务。
      • 这种策略可以在资源利用率和资源碎片化之间取得平衡。
  • 调度优化的玩法特别多
    • 比如 找局部最佳节点:
      • 假设一个集群里面有1万个节点,调度时最好的方式就是遍历这1万台机器,找一个最佳的。
      • 但有时候可能要求没有那么高,不要求那么完美。就可以其中选10台或100台,从这些机器中找一个最佳的,也可以提升调度效率
      • 不过这种能力,目前kubernetes不支持,很多公司会自己做,比如阿里自己做了
    • 再比如当有大量的作业要来调度,可以做一些批次调度,来提高效率

注:从这里可以看到,一个系统出现它并不是偶然的,一定是很多以前的经验,把这些思想带到新的系统上来,然后再用新的思维,新的技术手段去实现,这一般是一个系统的变革或者迭代。而为什么kubernetes现在发展前景这么好?包括它API的定义、model的定义等,后面会详细说。

2.6.Borg如何保证高可用?

2.6.1.运行在Borg系统上的应用如何保证高可用?

在这里插入图片描述

  • 保证鸡蛋不在同一个篮子里:多副本冗余部署、跨故障域部署、跨可用区部署、跨城市部署等等
  • 保证幂等性:幂等性就是容忍重复提交的场景。
    • 对于异步系统,我们经常会一个作业发出去,系统响应收到后就结束了,但是客户端有时候会重复提交。
    • 所谓的密等性,就是不管你的这个请求提交多少次,对提供服务的服务器端,处理都是一样的

2.6.2.Borg控制平面如何保证自身高可用?

在这里插入图片描述

2.7.Borg如何提高资源利用率

2.7.1.Borg提高资源利用率

在这里插入图片描述

  • 在kubernetes集群中,默认会给node设置pod上限110个,
    • 可以在kubelet启动命令中增加–max-pods参数,重启kubelet 服务,修改node的pod上限。
      • 可以参考:https://www.cnblogs.com/cheyunhua/p/18067849
    • 查看kubernetes集群node的pod上限
      kubectl describe node vm-226-235-tencentos | grep Capacity -A 10
      

在这里插入图片描述

  • 那么为什么要设置上限呢,不设置行不行,只要有资源,就让pod运行?

    • 跑在node上的应用,是需要定期巡检的,需要知道这些作业的状态,太多的pod会让巡检压力变大
    • 110个的默认值,大概是基于一些经验得出的数据,综合考量了资源利用率、管理成本。
  • 关于资源利用率,谷歌后来又发了一篇paper,叫 Autopilot

    • Autopilot: workload autoscaling at Google
    • Autopilot 是通过动态的调整作业的资源需求来完成更高的资源利用率,后面讲应用落地的时候会再讲,包括HPA和VPA等

2.7.2.Borg提高资源利用率的实现

在这里插入图片描述

  • Borg提高资源利用率的方法
    • 允许用户先设置资源limit,但是在实际运行中,Borg会动态监控应用实际的资源使用量,作出冗余分配,或者回收未用到的资源
  • 为什么在用户设置limit后还要动态监控?
    • 因为一个新开发的应用,它实际上会使用多少资源,研发和运维都是很难确认的
    • 一般会通过线上的访问量,高峰时段的QPS等,拿着QPS去乘以一个Buffer(比如50或60),拿着这个数据去对应用做压测,看它的CPU和memory会占多少
    • 然后以这个为数值作为参考去设置的资源limit
  • Borg在资源申请时的动态计算
    • 应用对资源申请的时候,Borg本身也会做一些动态计算
    • 比如你可以设的很高,但是接下来Borg会去监控你的资源利用率。在启动的300秒以后,Borg会一直做评估,如果你的真实使用率只有上面绿色框这么点,而你申请了黄色框这么多,那么意味着中间的这一部分都是可以回收的
    • 不过Borg会保守回收,他不会把绿色之外的都回收,而是会留一部分保留资源,让应用应对高峰期,剩下的其他资源就回收了。
  • 目前在腾讯云这边,这些功能都已经做好了。所以使用公有云和自建云,最大的差异就是各种保障性功能公有云都做好了,自建云的话都需要自己搞

2.8.Borg如何实现隔离性

在这里插入图片描述

  • 其实不止Borg系统,整个计算机领域中,都认为CPU是可压榨资源,Memory是不可压榨资源
    • CPU是分时复用的,假设说CPU不够,应该分给应用A 80ms的,只分给了40ms,其他被别人占用了。从应用程序的角度来说,只是感觉应用慢一点,也不会有太大的问题,可能是用户多了1ms、2ms的,感受也不是很深。这种就是可压榨资源,因此对可压榨资源不需要关照的特别厉害,偶尔超一下没关系的。
    • 但是对于Memory内存来说就不一样了,内存一旦超限,大部分情况下就会OOM,所以我们对内存要格外关照,这种资源就是不可压缩资源。

3.什么是Kubernetes(K8s)

3.1.认识Kubernetes

在这里插入图片描述

  • 上图是Kubernetes worker计算节点的架构
    • 在每一个计算节点上面,都会运行一个kubelet
    • kubelet会通过Docker本身的interface去起一个个的容器
    • 容器之间依然是通过namespace和cgroup做安全隔离和性能隔离
  • Kubernetes的功能大部分沿袭了Borg
    • 比如说基于容器的应用部署、维护,滚动升级,实现负载均衡,基于服务发现实现了跨集群、跨地域的调度,自动伸缩等
  • Kubernetes可以承载有状态服务和无状态服务
    • 关于云原生应用,其实更推荐把应用做成无状态的,这样才能更好的利用kubernetes平台的弹性伸缩、跨az部署升级等能力
    • 有状态应用一般是千人千面的,不同的中间件,它的内在机理可谓千差万别,没有办法做成一个通用的组件,所以针对一个有状态的中间件,一般会为其单独开发一个Operator,而且一般也需要这个应用的专家才能维护
    • 要使用有状态应用的话,建议先去社区搜一搜,可能就会有人已经做出来了,可以二次开发

3.2.Kubernetes代码结构

在这里插入图片描述

在这里插入图片描述

  • api包

    • api包里面有个open-api-spec
    • open-api-spec里面有个swagger.json
      • swagger一般就是做API声明的,API声明一般会提供一个json,作为接口文档
  • build:所有构建相关的脚本

  • cmd:

    • 所有应用程序的main方法入口,二进制的编译入口
    • kubernetes是一个项目,这个项目下可以编译出好多个binery二进制可执行文件,就是不同的组件。另外kubernetes支持交叉编译,通过Makefile可以编译出不同CPU架构的可执行文件,如amd、windows等
    • 其中的每一个目录都是一个应用模块。每个应用模块中都应该有一个options目录,用于作入参校验等。如kube-apiserver目录下:
      在这里插入图片描述
  • pkg:各种组件功能的核心逻辑
    在这里插入图片描述

    • api、apis:对象的定义
    • 每种组件都有一个独立的目录

3.3.命令式vs声明式 系统

在这里插入图片描述

  • 现在系统大部分会被分为两种模式:
    • 命令式
    • 声明式
  • 命令式(Imperative System)
    • 一般就是交互式的系统,它会关注如何做
    • 比如说我在一个操作系统里面,我敲一个ls,我来看系统会给我什么反馈,基于他的反馈决定我下一次怎么做,这就是命令式
    • 命令式系统需要人工全程参与,根据上一次的结果,决定下一条命令怎么敲
    • 可以类比电视遥控器换台,不喜欢的话再换
  • 声明式(declarative system)
    • 我只约定我需要做什么,不关心系统是怎么做的,即面向终态的
    • 可以类比空调遥控器,空调的温度设定为25摄氏度,我期望最终变成25度,但是过程我不管
  • 二者对比
    • 命令式系统一定是响应非常快,或者比较简单的系统,要求立刻给出反馈
    • 声明式系统更适合复杂系统,比如说一个复杂任务,可能20分钟才能做完,过程中不阻塞,等做完后给出个通知提示就好。或者任何时候我要去查询的时候,你只需要把实时的状态返回即可
  • kubernetes就是一种声明式系统
    • 用户通过定义资源的spec,表达自己的期望状态。Kubernetes通过资源的status,表示实际状态。如何把状态调整到spec,由Kubernetes系统完成,不需要用户做指导和介入。
    • kubernetes能够变成业界标准的原因主要有两个。
      • 其一:kubernetes只是定义了一堆厂商中立的、通用的API,并且提供了一套框架来支撑这些API,维护最核心的功能。
        • kubernetes使用这些通用的API和框架,企图解决业界的一些通用问题,比如高可用怎么做、滚动升级怎么做、故障转移怎么做、扩缩容怎么做等。kubernetes给出的解决方案,和任何的厂商实现、任何的技术实现都没有太大关系,因此从这个角度来看,这种项目一定是一个长寿项目,生命周期一定非常长。
        • 对于不同的厂商来说,你用什么样的架构(arm、x86…)、用什么样的网络,用什么样的存储,这是你厂商要去解决的,你自己去选plugin。其实每个开源的plugin后面可能都围绕着一个厂商
        • kubernetes把这些东西剥离开,自己只解决最核心的通用问题,这是它最厉害的地方。
    • 其二:kubernetes系统足够灵活,任何人任何方案都可以和其对接,你自己提供一个CA网络插件,你有可能就成了一个创业公司,给整个生态都带来了机会,所以大家也愿意跟你一块发展。

3.4.kubernetes声明式系统包含哪些资源

在这里插入图片描述

  • Node
    • Kubernetes的本质就是把一堆节点组成一个集群,如何把几百上千个节点 组成一个集群,涉及集群管理的功能。
    • Kubernetes抽象了一个Node的概念
    • Node的名称即为主机名,node资源中记录了当前节点的状态:CIDR是什么、状态怎么样、一共有多少资源、可分配资源数量…
  • Namespace
    • 为了把多个用户或者多个项目的对象隔离开,Kubernetes抽象了一个Namespace的概念
    • 比如一个操作系统,不同的文件目录,可以设置不同的权限,进行文件隔离。Namespace就相当于一个虚拟目录,Kubernetes可以为不同Namespace设置不同的访问权限,进行访问控制。
    • 当然有些对象,比如Node是为整个集群提供服务的,不属于任何的namespace,因此Kubernetes的对象被分为:Namesapce对象、NonNamespace对象
  • Pod
    • 前面提到的都是管控层面的资源,真正用来描述应用实例的核心对象是Pod。Pod对象的出现打通了基础架构和应用接入的两个维度
    • 以前存在的问题:假设 现在使用了OpenStack集群,OpenStack只管理到操作系统层,应用人员只管到应用部署,上下两层是割裂的。难以控制应用要部署到哪个集群上,那如果要对openStack集群进行升级,就很难知道哪些节点可以一起重启,重启的时候会影响哪些应用,因此使得我基础架构层面的升级变得非常困难。
    • Kubernetes使用Pod打通了基础架构和应用接入的两个维度,应用层面只需要将自己的代码构建成容器镜像,然后资源、存储等基础架构的设置 使用 Pod的统一API进行联动,就可以控制 应用 跑在哪些节点上面。也可以随时查看某个节点上正在运行哪些应用,就可以知道重启节点会影响哪些应用了。
  • Service
    • Pod完成对应用的部署,但是还没有发布出去。想要发布一个服务,一定需要负载均衡、服务发现、服务治理等能力,Service应运而生。

3.5.Kuberntes系统架构

  • 下图即为Kubernetes的架构, 乍一看去,跟BOG系统没有什么区别,因此可以看出Borg真的是Kubernetes的前身

  • 下图是一个Kuberntes集群,对应Borg的一个Cell
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 控制平面组件(Master节点)

    • API Server
      • 整个Kubernetes系统的API网关,其实本质上就是一个Web服务,逻辑并不复杂,但是apiserver的地位非常重要,所有的Kubernetes组件都不会直接通信,而是通过API Server进行间接通信
      • API Server会对 所有的请求 进行 准入控制、鉴权等,然后对etcd数据库进行crud
    • etcd
      • 基于Raft协议的 Watchable(后面会讲)分布式键值对存储,所有资源的信息都存储在这里。
    • Scheduler
      • Scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。
      • 具体操作:当Scheduler发现etcd中有尚未调度的pod,就会从健康可调度node中选择一台,修改pod的node字段。之后对应node上的kubelet就会调用容器运行时接口,在自己node上创建pod了
    • Controller Manager
      • 一个好的云平台,一定有大量自动化逻辑,Controllers其实就是帮我们的资源实现大量自动化逻辑的位置。
      • controller-manager负责运行控制器进程。从逻辑上讲, 每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。
      • controller-manager包含了非常多的Controller,每个Controller都会监听自己关心的那部分资源,并负责将资源调谐到 spec中期望的状态
  • 计算节点组件(Worker节点)

    • Kubelet
      • 每个节点上都会跑一个Kubelet,负责上报 节点状态,pod状态、pod资源使用情况等信息到ApiServer,由ApiServer写入etcd。
      • 同时,Kubelet也会和apiserver交互,当发现 有pod被 Schedule 调度到自己所在node时,就会调用一系列标准接口,拉起pod的进程,并为之挂载网络和存储。
      • 厂商无关的标准接口:容器运行时(CRI)、容器网络标准(CNI)、容器存储标准(CSI)
    • Kube-Proxy(可选)
      • kube-proxy 实际上就是用来实现Service的一部分,是集群中每个节点(node)上所运行的网络代理。
      • kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。
      • 如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。
  • 上述组件并不是kubernetes所包含的所有组件,更详细的请参考:Kubernetes官网架构介绍

4.Kubernetes组件原理简介

4.1.etcd

4.1.1.etcd简介

在这里插入图片描述

  • ETCD本身是一个有状态的应用,基于Raft协议的分布式存储
  • 单节点存储的缺点
    • 如果数据库是单节点存储,那效率一定是很高的,但是会带来数据丢失的风险,万一磁盘坏了,数据就没了。
    • 因此就需要考虑数据备份,数据备份后安全性又需要保证,可以看出单节点存储本身会有很多问题。
  • 分布式存储
    • 那么有没有一种方式,可以让数据安全性提高一个等级呢?
    • 分布式存储,即使用多台服务器存储同一份数据,一个节点坏了,还有其他拷贝呢,这样的话数据的安全性就得以保证了。
    • 但是分布式存储需要解决两个问题:多副本的数据一致性、某个节点宕机后如何继续工作。Raft协议解决了这两个问题:
      • 分布式存储需要保证数据的一致性,写数据的时候需要 在多个存储中同时写入,使大家的数据状态都是一致的。
      • 节点宕机后整个应用还可以继续工作
    • etcd 集群使用 Raft 协议保障多节点集群状态下的数据一致性。etcd 是使用 Go 语言对 Raft 协议一种实现方式。
    • Etcd 中文文档
  • ETCD的应用场景
    • 服务发现,有点类似于concul的服务发现机制
    • 共享配置:相当于把它当成一个键值分布式数据库
    • 监听机制:
      • 一般的数据库,给它一个查询,它给你返回一个结果就结束了。但是在分布式系统里面经常需要用到消息队列实现监听,希望只在某件事情发生时才进行通知。
      • 对kubernetes的控制器来说,如果一直轮询请求apiserver来获取 资源的变化,实时性不好,而且对etcd本身的并发能力要求特别高
      • ETCD可以充当消息队列的角色,只在 数据发生变化时,通知 对应的监听者。
      • 实现方式:当一个客户端去访问ETCD数据库的时候,可以不是通过get的方式,而是watch的方式建立一个长连接,当数据发生变化的时候再来通知。这种方式减少了数据库的压力,而且听起来这就是一个消息中间件,巧妙地解决了组件和组件之间的协调关系。

4.1.2.etcd基本使用

在这里插入图片描述

  • kubernetes中。演示下etcd访问数据方式
    # 声明个别名
    [root@VM-226-235-tencentos ~]# alias ks='kubectl -n kube-system'
    
    # 获取etcd pod
    [root@VM-226-235-tencentos ~]# ks get pods | grep etcd
    NAME                                           READY   STATUS    RESTARTS   AGE
    etcd-vm-226-235-tencentos                      1/1     Running   0          223d
    
    # 进入pod内部[pod中没有bash命令,所以使用sh进入]
    [root@VM-226-235-tencentos ~]# ks exec -it etcd-vm-226-235-tencentos bash
    kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
    OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown
    command terminated with exit code 126
    
    [root@VM-226-235-tencentos ~]# ks exec -it etcd-vm-226-235-tencentos sh
    kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
    sh-5.0#
    
    # 查看etcd的主进程,发现没有ps命令
    sh-5.0# ps -ef
    sh: ps: command not found
    
    # 直接使用etcdctl也可以的,先指定要使用的 etcd API 版本为 v3
    sh-5.0# export ETCDCTL_API=3
    
    # 通过与 etcd 服务器建立安全连接,获取以斜杠(/registry/pods)开头的所有键的列表,而不返回与这些键关联的值
    	# --endpoints 指定 etcd 服务器的地址和端口。本例中 etcd 服务器位于 localhost 的 2379 端口上
    	# --cert、--key:指定用于进行 TLS 客户端身份验证的证书文件、私钥文件路径
    	# --cacert:指定用于进行 TLS 服务器身份验证的 CA 证书文件路径
    	# get --keys-only:具体要执行的操作,且只返回键(key),不返回与键关联的值(value)
    	# --prefix:指定要获取的键的前缀
    sh-5.0# etcdctl --endpoints https://localhost:2379 --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key --cacert /etc/kubernetes/pki/etcd/ca.crt get --keys-only --prefix /registry/pods
    /registry/pods/default/my-pod
    
    /registry/pods/default/mysql-pod
    
    /registry/pods/default/nginx-deployment-585449566-f9zt2
    
    /registry/pods/default/nginx-deployment-585449566-gtw92
    
    /registry/pods/default/nginx-deployment-585449566-kzdgv
    
    # 对etcd中的一个键值对,添加watch【以ns==default下的mysql-pod为例】
    	# 该命令执行完,会建立一个长连接,控制台会进入实时展示的状态
    	# 需要另外开一个窗口,编辑mysql-pod的yaml,查看watch机制的通知。
    sh-5.0# etcdctl --endpoints https://localhost:2379 --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key --cacert /etc/kubernetes/pki/etcd/ca.crt watch --prefix /registry/pods/default/mysql-pod
    
  • 下面演示watch的效果
    在这里插入图片描述
  • apiserver如何利用etcd的watch机制,实现控制器的watch?
    • 首先apiserver会对etcd中所有的数据,进行watch,并把watch到的数据添加一份缓存
    • 同时,apiserver也对外提供watch机制,所有的kubernetes组件都可以 建立长连接 watch自己感兴趣的资源,当资源发生变化的时候,通过长连接将数据变更事件发往各个组件
      • kubernetes组件首先会采用List机制,获取资源数据,然后以 watch机制 获取增量变化
    • 当一个组件watch到资源有变化的时候,要做什么处理,就是自己的代码逻辑了

4.2.APIServer

4.2.1.APIServer简介

在这里插入图片描述

  • apiserver的watch缓存
    • 从前面我们知道,apiserver是唯一一个和etcd通信的组件
    • 并且apiserver维护了一个watch缓存,List+Watch etcd中的所有资源,使得所有对资源的读操作 都直接走apiserver的watch缓存,写操作才会到达etcd
    • 这么做,是保护了etcd不被击穿,不会承受太大压力
  • apiserver的版本
    • v3版本已经比较成熟,v2当时是存在很多问题的
  • apiserver的三大功能
    • 认证
    • 授权
    • 准入控制

4.2.2.APIServer架构

在这里插入图片描述

  • APIHandler:http服务一般都包括的 url–>function路由转发
  • AuthN:authentication认证
  • Rate Limit:做限流处理,防止自己被过多流量打挂
  • Auditing:记录审计日志,可以用于破坏命令的责任追查
  • AuthZ:鉴权,一般会使用RBAC
  • Aggregator:apiserver的聚合器
    • 如果你想要自己做后续的 数据变形+验证+etcd交互,可以编写自己的apiserver,作为Aggregated APIServer,链接到此处。这种方式让APIServer具备了极大的扩展性。
    • Aggregated Server有时也会称为 Extension Server
    • 一般kubernetes的内置资源,都会按照上面的流程走完。
  • MutatingWebhook:数据变形处理器,包括 apiserver默认的、外置的。
    • 很多CRD,都会有自己的数据变形需求,可以开发一个MutatingWebhookService,作为Webhook供Apiserver在此处调用
    • 需要注意,Apiserver调用MutatingWebhookService,肯定是需要TLS连接的,所以MutatingWebhookService一般要配置证书的
  • SchemaValidating:校验变形后的数据,是否符合Schema规范
  • ValidatingWebhook:数据校验器,包括 apiserver默认的、外置的。
    • 很多CRD,都会有自己的数据校验需求,可以开发一个ValidatingWebhookService,作为Webhook供Apiserver在此处调用
    • 需要注意,Apiserver调用ValidatingWebhookService,肯定是需要TLS连接的,所以ValidatingWebhookService一般要配置证书的
  • etcd:上述步骤都走完了之后,才会将数据写入etcd,保护还是很严密的

4.2.3.Aggregated APIServer的使用案例

  • 比如 要给pod做 HPA 自动扩缩容,肯定是需要一些cpu、memory等指标数据的,这些指标要在APIServer中取
  • 在原生APIServer中是不包含这些指标的,因此可以自己写一个 Metrics APIServer,以 Aggregated APIServer的方式嵌入到APIServer中去,HPA的一些Controller就可以在APIServer中获取这些metrics指标数据了
  • 目前kubernetes社区已经有了开源的 metrics APIServer:即 metrics-server
    • https://github.com/kubernetes-sigs/metrics-server
    • 官方文档
  • 安装之后,可以使用kubectl top命令,查看指标
    • 比如 kubectl top node 就可以展示node的cpu、memory等使用情况

4.3.ControllerManager

4.3.1.ControllerManager介绍

  • 每个Controller逻辑是大同小异的,都是一个生产者消费者模型
    • Controller里的watcher就是一个生产者:使用watch机制监控APIServer中某些资源的变化,观察到的变化事件都会放入一个队列中
    • Controller里的处理逻辑作为消费者:不断从队列中取出数据去做调谐。如果调谐失败,需要有将事件重新放回队列,等待一段时间后重试,以此达到 最终一致性。
  • 最终一致性:不能保证一次就能达到spec期望状态,但是会有重试机制,保证经过多轮处理后,最终能够达到spec期望状态。
  • ControllerManager其实是一个控制器合集,内置资源的Controller都在这里,比如:
    • Deployment Controller
    • ReplicaSet Controller
    • Service Controller

4.3.2.控制器的工作流程

在这里插入图片描述

  • Controllerde Informer机制一般都包含两部分
    • Lister:负责从APIServer List全量数据
    • Informer:负责从APIServer Watch数据的变化
  • Controller 处理的基本流程
    • 首先Lister会从 APIServer List 全量数据
    • 之后Informer 会持续Watch资源的变更事件,并将不同的事件使用对应的 EventHandler(可以自行注册) 处理后,将资源key(namespace+name)加入队列
    • 启动一个或多个协程goroutine,作为消费者,从队列中取出资源key并处理

4.3.3.Informer的内部机制

在这里插入图片描述

  • Informer的组件及其职责
    • Reflector:反射器,负责将APIServer发过来的对象数据(一般是json或protobuf),反序列化成一个go struct
    • Delta FIFO Queue:循环FIFO队列,负责存储 待处理对象,Delta FIFO Queue是一个循环队列,满的时候会覆盖旧数据
    • Informer:通知器,负责从Delta FIFO Queue中不断弹出对象,做两件事:
      • 通过Indexer索引器,以key-value形式存入Thread Safe Store本地存储。
        • key:namespaceName
        • value:对象本身
      • 通过Handler,调用当前Event类型 对应的那一个Handler,处理后将对象的key添加到WorkQueue
    • Indexer:本地缓存索引器,负责处理和本地缓存相关的查询、写入操作
    • Thread Safe Store:线程安全的本地存储,负责在Informer内部维护一份对象缓存,这样控制器的查询操作,就不用到APIServer查询,直接在本地查询即可
      • 提高了查询效率,而且缓解了 APIServer 的压力
    • Handler:事件处理器,负责处理资源的不同Event,每种Event都应该有一个对应的Handler,所以应该有很多类型的Resource Handler。比如 Create Handler、Update Handler、Delete Handler…
    • WorkQueue:工作队列,负责存储所有待处理对象的key(namespaceName)
    • Process NextWorkItem:负责不断从WorkQueue取出key,交给某个Worker处理
    • Worker:资源处理工作器,负责真正的对象调谐工作。一般会启动多个Worker,每个Worker都是一个goroutine,并行处理WorkQueue中的事件
  • Informer是一个概念,SharedInformer是一个具体实现
  • Controller的整个处理流程如下(以Deployment Controller为例):
    • Controller 启动时,会通过Lister 先List一下所有Deployment资源,存入Thread Safe Store本地缓存
    • 然后 SharedInformer 通过长连接建立 Deployment资源的 watch 连接
    • 当发生Deployment资源变化时,APIServer会把事件及对应的Deployment资源对象,发送给Deployment控制器的SharedInformer
    • 首先会使用 Reflector将其反序列化为go struct,然后存入Delta FIFO Queue
    • Informer 组件会 从Delta FIFO Queue中取出对象,通过IndexerThread Safe Store本地缓存,并通过Handler将对象的key放入WorkQueue
    • Process NextWorkItem会从WorkQueue中取出key,找到一个worker对这个deployment资源进行处理

4.3.4.控制器之间协同工作原理

以创建一个Deployment资源为例

在这里插入图片描述

  • 用户使用kubectl或http请求方式,发起一个创建Deployment资源的请求
  • 请求到达APIServer,会经过 认证、鉴权、资源变形、schema校验、其他校验 等一系列处理后,APIServer 将deployment数据写入自己的watch缓存 和 etcd
    • Kubernetes 内部的 DeploymentController 早就已经和APIServer建立了Watch长连接
    • 当APIServer将数据写入缓存之后,就会把Deployment资源的变化,通知所有关心Deployment资源的watcher,其中就包括DeploymentController
  • DeploymentController 根据自己的处理逻辑,编排出对应的 ReplicaSet 资源,向APIServer发送了创建ReplicaSet请求
  • 请求到达APIServer,会经过 认证、鉴权、资源变形、schema校验、其他校验 等一系列处理后,APIServer 将ReplicaSet数据写入自己的watch缓存 和 etcd
    • Kubernetes 内部的 ReplicaSetController 早就已经和APIServer建立了Watch长连接
    • 当APIServer将数据写入缓存之后,就会把ReplicaSet资源的变化,通知所有关心ReplicaSet资源的watcher,其中就包括ReplicaSetController
  • ReplicaSetController 根据自己的处理逻辑,编排出对应的 Pod 资源,向APIServer发送了创建Pod请求
  • 请求到达APIServer,会经过 认证、鉴权、资源变形、schema校验、其他校验 等一系列处理后,APIServer 将Pod数据写入自己的watch缓存 和 etcd
    • Kubernetes 内部的 Scheduler调度器 和 每个Worker Node上的Kubelet 都早就已经和APIServer建立了Watch长连接
    • 当APIServer将数据写入缓存之后,就会把Pod资源的变化,通知所有关心Pod资源的watcher,其中就包括 Scheduler调度器.
    • 同时,Scheduler调度器还 watch 了所有的node对象
  • Scheduler调度器 发现该pod属于新创建,还没有调度,就会经过计算选择一个node,将 node名称 写到 pod的 spec.nodeName 中,即绑定pod与node,并向 APIServer 发起 pod update 请求。
  • APIServer一样会更新 watch缓存+etcd,并通知所有关心Pod资源的watcher,其中就包括 Worker Node 上的 kubelet
  • 某一个node上的kubelet 发现pod的 spec.nodeName 和自己的名称一致,就知道这个pod被调度到自己身上
    • 这个node上的kubelet,就会以此调用 CRI、CNI、CSI,启动容器,挂载网络和数据卷

4.4.Scheduler

  • 简单了解下,详细内容会有专门的文章讲解
    在这里插入图片描述

4.5.Kubelet

在这里插入图片描述

  • Kubelet是每一个Worker Node上都会安装的组件,极为重要,因为该node上所有管理pod都是它拉起来的。比如
    • PodWorker:负责管理当前节点上Pod的启停
    • OOMWatcher:负责管理当前节点的内存
    • GPUManager:负责管理当前节点的GPU
    • ProbeManager:负责对当前节点的应用进行健康检查
    • ImageGC:负责回收当前节点无用的镜像
    • ContainerGC:负责回收当前节点无用的容器
  • 对下层,Kubelet通过调用CRI、CNI、CSI 创建容器,挂载网络和数据卷
  • 对上层,Kubelet会把node、pod状态等信息,汇报给APIServer

4.6.Kube-Proxy(可选)

在这里插入图片描述

  • Kube-Proxy 是用来搭建负载均衡的。
    • 创建一个Service,关联上相应的Pod,就可以实现负载均衡。
    • 实际上这个负载均衡的网络规则配置等,都是Kube-Proxy做的。

4.7.附加组件 add-ons

  • 下面是一些附加组件,根据需求安装即可
  • 官方文档:https://kubernetes.io/zh-cn/docs/concepts/architecture/
    在这里插入图片描述

常见问题解答

  • 请见:Kubernetes常见问题解答

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2254078.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣-图论-1【算法学习day.51】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…

学习笔记056——Docker日志的清理问题

文章目录 Docker日志的清理问题1、Docke日志所在位置2、日志清理 Docker日志的清理问题 Ubuntu上部署Docker,运行一段时间后,会累计很多的日志量。 如果不及时处理,会占用系统空间,影响系统性能。 如何处理日志累计过大的问题&…

Python3:Pytest框架parametrize报错in “parametrize“ the number of names (4)

Python3:Pytest框架parametrize报错in “parametrize“ the number of names (4) 排查原因:是pytest入参时,需要4个参数,但是提供了3个参数 test_tenant_list:- ["http://xx:8081/scheduler/v1/tenancy/list",{"co…

Linux 35.6 + JetPack v5.1.4之RTP实时视频Python框架

Linux 35.6 JetPack v5.1.4之RTP实时视频Python框架 1. 源由2. 思路3. 方法论3.1 扩展思考 - 慎谋而后定3.2 扩展思考 - 拒绝拖延或犹豫3.3 扩展思考 - 哲学思考3.4 逻辑实操 - 方法论 4 准备5. 分析5.1 gst-launch-1.05.1.1 xvimagesink5.1.2 nv3dsink5.1.3 nv3dsink sync05…

GIt (一) Git的安装,项目搭建,远程仓库,分支

文章目录 一、 版本控制1.1 集中式版本控制1.2 分布式版本控制 二、 Git的安装及配置2.1 安装2.2 Git的配置2.2 查看配置 三、 Git基本理论3.1 工作区域3.2 文件状态 四、Git项目的搭建与操作4.1 初始化Git仓库4.2 常见的操作4.2.1 文件添加到暂存区4.2.2 文件提交更新4.2.3 查…

iview upload clearFiles清除回显视图

iview upload 上传完文件之后清除内容&#xff0c;打开会回显视图&#xff0c;清除不掉 关闭弹框时主动清除回显内容即可this.$refs.uploads.clearFiles() <FormItem label"上传附件:" :label-width"formNameWidth"><Upload action"/fms/ap…

JAVA |日常开发中Servlet详解

JAVA &#xff5c;日常开发中Servlet详解 前言一、Servlet 概述1.1 定义1.2 历史背景 二、Servlet 的生命周期2.1 加载和实例化2.2 初始化&#xff08;init 方法&#xff09;2.3 服务&#xff08;service 方法&#xff09;2.4 销毁&#xff08;destroy 方法&#xff09; 三、Se…

【C++】入门【六】

本节目标 一、继承的概念及定义 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 五、继承与友元 六、继承与静态成员 七、复杂的菱形继承及菱形虚拟继承 八、继承的总结和反思 九、笔试面试题 一、继承的概念及定义 1.继承的概念 继承是面向对象…

Docker--Docker Image(镜像)

什么是Docker Image&#xff1f; Docker镜像&#xff08;Docker Image&#xff09;是Docker容器技术的核心组件之一&#xff0c;它包含了运行应用程序所需的所有依赖、库、代码、运行时环境以及配置文件等。 简单来说&#xff0c;Docker镜像是一个轻量级、可执行的软件包&…

架构05-架构安全性

零、文章目录 架构05-架构安全性 1、软件架构安全的重要性 **系统安全&#xff1a;**不仅包括防御黑客攻击&#xff0c;还包括安全备份与恢复、安全审计、防治病毒等。**关注重点&#xff1a;**认证、授权、凭证、保密、传输安全、验证。 2、认证&#xff08;Authenticatio…

elasticsearch-如何给文档新增/更新的字段

文章目录 前言elasticsearch-如何给文档新增/更新的字段1. 如何给某些文档新增/更新的字段2. 给所有文档添加/更新一个新的字段3. 测试 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且…

Ansible自动化一键部署单节点集群架构

自动化部署利器&#xff1a;Ansible 一键部署脚本 在现代IT基础设施管理中&#xff0c;Ansible以其简洁、强大的自动化能力脱颖而出。以下是精心打造的Ansible自动化一键部署脚本&#xff0c;旨在简化部署流程&#xff0c;提升效率&#xff0c;确保一致性和可靠性。 通过这个…

常见Linux命令(详解)

文章目录 常见Linux命令文件目录类命令pwd 打印当前目录的绝对路径ls 列出目录内容cd 切换路径mkdir 建立目录rmdir 删除目录touch 创建空文件cp 复制文件或目录rm 移除文件或者目录mv 移动文件与目录或重命名cat 查看文件内容more 文件分屏查看器less 分屏显示文件内容head 显…

数据库复习记录

边复习边整理。 数据库 数据库管理系统&#xff08;DBMS&#xff09;&#xff1a;用来管理数据库的系统。 关系型数据库&#xff1a;二维表格&#xff08;即关系&#xff09;来存储数据&#xff0c;一个表对应一个关系&#xff0c;用SQL来查询数据。如MySQL、PostgreSQL、SQ…

Navicat连接SQL Server及SpringBoot连接SQL Server(jtds)

Navicat连接SQL Server 安装自带的SQL Server客户端 去到Navicat安装目录&#xff0c;找到安装程序&#xff0c;安装即可。 安装对应版本的Microsoft ODBC Driver for SQL Server 打开Navicat输入对应的SQL Server相关信息 然后点测试连接&#xff0c;提示连接成功。 Spr…

数字图像处理(15):图像灰度反转和彩色反转

&#xff08;1&#xff09;图像反转&#xff1a;是指对图像的颜色信息进行相反的处理&#xff0c;从而得到一个新的图像。在计算机视觉和图像处理领域&#xff0c;图像反转是一种常见的操作&#xff0c;它可以帮助我们实现不同的图像特效和视觉效果。 &#xff08;2&#xff09…

Linux——基础命令(3)

1.Linux——基础命令&#xff08;1&#xff09;-CSDN博客 2.Linux——基础命令&#xff08;2&#xff09; 文件内容操作-CSDN博客 一、打包压缩 打包压缩 是日常工作中备份文件的一种方式 在不同操作系统中&#xff0c;常用的打包压缩方式是不同的选项 含义 Windows 常用 rar…

【力扣热题100】—— Day4.回文链表

正视自己的懦弱和无能&#xff0c;克服自己的嫉妒与不甘 —— 24.12.3 234. 回文链表 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a…

python源码实例游戏开发小程序办公自动化网络爬虫项目开发源码(250+个项目、26.6GB)

文章目录 源代码下载地址项目介绍预览 项目备注源代码下载地址 源代码下载地址 点击这里下载源码 项目介绍 python源码实例游戏开发小程序办公自动化网络爬虫项目开发源码(250个项目、26.6GB) 预览 项目备注 1、该资源内项目代码都经过测试运行成功&#xff0c;功能ok的情…

AI与BI的火花:大语言模型如何重塑商业智能的未来

大家好&#xff0c;我是独孤风。 在当今这个数据驱动的时代&#xff0c;企业对于信息的需求如同对于氧气的需求一般至关重要。商业智能&#xff08;BI&#xff09;作为企业获取、分析和呈现数据的关键工具&#xff0c;正在经历一场深刻的变革&#xff0c;而这一变革的催化剂正是…