可以兼职做设计的网站,创意空间设计,公司宣传册设计样本免费下载,wordpress社交登录云原生学习路线导航页#xff08;持续更新中#xff09;
快捷链接 Kubernetes常见问题解答 本文从 Google Borg系统的架构设计开始#xff0c;深入讲解Kubernetes架构及组件的基本原理 1.什么是云计算
1.1.传统行业应用
假设有10台服务器#xff0c;两个应用。小规模管…云原生学习路线导航页持续更新中
快捷链接 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、WebSearchNonProduction应用离线作业
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 GoogleAutopilot 是通过动态的调整作业的资源需求来完成更高的资源利用率后面讲应用落地的时候会再讲包括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.什么是KubernetesK8s
3.1.认识Kubernetes 上图是Kubernetes worker计算节点的架构 在每一个计算节点上面都会运行一个kubeletkubelet会通过Docker本身的interface去起一个个的容器容器之间依然是通过namespace和cgroup做安全隔离和性能隔离 Kubernetes的功能大部分沿袭了Borg 比如说基于容器的应用部署、维护滚动升级实现负载均衡基于服务发现实现了跨集群、跨地域的调度自动伸缩等 Kubernetes可以承载有状态服务和无状态服务 关于云原生应用其实更推荐把应用做成无状态的这样才能更好的利用kubernetes平台的弹性伸缩、跨az部署升级等能力有状态应用一般是千人千面的不同的中间件它的内在机理可谓千差万别没有办法做成一个通用的组件所以针对一个有状态的中间件一般会为其单独开发一个Operator而且一般也需要这个应用的专家才能维护要使用有状态应用的话建议先去社区搜一搜可能就会有人已经做出来了可以二次开发
3.2.Kubernetes代码结构 api包 api包里面有个open-api-specopen-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访问数据方式# 声明个别名
[rootVM-226-235-tencentos ~]# alias kskubectl -n kube-system# 获取etcd pod
[rootVM-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进入]
[rootVM-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[rootVM-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_API3# 通过与 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【以nsdefault下的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缓存ListWatch etcd中的所有资源使得所有对资源的读操作 都直接走apiserver的watch缓存写操作才会到达etcd这么做是保护了etcd不被击穿不会承受太大压力 apiserver的版本 v3版本已经比较成熟v2当时是存在很多问题的 apiserver的三大功能 认证授权准入控制
4.2.2.APIServer架构 APIHandlerhttp服务一般都包括的 url–function路由转发AuthNauthentication认证Rate Limit做限流处理防止自己被过多流量打挂Auditing记录审计日志可以用于破坏命令的责任追查AuthZ鉴权一般会使用RBACAggregatorapiserver的聚合器 如果你想要自己做后续的 数据变形验证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 ControllerReplicaSet ControllerService Controller…
4.3.2.控制器的工作流程 Controllerde Informer机制一般都包含两部分 Lister负责从APIServer List全量数据Informer负责从APIServer Watch数据的变化 Controller 处理的基本流程 首先Lister会从 APIServer List 全量数据之后Informer 会持续Watch资源的变更事件并将不同的事件使用对应的 EventHandler可以自行注册 处理后将资源keynamespacename加入队列启动一个或多个协程goroutine作为消费者从队列中取出资源key并处理
4.3.3.Informer的内部机制 Informer的组件及其职责 Reflector反射器负责将APIServer发过来的对象数据一般是json或protobuf反序列化成一个go structDelta FIFO Queue循环FIFO队列负责存储 待处理对象Delta FIFO Queue是一个循环队列满的时候会覆盖旧数据Informer通知器负责从Delta FIFO Queue中不断弹出对象做两件事 通过Indexer索引器以key-value形式存入Thread Safe Store本地存储。 keynamespaceNamevalue对象本身 通过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工作队列负责存储所有待处理对象的keynamespaceNameProcess 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 QueueInformer 组件会 从Delta FIFO Queue中取出对象通过IndexerThread Safe Store本地缓存并通过Handler将对象的key放入WorkQueueProcess 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负责管理当前节点的GPUProbeManager负责对当前节点的应用进行健康检查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常见问题解答