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早期用的 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 策略来分配任务。
- 这种策略可以在资源利用率和资源碎片化之间取得平衡。
- Worst 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
- 可以在kubelet启动命令中增加–max-pods参数,重启kubelet 服务,修改node的pod上限。
-
那么为什么要设置上限呢,不设置行不行,只要有资源,就让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只是定义了一堆厂商中立的、通用的API,并且提供了一套框架来支撑这些API,维护最核心的功能。
- 其二: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中期望的状态
- API Server
-
计算节点组件(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 仅做流量转发。
- Kubelet
-
上述组件并不是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索引器,以key-value形式存入Thread Safe Store本地存储。
- 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 ,其中 left < right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。 示例 1: 输入:head [1,2,3,4,5], left …...
网络安全、Web安全、渗透测试之笔经面经总结(一)
本篇文章总结涉及以下几个方面: 一:对称加密非对称加密? 对称加密:加解密用同一密钥,密钥维护复杂n(n-1)/2,不适合互联网传输密钥,加解密效率高。应用于加密数据。 非…...
11 设计模式之代理模式(送资料案例)
一、什么是代理模式? 在现实生活中,我们常常遇到这样的场景:由于某些原因,我们可能无法亲自完成某个任务,便会委托他人代为执行。在设计模式中,代理模式 就是用来解决这种“委托”问题的࿰…...
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公司(现为施耐德电气Schneider Electric)于1979年发表的网络通信协议,旨在实现可编辑逻辑控制器(PLC)之间的通信。 1.1 什么是Mod…...
JDK、JRE、JVM的区别
JDK(Java Development Kit)、JRE(Java Runtime Environment)和JVM(Java Virtual Machine)是Java技术栈中的三个核心组件,它们各自有不同的功能和用途: 1. JDK(Java Deve…...
linux基础2
声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&#…...
vue 项目实现阻止浏览器记住密码
在各个浏览器中,登录输入密码一般都会弹出是否记住密码的功能,如果记住之后,会在各个密码框自动填充记住的密码,这无疑是一种不安全的操作,所以要实现禁用阻止浏览器记住密码的行为 查阅资料,也得到很多…...
【23种设计模式】工厂模式:理论剖析与Java实践
文章目录 工厂模式:理论、Java 实现与实践应用一、工厂模式概述二、简单工厂模式(一)理论介绍(二)代码实现(三)关键步骤(四)流程图 三、工厂方法模式(一&…...
(补充)JSON在Java后端的应用
JSON在Java后端的应用 本篇介绍 本篇文档不涉及到写一个JSON字符串,只是介绍如何在后端实现JSON字符串和Java对象的相互转换 Java对象转换为JSON字符串 在Java中,可以使用一个第三方工具包Jackson将Java对象转换为JSON对象,假设现在有一个…...
使用 Apache Commons IO 实现文件读写
在 Java 编程中,文件读写是常见的操作。虽然 Java 标准库提供了基本的文件 I/O 功能,但使用 Apache Commons IO 库可以进一步简化这些操作,提高开发效率。Apache Commons IO 是一个强大的工具库,提供了许多实用的类和方法…...
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 官网(Node.js — Run JavaScript Everywhere),点击下载。 双击打开,进行安装 双击打开后,点击 next(下一步),后面也是一直点击 next 无其他设置,直到 …...
STM32 进阶 定时器:1系统定时器 系统中断案例 LED闪烁
定时器: 功能从高到低: TIM1和TIM8 高级控制定时器:输出能力更强,刹车控制、死区时间。 TIMx 通用定时器:可以输出PWM方波 TIM6和TIM7 基本定时器:只能计时 系统定时器 系统定时器(SysTic…...
基于微信小程序的教学质量评价系统
私信我获取源码和万字论文,制作不易,感谢点赞支持。 基于微信小程序的教学质量评价系统 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的教学质量评价系统的开发全过…...
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. 支持静态分析和测试 三、…...
电脑显示没信号显示屏不亮怎么办?电脑没信号解决方法
电脑没信号显示屏不亮这种故障的原因可能有多种,例如显示器的供电、连接、设置等问题,或者电脑的显卡、内存、硬盘、主板等硬件问题。所以我们想要解决这个问题,也是需要多方面排除找到具体原因然后进行修复。下面将为大家介绍一些常见的电脑…...
C++零基础入门:运算符与表达式详解 —— 树莓派Pico编程应用
C语言作为信息学奥赛的指定语言,广泛应用于嵌入式开发、系统编程、游戏开发等领域。对于初学者而言,掌握基本的运算符和表达式是进行编程的基础,而这些基础知识能够帮助你解决各种实际问题。本文将带你深入理解C中的运算符与表达式࿰…...
mvc命令
命令 mvc MVC(Model-View-Controller)是一种软件架构模式,用于组织和管理应用程序的代码mvc重要的三部分 (1)模型(Model):负责存储系统的中心数据,提供访问数据的函数,封装了应用程序的功能内核。 (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、是什么 单元测试(Unit Testing)又称为模块测试,是针对程序模块来进行正确性检验的测试工作。 程序模块是软件设计的最小单位,程序单元是应用的最小可测试部件 • 在面向过程编程中,一个单元就是单个程序、函数、过…...
网络练级宝典-> UDP传输层协议
目录 传输层 端口号 端口号和进程的关系 UDP协议 UDP协议格式 UDP数据封装: UDP数据分用: 面向数据报 UDP的缓冲区 UDP的缺点 基于UDP的应用层协议 传输层 端口号 我们知道端口号对应的其实就是一个进程的pid,在操作系统中二者的…...
【Elasticsearch】07-ES聚合
1. 桶 桶(Bucket)聚合:用来对文档做分组 TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组…...
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. 选择题 题目: 如果想将电脑中Windows C盘(hd1)安装在Linux文件系统的/winsys目录下,请问正确的命令是()。 选项: A. root104.123.123.123:~# mount dev/hd1 /winsys B. root104.123.123.12…...
什么是快速傅里叶变换?
一、FFT概念 快速傅里叶变换(Fast Fourier Transform,FFT)是一种高效计算离散傅里叶变换(Discrete Fourier Transform,简称DFT)及其逆变换的算法。DFT和FFT都是音频处理、图像分析、振动分析、无线通信等许…...
android-studio开发第一个项目,并在设备上调试
恭喜你成功安装并配置好了 Android Studio!下面是开发你的第一个 Android 项目并在设备上调试的详细步骤: 1. 启动 Android Studio 首先,启动 Android Studio。你可以通过以下几种方式启动: 使用桌面快捷方式(如果已…...
深入浅出:php-学习入门全攻略
文章目录 1. 为什么选择 PHP?2. 安装 PHP 环境2.1 Windows 系统安装步骤 1:下载 PHP步骤 2:解压并配置步骤 3:配置环境变量步骤 4:验证安装 2.2 Mac 系统安装步骤 1:使用 Homebrew 安装步骤 2:验…...
Qml之基本控件
一.Qml常用控件 1.Text(显示普通文本和富文本) 1.1显示普通文本: Window { visible: true width: 320 height: 240 title: qsTr("Hello World") Text { text: "Hello World!" font.family: "Helvetica" font.pointSize: 24 color:…...
redis机制详解
RDB 快照机制 在默认情况下,Redis 会将内存数据库的快照存储在名为 “dump.rdb” 的二进制文件中。同时,你可以通过相关设置,让 Redis 在满足特定条件时自动保存数据集。例如,设定 “save 60 1000”,意味着当在 60 秒内…...
【知识科普】Linux系统下用户权限体系
文章目录 概述一、用户类型二、用户权限的组成三、权限的表示方法四、权限的修改方法五、特殊权限六、权限掩码(umask) 密码相关一、修改用户密码二、删除用户密码三、设置用户密码有效期四、查询用户密码信息五、密码策略配置 SSH远程访问1. 检查SSH服务…...
【数据结构】堆
目录 一、堆 二、堆的模拟实现 1.结构体 2.push 3.pop和top 三.实现堆排序 1.成堆算法 2.堆排序 heap模拟实现源码_gitee 一、堆 分为大堆和小堆 大堆是每个父节点都大于子节点,小堆则相反是每个父节点都小于子节点 底层抽象结构是完全二叉树࿰…...
6.824/6.5840 Lab 1: MapReduce
宁静的夏天 天空中繁星点点 心里头有些思念 思念着你的脸 ——宁夏 完整代码见: https://github.com/SnowLegend-star/6.824 由于这个lab整体难度实在不小,故考虑再三还是决定留下代码仅供参考 6.824的强度早有耳闻,我终于也是到了挑战这座高…...
Day5:生信新手笔记 — R语言基本语法
一、数据类型 (重点只有两个,剩下的不看) 1.1 向量(vector) 矩阵(Matrix) 数组(Array) 1.2 数据框(Data frame) x<- c(1,2,3) #常用的向…...
lua download
https://www.lua.org/ https://www.lua.org/versions.html#5.4...
安装更新upgrade导致ubuntu崩溃
安装更新导致ubuntu崩溃 前言uuid编不过,导致的崩溃 记录一些ubuntu崩溃的过程。 目前只有一个,以后遇到都放在这里,以提醒自己。 前言 如果从10000年看现在的linux,不是说不完美,而是糟透了。 linux的版本号…...