当前位置: 首页 > news >正文

Kubernetes架构原则和对象设计

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

  • 快捷链接
    • 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常见问题解答

相关文章:

Kubernetes架构原则和对象设计

云原生学习路线导航页(持续更新中) 快捷链接 Kubernetes常见问题解答 本文从 Google Borg系统的架构设计开始,深入讲解Kubernetes架构及组件的基本原理 1.什么是云计算 1.1.传统行业应用 假设有10台服务器,两个应用。小规模管…...

npm : 无法加载文件 D:\nodejs\npm.ps1,因为在此系统上禁止运行脚本

要以管理员身份打开PowerShell,请按照以下步骤操作: 在Windows搜索框中查找PowerShell: 在任务栏上,点击左下角的Windows徽标(或按Win S键)以打开搜索框。输入“PowerShell”以查找PowerShell应用程序。右…...

Linux CentOS

​阿里云开源镜像下载链接 https://mirrors.aliyun.com/centos/7/isos/x86_64/ VMware 安装 CentOS7 自定义 下一步 选择稍后安装操作系统 选择 输入 查看物理机CPU内核数量 CtrlShiftEsc 总数不超过物理机内核数量 推荐内存 自选 推荐 推荐 默认 拆分成多个 默认 自定义硬件…...

如何用注册机破解Reflexive游戏

相信有许多小朋友(像我以前一样)已经迫不及待地准备准备对浩瀚的、像三星堆一般的Reflexive游戏合集进行考古挖掘工作了。不巧的是,打开游戏之后发现常常提示要付费才能解锁完整版。 一、下载注册机与破解文件 首先,在我的永硕网…...

【算法day7】字符串:反转与替换

题目引用 反转字符串反转字符串II替换数字 1.反转字符串 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1&am…...

基于Linux C++多线程服务器 + Qt上位机开发 + STM32 + 8266WIFI的智慧无人超市

前言 针对传统超市购物车结账排队时间长、付款效率低的问题,提出了一种更符合现代社会人们购物方式-基于RFID的自助收银系统。习惯了快节奏生活的人们都会选择自助收银机结账,理由显而易见:自助收银机结账很方便,几乎不用排队&am…...

继电器测试的培训和学习资源有哪些推荐?

继电器是电气控制设备中常见的一种元件,用于实现电路的开关控制和保护功能。对于从事电气相关工作的人员来说,掌握继电器的测试技能是非常重要的。以下是一些推荐的继电器测试培训和学习资源: 1. 在线课程:许多在线学习平台提供了…...

学习日志020---qt信号与槽

作业 import sysfrom PySide6.QtWidgets import QApplication, QWidget,QPushButton,QLineEditfrom Form import Ui_Form from second import Ui_second from PySide6.QtCore import Qtclass MyWidget(QWidget,Ui_Form):def __init__(self):super().__init__()self.setupUi(se…...

小迪安全笔记 第四十四天 sql盲注 实战利用sql盲注 进行漏洞的利用

sql盲注的分类 什么是盲注 就是我们什么也不知道的情况下进行的注入 前边的注入 都是简单的注入 我们猜测 数据类型 之后 可以直接 union 去查 这种情况多用于 数据库增删查改中的 查 bool盲注也用于查 这个的情况的就是我们前边都试了 没有用 就需要…...

AMEYA360:上海永铭电子全新高压牛角型铝电解电容IDC3系列,助力AI服务器电源高效运转

随着数据中心和云计算的高速发展,AI服务器的能效要求日益提高。如何在有限空间内实现更高的功率密度和稳定的电源管理,成为AI服务器电源设计的一大挑战。永铭推出全新高压牛角型铝电解电容IDC3系列,以大容量、小尺寸的创新特性,为…...

SpringBoot Web 开发请求参数

SpringBoot Web 开发请求参数 简单的 web 请求: @RestController public class HelloController {@RequestMapping("sayHello")public String sayHello(){System.out.println("Hello World");return "hello world";} }获取请求参数 简单参数…...

力扣92.反转链表Ⅱ

题目描述 题目链接92. 反转链表 II 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left …...

网络安全、Web安全、渗透测试之笔经面经总结(一)

本篇文章总结涉及以下几个方面&#xff1a; 一&#xff1a;对称加密非对称加密&#xff1f; 对称加密&#xff1a;加解密用同一密钥&#xff0c;密钥维护复杂n&#xff08;n-1&#xff09;/2&#xff0c;不适合互联网传输密钥&#xff0c;加解密效率高。应用于加密数据。 非…...

11 设计模式之代理模式(送资料案例)

一、什么是代理模式&#xff1f; 在现实生活中&#xff0c;我们常常遇到这样的场景&#xff1a;由于某些原因&#xff0c;我们可能无法亲自完成某个任务&#xff0c;便会委托他人代为执行。在设计模式中&#xff0c;代理模式 就是用来解决这种“委托”问题的&#xff0…...

matlab2024a安装

1.开始安装 2.点击安装 3.选择安装密钥 4.接受条款 5.安装密钥 21471-07182-41807-00726-32378-34241-61866-60308-44209-03650-51035-48216-24734-36781-57695-35731-64525-44540-57877-31100-06573-50736-60034-42697-39512-63953 6 7.选择许可证文件 8.找许可证文件 9.选…...

齐护机器人ModbusRTU RS485转TTL通信模块与ESP32 Arduino通信可Mixly的图形化编程Scratch图形化编程

齐护机器人ModbusRTU RS485-TTL通信模块 一、概念理解 Modbus协议是一种由Modicon公司&#xff08;现为施耐德电气Schneider Electric&#xff09;于1979年发表的网络通信协议&#xff0c;旨在实现可编辑逻辑控制器&#xff08;PLC&#xff09;之间的通信。 1.1 什么是Mod…...

JDK、JRE、JVM的区别

JDK&#xff08;Java Development Kit&#xff09;、JRE&#xff08;Java Runtime Environment&#xff09;和JVM&#xff08;Java Virtual Machine&#xff09;是Java技术栈中的三个核心组件&#xff0c;它们各自有不同的功能和用途&#xff1a; 1. JDK&#xff08;Java Deve…...

linux基础2

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…...

vue 项目实现阻止浏览器记住密码

​在各个浏览器中&#xff0c;登录输入密码一般都会弹出是否记住密码的功能&#xff0c;如果记住之后&#xff0c;会在各个密码框自动填充记住的密码&#xff0c;这无疑是一种不安全的操作&#xff0c;所以要实现禁用阻止浏览器记住密码的行为 查阅资料&#xff0c;也得到很多…...

【23种设计模式】工厂模式:理论剖析与Java实践

文章目录 工厂模式&#xff1a;理论、Java 实现与实践应用一、工厂模式概述二、简单工厂模式&#xff08;一&#xff09;理论介绍&#xff08;二&#xff09;代码实现&#xff08;三&#xff09;关键步骤&#xff08;四&#xff09;流程图 三、工厂方法模式&#xff08;一&…...

(补充)JSON在Java后端的应用

JSON在Java后端的应用 本篇介绍 本篇文档不涉及到写一个JSON字符串&#xff0c;只是介绍如何在后端实现JSON字符串和Java对象的相互转换 Java对象转换为JSON字符串 在Java中&#xff0c;可以使用一个第三方工具包Jackson将Java对象转换为JSON对象&#xff0c;假设现在有一个…...

使用 Apache Commons IO 实现文件读写

在 Java 编程中&#xff0c;文件读写是常见的操作。虽然 Java 标准库提供了基本的文件 I/O 功能&#xff0c;但使用 Apache Commons IO 库可以进一步简化这些操作&#xff0c;提高开发效率。Apache Commons IO 是一个强大的工具库&#xff0c;提供了许多实用的类和方法&#xf…...

AWS ECS Task 添加 Prometheus 监控采集配置详细指南

以下是一篇完整的博文,介绍如何在 AWS ECS 环境中实现 JVM 监控。 AWS ECS 环境下的 JVM 监控实践 概述 在 AWS ECS (Elastic Container Service) 环境中监控 Java 应用性能是一项重要任务。本文将详细介绍如何使用 AWS Distro for OpenTelemetry (ADOT) 结合 Spring Boot …...

Vue+vite 组件开发的环境准备

一.nodejs安装 进入Node.js 官网&#xff08;Node.js — Run JavaScript Everywhere&#xff09;&#xff0c;点击下载。 双击打开&#xff0c;进行安装 双击打开后&#xff0c;点击 next&#xff08;下一步&#xff09;,后面也是一直点击 next 无其他设置&#xff0c;直到 …...

STM32 进阶 定时器:1系统定时器 系统中断案例 LED闪烁

定时器&#xff1a; 功能从高到低&#xff1a; TIM1和TIM8 高级控制定时器&#xff1a;输出能力更强&#xff0c;刹车控制、死区时间。 TIMx 通用定时器&#xff1a;可以输出PWM方波 TIM6和TIM7 基本定时器&#xff1a;只能计时 系统定时器 系统定时器&#xff08;SysTic…...

基于微信小程序的教学质量评价系统

​ 私信我获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 基于微信小程序的教学质量评价系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的教学质量评价系统的开发全过…...

Qt Qtablewidget 标题 QHeaderView 增加可选框 QcheckBox

创建自定义QHeaderView #pragma once#include <QObject> #include <QHeaderView> #include <QPainter> #include <QMouseEvent>class SSHeaderView : public QHeaderView {Q_OBJECTprivate:bool isChecked;int m_checkColIdx; public:SSHeaderView(i…...

在CentOS上无Parallel时并发上传.wav文件的Shell脚本解决方案

在CentOS上无Parallel时并发上传.wav文件的Shell脚本解决方案 背景概述解决方案脚本实现脚本说明使用指南注意事项在CentOS操作系统环境中,若需并发上传特定目录下的.wav文件至HTTP服务器,而系统未安装GNU parallel工具,我们可通过其他方法实现此需求。本文将介绍一种利用Sh…...

实战ansible-playbook(四) -文件操作重定向/追加

原始命令: ----------阶段1--------------- apt-get update -y apt install nano vim iputils-ping net-tools dialog gcc apt-utils make -y systemctl stop unattended-upgradessystemctl disable unattended-upgradesecho APT::Periodic::Update-Package-Lists "1&qu…...

嵌入式 C 编程必备(7):const 关键字 —— 打造稳定的常量空间

目录 一、const关键字的基本含义与用法 1.1. 修饰基本数据类型 1.2. 修饰指针 1.3. 修饰数组 1.4. 修饰结构体 二、const关键字在嵌入式编程中的优势 2.1. 提升代码可读性 2.2. 增强代码安全性 2.3. 优化内存使用 2.4. 促进模块化设计 2.5. 支持静态分析和测试 三、…...

电脑显示没信号显示屏不亮怎么办?电脑没信号解决方法

电脑没信号显示屏不亮这种故障的原因可能有多种&#xff0c;例如显示器的供电、连接、设置等问题&#xff0c;或者电脑的显卡、内存、硬盘、主板等硬件问题。所以我们想要解决这个问题&#xff0c;也是需要多方面排除找到具体原因然后进行修复。下面将为大家介绍一些常见的电脑…...

C++零基础入门:运算符与表达式详解 —— 树莓派Pico编程应用

C语言作为信息学奥赛的指定语言&#xff0c;广泛应用于嵌入式开发、系统编程、游戏开发等领域。对于初学者而言&#xff0c;掌握基本的运算符和表达式是进行编程的基础&#xff0c;而这些基础知识能够帮助你解决各种实际问题。本文将带你深入理解C中的运算符与表达式&#xff0…...

mvc命令

命令 mvc MVC(Model-View-Controller)是一种软件架构模式,用于组织和管理应用程序的代码mvc重要的三部分 (1)‌模型&#xff08;Model&#xff09;‌&#xff1a;负责存储系统的中心数据&#xff0c;提供访问数据的函数&#xff0c;封装了应用程序的功能内核。 (2)视图&…...

Kafka-创建topic源码

一、命令创建topic kafka-topics --create --topic quickstart-events --bootstrap-server cdh1:9092 --partitions 2 --replication-factor 2 二、kafka-topics脚本 exec $(dirname $0)/kafka-run-class.sh org.apache.kafka.tools.TopicCommand "$" 脚本中指定了…...

如何开展单元测试

1、是什么 单元测试&#xff08;Unit Testing&#xff09;又称为模块测试&#xff0c;是针对程序模块来进行正确性检验的测试工作。 程序模块是软件设计的最小单位&#xff0c;程序单元是应用的最小可测试部件 • 在面向过程编程中&#xff0c;一个单元就是单个程序、函数、过…...

网络练级宝典-> UDP传输层协议

目录 传输层 端口号 端口号和进程的关系 UDP协议 UDP协议格式 UDP数据封装&#xff1a; UDP数据分用&#xff1a; 面向数据报 UDP的缓冲区 UDP的缺点 基于UDP的应用层协议 传输层 端口号 我们知道端口号对应的其实就是一个进程的pid&#xff0c;在操作系统中二者的…...

【Elasticsearch】07-ES聚合

1. 桶 桶&#xff08;Bucket&#xff09;聚合&#xff1a;用来对文档做分组 TermAggregation&#xff1a;按照文档字段值分组&#xff0c;例如按照品牌值分组、按照国家分组Date Histogram&#xff1a;按照日期阶梯分组&#xff0c;例如一周为一组&#xff0c;或者一月为一组…...

Unity 画线(UILineRenderer)

实现 以鼠标点击点作为起点创建UILineRenderer 并记录起点。 GameObject go new GameObject(); go.transform.parent transPaint; go.transform.localPosition Vector3.zero; line go.AddComponent<UILineRenderer>(); line.LineWidth widthLine; line.color col…...

【Linux测试题】

1. 选择题 题目&#xff1a; 如果想将电脑中Windows C盘&#xff08;hd1&#xff09;安装在Linux文件系统的/winsys目录下&#xff0c;请问正确的命令是&#xff08;&#xff09;。 选项&#xff1a; A. root104.123.123.123:~# mount dev/hd1 /winsys B. root104.123.123.12…...

什么是快速傅里叶变换?

一、FFT概念 快速傅里叶变换&#xff08;Fast Fourier Transform&#xff0c;FFT&#xff09;是一种高效计算离散傅里叶变换&#xff08;Discrete Fourier Transform&#xff0c;简称DFT&#xff09;及其逆变换的算法。DFT和FFT都是音频处理、图像分析、振动分析、无线通信等许…...

android-studio开发第一个项目,并在设备上调试

恭喜你成功安装并配置好了 Android Studio&#xff01;下面是开发你的第一个 Android 项目并在设备上调试的详细步骤&#xff1a; 1. 启动 Android Studio 首先&#xff0c;启动 Android Studio。你可以通过以下几种方式启动&#xff1a; 使用桌面快捷方式&#xff08;如果已…...

深入浅出:php-学习入门全攻略

文章目录 1. 为什么选择 PHP&#xff1f;2. 安装 PHP 环境2.1 Windows 系统安装步骤 1&#xff1a;下载 PHP步骤 2&#xff1a;解压并配置步骤 3&#xff1a;配置环境变量步骤 4&#xff1a;验证安装 2.2 Mac 系统安装步骤 1&#xff1a;使用 Homebrew 安装步骤 2&#xff1a;验…...

Qml之基本控件

一.Qml常用控件 1.Text(显示普通文本和富文本) 1.1显示普通文本&#xff1a; Window { visible: true width: 320 height: 240 title: qsTr("Hello World") Text { text: "Hello World!" font.family: "Helvetica" font.pointSize: 24 color:…...

redis机制详解

RDB 快照机制 在默认情况下&#xff0c;Redis 会将内存数据库的快照存储在名为 “dump.rdb” 的二进制文件中。同时&#xff0c;你可以通过相关设置&#xff0c;让 Redis 在满足特定条件时自动保存数据集。例如&#xff0c;设定 “save 60 1000”&#xff0c;意味着当在 60 秒内…...

【知识科普】Linux系统下用户权限体系

文章目录 概述一、用户类型二、用户权限的组成三、权限的表示方法四、权限的修改方法五、特殊权限六、权限掩码&#xff08;umask&#xff09; 密码相关一、修改用户密码二、删除用户密码三、设置用户密码有效期四、查询用户密码信息五、密码策略配置 SSH远程访问1. 检查SSH服务…...

【数据结构】堆

目录 一、堆 二、堆的模拟实现 1.结构体 2.push 3.pop和top 三.实现堆排序 1.成堆算法 2.堆排序 heap模拟实现源码_gitee 一、堆 分为大堆和小堆 大堆是每个父节点都大于子节点&#xff0c;小堆则相反是每个父节点都小于子节点 底层抽象结构是完全二叉树&#xff0…...

6.824/6.5840 Lab 1: MapReduce

宁静的夏天 天空中繁星点点 心里头有些思念 思念着你的脸 ——宁夏 完整代码见&#xff1a; https://github.com/SnowLegend-star/6.824 由于这个lab整体难度实在不小&#xff0c;故考虑再三还是决定留下代码仅供参考 6.824的强度早有耳闻&#xff0c;我终于也是到了挑战这座高…...

Day5:生信新手笔记 — R语言基本语法

一、数据类型 &#xff08;重点只有两个&#xff0c;剩下的不看&#xff09; 1.1 向量&#xff08;vector&#xff09; 矩阵&#xff08;Matrix&#xff09; 数组&#xff08;Array&#xff09; 1.2 数据框&#xff08;Data frame&#xff09; x<- c(1,2,3) #常用的向…...

lua download

https://www.lua.org/ https://www.lua.org/versions.html#5.4...

安装更新upgrade导致ubuntu崩溃

安装更新导致ubuntu崩溃 前言uuid编不过&#xff0c;导致的崩溃 记录一些ubuntu崩溃的过程。 目前只有一个&#xff0c;以后遇到都放在这里&#xff0c;以提醒自己。 前言 如果从10000年看现在的linux&#xff0c;不是说不完美&#xff0c;而是糟透了。 linux的版本号&#xf…...