go
文章平均质量分 90
进德
这个作者很懒,什么都没留下…
展开
-
Kubernetes API的流编解码器StreamSerializer
从数据流中读取数据并解码API对象的解码器本文命名为流解码器,我们日常说的流是字节流,那么流解码器可以看做是API对象流,每调用一次返回一个API对象。如果想把字节流变成API对象流,首先需要将字节流变成json/yaml/protobuf序列化格式对象流,即先从字节流中读取一个一个的json/yaml/protobuf对象。然后再用解码器将json/yaml/protobuf对象解码成API对象就完成了。...原创 2022-07-02 11:59:40 · 688 阅读 · 2 评论 -
Kubernetes的NodeLifecycleController如何管理污点
需要强调的是,本文的污点指的是NoExecute污点,这种污点会驱逐已经运行的pod,这可以从NoExecute字面意思看的出来。《kube-scheduler调度插件》的TaintToleration在Filter阶段会过滤掉pod无法容忍的NoSchedule和NoExecute污点,也就是说调度器不会调度pod到无法容忍污点node上,那NodeLifecycleController管理还要管理NoExecute干什么呢?道理很简单,node的污点会更新,pod的容忍度也会更新,调度器不会因为no原创 2022-06-19 11:39:55 · 726 阅读 · 0 评论 -
Kubernetes的RecognizingDecoder解析
前言在Serializer文章中提到了,Serializer虽然抽象了序列化/反序列化的接口,但是反序列化不同格式的数据需要不同的Serializer对象,并不是很通用。有没有一种类型可以反序列化任意格式的数据呢?答案是有的,但是在介绍这个“万能解码器”之前,需要引入RecognizingDecoder接口。本文引用源码为kubernetes的release-1.21分支。RecognizingDecoder如果笔者自己实现“万能解码器”,我抽象一个接口用于判断解码器是否能够解码当前格式的数原创 2021-06-08 22:17:42 · 2044 阅读 · 1 评论 -
Kubernetes的Serializer解析
前言序列化和反序列化在很多项目中都有应用,Kubernetes也不例外。Kubernetes中定义了大量的API对象,为此还单独设计了一个包,方便多个模块引用。API对象在不同的模块之间传输(尤其是跨进程)可能会用到序列化与反序列化,不同的场景对于序列化个格式又不同,比如grpc协议用protobuf,用户交互用yaml(因为yaml可读性强),etcd存储用json。Kubernetes反序列化API对象不同于我们常用的json.Unmarshal()函数(需要传入对象指针),Kubernetes需要原创 2021-06-08 22:12:42 · 3783 阅读 · 0 评论 -
一张图看懂kube-scheduler
利用SharedIndedInformer过滤未调度的Pod放入调度队列 利用SharedIndexInformer过滤已调度的Pod更新调度缓存 从调度队列取出一个待调度的Pod,通过Pod.Spec.SchedulerName获取调度框架 调度框架是配置好的调度插件集合,既可以通过扩展调度插件的方式扩展调度能力,也可以通过调度扩展器 调度算法利用调度缓存的快照以及输入的调度框架,为Pod选择最优的节点 如果调度算法执行失败,将Pod放入调度队列的不可调度自队列;如果调度算法执行成功,通知调度缓原创 2021-06-07 21:38:03 · 2477 阅读 · 0 评论 -
kube-scheduler的Configurator解析
前言调度器配置中解析了kube-scheduler的各种配置,但是自始至终都没有看到如何根据配置构造调度器。虽然调度器文章中提到了构造函数,但是其核心实现是Configurator,本文将解析Configurator构造调度器的过程。虽然意义远没有调度队列、调度框架、调度插件等重大,但是对于了解调度器从生到死整个过程来说是必要一环,况且确实能学到点东西。ConfiguratorConfigurator定义Configurator类似于Scheduler的工厂,但是一般的工厂类很少会有这么多的原创 2021-06-07 21:30:09 · 2442 阅读 · 0 评论 -
KubeSchedulerConfiguration解析
前言kube-scheduler如何配置调度框架和调度插件中提到的插件(比如使能或禁止哪些插件?)?如何配置调度队列的排序函数以及退避时间?本文将详细解析kube-scheduler的配置,在kube-scheduler中,配置也是一种API对象(其实在Kubernetes中都是这种设计,万物皆可API化),它被定义在k8s.io/kubernetes/pkg/scheduler/apis/config包中。本文引用源码为kubernetes的release-1.21分支。KubeSchedul原创 2021-06-03 21:58:03 · 5488 阅读 · 0 评论 -
kube-scheduler的Scheduler解析
前言调度算法只对调度周期从PreFilter到Score扩展点进行抽象和实现,那么调度算法又是如何与其他扩展点配合实现Pod的调度呢?这就是本文重点解析的内容,kube-scheduler定义了Scheduler类型,它实现了调度Pod的全流程。本文引用源码为kubernetes的release-1.21分支。SchedulerScheduler定义Scheduler要想实现调度一个Pod的全流程,那么必须有调度队列、调度缓存、调度框架、调度插件、调度算法等模块的支持。所以,Schedu原创 2021-06-01 21:30:05 · 3596 阅读 · 0 评论 -
kube-scheduler的ScheduleAlgorithm解析
前言调度框架和调度插件将调度流程抽象为若干的阶段,每个阶段称之为一个扩展点,也就是用户可以在每个阶段扩展自定义的调度插件。由于调度框架和调度插件相对比较复杂,如果将调度视为一种接口(interface),那么输入应该是一个Pod和全量的Node,输出是为Pod分配的节点。至于接口的使用者就可以弱化调度框架和调度插件的概念,这是一种友好且通用的抽象。再者,Pod.Spec.SchedulerName可以选择调度框架来调度该Pod,虽然不同的Pod的调度框架有所不同,但是调用调度插件的流程大部分都是一致原创 2021-06-01 21:21:54 · 3172 阅读 · 0 评论 -
kube-scheduler的EventHandlers解析
前言笔者已经在调度队列、调度框架、调度插件、调度缓存以及调度扩展器等文章中解析了kube-scheduler基本的调度原理与实现,但是有没有发现几个问题?需要调度的Pod是怎么进入调度队列的? 调度完成的Pod是如何被更新到调度缓存的? Node的上线、下线等状态更新是如何更新到调度缓存的? 调度插件依赖的各种资源(比如PV)是如何影响调度的?只有解答了以上问题后,才能把kube-scheduler各个功能模块串接起来,形成闭环。本文的目标就是解析kube-scheduler是如何感知调度依原创 2021-05-31 22:12:26 · 3257 阅读 · 0 评论 -
kube-scheduler的Extender解析
前言kube-scheduler基于Kubernetes管理的资源(比如CPU、内存、PV等)进行调度,但是,当需要对在Kubernetes外部管理的资源进行调度时,在Extender之前没有任何机制可以做到这一点。有一种方法可以让kubernetes具有扩展性,就是增加HTTP调度扩展程序。有三种方法可以向kube-scheduler添加新的调度规则:更新现有的或添加新的调度插件并重新编译,这个在调度插件和调度框架可以找到答案; 开发一个自定义的kube-scheduler,该进程可代替标准原创 2021-05-31 22:00:13 · 4284 阅读 · 0 评论 -
client-go(kuberenetes)的RestClient解析
前言apiserver的REST客户端可以类比为http.Client,至少它继承了http.Client的功能(更准确的说应该是有一个http.Client的成员变量),如果读者对http.Client不了解,那么建议先简单学习一下,这非常有助于理解本文的内容。为了区分apiserver的REST客户端和http.Client,本文将用RestClient表示apiserver的REST客户端,而http.Client则直接引用齐全名。因为apiserver是一个相对标准的REST服务,所以访问a原创 2021-04-10 10:20:48 · 3628 阅读 · 0 评论 -
kube-scheduler的WaitingPod解析
前言本文的等待Pod不是调度队列中等待调度的Pod,在调度队列中的Pod类型是PodInfo。本文的等待Pod是在调度插件中PermitPlugin返回等待的Pod,虽然当前没有PermitPlugin的实现,但这不影响我们理解kube-scheduler如何处理多个插件同时返回等待的情况。毕竟有任何插件返回拒绝,Pod就会返回调度队列,全部返回批准,Pod就会进入绑定周期,所以kube-scheduler需要管理至少一个PermitPlugin返回等待并且其他PermitPlugin都返回批准的Pod原创 2021-04-01 22:25:18 · 2969 阅读 · 0 评论 -
Controller(Kubernetes)的ControllerRefManager解析
前言名词解释中已经解释了什么是Controller,那么ControllerRef就是对Controller的引用。在单进程编程中引用一般等同于指针(指针是对象的唯一标识),但是分布式系统中引用一般是对象的唯一键,这个唯一键可能是多维度的(以K8S为例:NS、Name、Kind等)。ControllerRefManager从名词上理解就是管理对象的Controller引用,而本文的Controller指的是对象的父对象(Owner),所以ControllerRefManager用来管理对象的Onwer引原创 2021-03-31 22:21:46 · 3320 阅读 · 1 评论 -
Controller(Kubernetes)的ControllerExpectations解析
前言本文涉及的部分名词参看名词解释,此处还要强调两个概念:Controller和Controllee,在本文其实二者是同一个意思,代表XxxController(比如DeploymentController)管理的Xxx(比如Deployment)对象。ControllerExpectations可以看做是XxxExpectations,只是各种Xxx的Expectations接口是相同的,就用ControllerExpectations统一实现了。要想理解Kubernetes的Controller原创 2021-03-28 13:47:42 · 4132 阅读 · 2 评论 -
Controller(Kubernetes)的PodControl解析
前言阅读本文前请参看名词解释。PodControl是XxxController操作Pod的接口,比如ReplicaSetController创建、删除Pod。熟悉Clientset的读者肯定会质疑有必要再定义接口来操作Pod么?直接用Clientset提供的接口不就可以了么?答案肯定是有必要的,否则笔者就没必要介绍它了。因为很多Controller的子对象都是Pod,比如Job、Deamonset、ReplicaSet等等。这些Controller对于Pod都有类似的操作,比如设置Pod的拥有者(这原创 2021-03-28 07:41:25 · 4024 阅读 · 1 评论 -
kube-scheduler的Framework解析
前言在阅读本文之前,建议先看看调度框架官方文档和调度框架设提案,也有必要先看看调度插件,便于理解本文内容。本文提取以官方文档中笔者认为比较重要的信息,并做了批注:kubernetes-scheduler已添加了许多功能,这使得代码越来越大,逻辑也越来越复杂。一个复杂的调度程序很难维护,其错误也很难找到和修复,并且那些自己修改调度程序的用户很难赶上并集成新的版本更新。当前kube-scheduler提供了webhooks来扩展器功能(Extender),但是能力有限。调度器功能越来越复杂,很难维护原创 2021-03-20 09:42:13 · 5652 阅读 · 0 评论 -
kube-scheduler的Plugin解析
前言下图是维基百科关于Plug-in (computing)示例插件框架,关于插件机制实现的原理不了解的读者可以看看,本文不赘述了。但是上图中几个知识点本文会提及,所以此处重点说明一下:宿主应用(Host Application): kube-scheduler就是宿主应用,因为所有插件都是给kube-scheduler使用的。 插件管理器(Plugin Manager): 原理上讲Scheduling Profile(后文会有介绍)充当了插件管理器的角色,因为它可以配置使能/禁止插件的.原创 2021-03-14 16:17:04 · 8306 阅读 · 1 评论 -
SharedIndexInformer(k8s client-go)的Controller解析
前言Controller,中文翻译是控制器。本文的Controller是SharedIndexInformer的控制器,不是kube-controller-manager的控制器,所以千万不要搞混概念,虽然他们都叫控制器。既然叫控制器,那么它控制什么呢?还记得这个经典的图片么?Controller就是负责从Reflector接手Deltas并发送到DeltaFIFO的过程,看起来确实控制了Deltas的流动。此图中红色的controller是kube-controller,不是本文的Cont原创 2021-03-06 17:00:03 · 8880 阅读 · 2 评论 -
client-go(kubernetes)的ListerWatcher解析
前言ListerWatcher是Lister和Watcher的结合体,前者负责列举全量对象,后者负责监视(本文将watch翻译为监视)对象的增量变化。为什么要有这个接口?原因很简单,提交访问效率。众所周知,kubernetes所有API对象都存储在etcd中,并只能通过apiserver访问。如果很多客户端频繁的列举全量对象(比如列举所有的Pod),这会造成apiserver不堪重负。那么如果在客户端做本地缓存如何?至少在没有任何状态变化的情况下只需要读取本地缓存即可,效率提升显而易见。通过列举全量对象原创 2021-03-04 22:27:40 · 10686 阅读 · 1 评论 -
kube-scheduler的PodNominator解析
前言笔者在《kube-scheduler的SchedulingQueue解析》的文章中提到了PodNominator,因为调度队列继承了PodNominator,但是当时为了避免不必要的内容扩展,并没有对PodNominator做任何说明。本文将对PodNominator做较全面的解析,从它的定义、实现直到在kube-scheduler中的应用。本文采用的Kubenetes源码的release-1.20分支。PodNominator的定义首先需要了解PodNominator到底是干啥的,英文原创 2021-02-23 20:01:30 · 11456 阅读 · 1 评论 -
chan(golang)的N种玩法
调用一次以上就panic一个稍微大一点的工程,初始化函数和反初始化函数一遍只允许调用一次,调动超过一次可能会造成不可想象的问题。处于简单考虑,此时只要调用超过一次以上就panic。实现这个功能非常用chan非常容易,如下代码所示:// 定义一个只调用一次的变量var once = make(chan struct{})// 以全局只能关闭一次为例func Close() { // 在执行关闭前先关闭chan,因为chan关闭两次就会panic close(once)}原创 2021-02-22 20:04:47 · 11589 阅读 · 0 评论 -
kube-scheduler的Cache解析
前言在阅读本文之前,建议从《kube-scheduler的SchedulingQueue解析》开始,因为笔者是以调度队列为突破口开始逐步深入的解析kube-scheduler的源码实现。在《kube-scheduler的SchedulingQueue解析》已经总结了,调度队列(SchedulingQueue)中都是Pending状态的Pod,也就是为调度的Pod。而本文分析的Cache中都是已经调度的Pod(更准确的说。。。),Cache是kube-scheduler的调度状态。Cache//原创 2021-01-31 17:55:41 · 16764 阅读 · 1 评论 -
kube-scheduler的SchedulingQueue解析
前言到今天为止,笔者从事集群调度领域大约有7年多。突然想看看kubernetes的调度器是如何实现的,主要还是抱着学习的态度,看看kubernetes的调度实现在自己的工作中是否有可借鉴的地方。调度设计一般缺少不了队列的设计,好的队列设计会让调度事半功倍。所以本文以调度队列为突破口,研究调度队列的设计与实现,为后续深入理解调度器的实现做准备。理解调度队列的设计,多半都能推导出调度器的实现,因为调度器的本质就是从队列中取出、决策(放置)然后再送到另一个队列的过程。有一点读者需要知道,虽然kuber原创 2020-12-29 18:19:52 · 16073 阅读 · 2 评论 -
konfig:采用ConfigMap实现线上配置热更新
前言利用kubernetes部署应用越来越流行,而运行在kubernetes中的服务需要的各种各样的配置如何才能实现热更新?难道需要在kubernetes中再部署zookeeper或者etcd之类的服务么?本文采用的方案是利用ConfigMap作为服务配置的持久化方案,并利用kubernetes提供的watch能力主动发现ConfigMap更新并及时更新到服务的配置中。这样运维人员只需要利用kubernetes的控制台(cli或者web)修改线上服务的配置,比如修改日志等级、降级、调整阈值等等。本文原创 2020-12-05 08:50:30 · 15667 阅读 · 0 评论 -
NestedMap:一个可以无限嵌套的Map
1.概述NestedMap是在sync.Map基础上实现的无限嵌套(递归)的Map,由于sync.Map天生的协程安全,使用NestedMap时不用考虑锁的问题。NestedMap应用面还是比较广泛的,比如对大量的对象进行分类管理。以笔者从事的集群调度领域为例,一个综合性的scheduler管理多个类型的大量worker,一般两层(根节点除外)的Map:第一层是按照worker类型分类,第二层是每个分类的worker集群。笔者在介绍concurrent.Map的文章中专门剖析过sync.Map,其中原创 2020-12-01 20:07:32 · 15086 阅读 · 0 评论 -
concurrent.Map:扩展sync.Map
expunged的意思就是map中这个key已删除,它与nil意义不同,nil表示value被删除,但是key还是可以复用的,而expunged表示key也被删除了。举一个例子,当调用sync.Map.Delete()删除某个键值对的时候,如果这个键值对也在readOnly里,那么该键的entry.p被设置为nil表示value被删除;但是此时再调用sync.Map.Store(),因为readOnly里key已经存在,所以直接设置entry.p即可,这样就可以避免再write-on-copy。这又是syn原创 2020-08-17 23:11:55 · 14959 阅读 · 0 评论 -
利⽤⽆锁队列实现的协程池,简约⽽不简单
前言众所周知,golang协程的创建、销毁、调度是非常轻量的,但是即便再轻量,规模大了开销也不能忽视的。比如利用协程处理http请求,每个请求用一个协程处理,当QPS上万的时候,资源消耗还是比较大的。协程池和线程池一样,池子中都是热协程,需要的时候取出来,用完后归还,避免了高频率的创建和销毁。同时协程池还能将空闲超时的协程销毁来释放资源,并且还有一定保护能力,通过设定协程最大数量避免无休止的创建协程把系统资源消耗殆尽。总之,golang虽然提供了非常轻量且容易使用的协程编程环境,但是不同的应用场原创 2020-05-20 22:14:16 · 14717 阅读 · 0 评论 -
站在巨人的肩膀上-像kubernetes一样用etcd存储自定义对象
背景众所周知,kubernetes利用etcd存储API对象,例如Pod、Deployment、StatefulSet等等。笔者认为kubernetes这种API对象的设计方案当前来看非常先进,基于etcd实现对象存储是这个设计方案的关键基础。笔者和很多读者都有这样一些需求:自己设计的系统也希望采用etcd; 系统也想采用kubernetes设计的API对象思想,这些对象是为系统设计的,...原创 2019-10-18 22:51:10 · 15526 阅读 · 7 评论 -
深入浅出kubernetes之client-go的DeltaFIFO
记得大学刚毕业那年看了侯俊杰的《深入浅出MFC》,就对深入浅出这四个字特别偏好,并且成为了自己对技术的要求标准——对于技术的理解要足够的深刻以至于可以用很浅显的道理给别人讲明白。以下内容为个人见解,如有雷同,纯属巧合,如有错误,烦请指正。本文基于kubernetes1.11版本,后续会根据kubernetes版本更新及时更新文档,所有代码引用为了简洁都去掉了日志打印相关的代码,尽量只保留有价值...原创 2018-08-14 18:08:13 · 20882 阅读 · 2 评论 -
深入浅出kubernetes之client-go的SharedInformer
记得大学刚毕业那年看了侯俊杰的《深入浅出MFC》,就对深入浅出这四个字特别偏好,并且成为了自己对技术的要求标准——对于技术的理解要足够的深刻以至于可以用很浅显的道理给别人讲明白。以下内容为个人见解,如有雷同,纯属巧合,如有错误,烦请指正。本文基于kubernetes1.11版本,后续会根据kubernetes版本更新及时更新文档,所有代码引用为了简洁都去掉了日志打印相关的代码,尽量只保留有价值...原创 2018-08-22 16:35:34 · 15986 阅读 · 14 评论 -
深入浅出kubernetes之client-go的workqueue
记得大学刚毕业那年看了侯俊杰的《深入浅出MFC》,就对深入浅出这四个字特别偏好,并且成为了自己对技术的要求标准——对于技术的理解要足够的深刻以至于可以用很浅显的道理给别人讲明白。以下内容为个人见解,如有雷同,纯属巧合,如有错误,烦请指正。本文基于kubernetes1.11版本,后续会根据kubernetes版本更新及时更新文档,所有代码引用为了简洁都去掉了日志打印相关的代码,尽量只保留有价值...原创 2018-08-08 18:36:53 · 23494 阅读 · 6 评论 -
深入浅出prometheus之服务发现(sd)
记得大学刚毕业那年看了侯俊杰的《深入浅出MFC》,就对深入浅出这四个字特别偏好,并且成为了自己对技术的要求标准——对于技术的理解要足够的深刻以至于可以用很浅显的道理给别人讲明白。以下内容为个人见解,如有雷同,纯属巧合,如有错误,烦请指正。本文基于prometheus2.3版本,后续会根据prometheus版本更新及时更新文档,所有代码引用为了简洁都去掉了日志打印相关的代码,尽量只保留有价值的...原创 2018-08-07 11:31:00 · 13865 阅读 · 3 评论 -
深入浅出kubernetes之client-go的Indexer
记得大学刚毕业那年看了侯俊杰的《深入浅出MFC》,就对深入浅出这四个字特别偏好,并且成为了自己对技术的要求标准——对于技术的理解要足够的深刻以至于可以用很浅显的道理给别人讲明白。以下内容为个人见解,如有雷同,纯属巧合,如有错误,烦请指正。本文基于kubernetes1.11版本,后续会根据kubernetes版本更新及时更新文档,所有代码引用为了简洁都去掉了日志打印相关的代码,尽量只保留有价值...原创 2018-08-10 13:48:21 · 14975 阅读 · 8 评论 -
深入浅出golang的chan
记得大学刚毕业那年看了侯俊杰的《深入浅出MFC》,就对深入浅出这四个字特别偏好,并且成为了自己对技术的要求标准——对于技术的理解要足够的深刻以至于可以用很浅显的道理给别人讲明白。以下内容为个人见解,如有雷同,纯属巧合,如有错误,烦请指正。今天,我们聊一聊go语言中chan,在开始我们话题之前,我们先看看官方对于chan的介绍(其中斜体为原文拷贝,没有任何加工):A channel prov...原创 2018-07-31 14:36:52 · 20116 阅读 · 6 评论 -
快排的golang实现
今天想试试自己的golang功底,所以想用go实现各种快排,假设我们的测试例子是这样的:// 测试代码import ( "fmt" "math/rand")func main() { // 测试数据随机产生100以内的10个数 data := []int{} for i := 0; i < 10; i++ { data = ...原创 2018-08-19 00:05:49 · 18216 阅读 · 1 评论 -
golang的chan有趣用法
写这个博客的背景是我面试一家公司,这家公司的CTO给我出了一道我认为挺有意思的题,题的大概是这样的:// 抽象一个栅栏type Barrier interface { Wait ()}// 创建栅栏对象func NewBarrier (n int) Barrier { }// 栅栏的实现类type barrier struct {}// 测试代码func ...原创 2018-08-17 11:16:19 · 14409 阅读 · 9 评论 -
深入浅出kubernetes之client-go的SharedInformerFactory
记得大学刚毕业那年看了侯俊杰的《深入浅出MFC》,就对深入浅出这四个字特别偏好,并且成为了自己对技术的要求标准——对于技术的理解要足够的深刻以至于可以用很浅显的道理给别人讲明白。以下内容为个人见解,如有雷同,纯属巧合,如有错误,烦请指正。本文基于kubernetes1.11版本,后续会根据kubernetes版本更新及时更新文档,所有代码引用为了简洁都去掉了日志打印相关的代码,尽量只保留有价值...原创 2018-08-27 17:39:38 · 23911 阅读 · 2 评论 -
golang的“双向继承”让编程更优雅
1.背景笔者开发⼀套分布式系统的时候,在管理端实现了raft算法来避免整个系统的单点故障,整个系统的⼤致描述如下:管理端的所有节点状态是⼀致的,所以⽤peer定义管理端节点是⽐较贴切的; 在管理端所有节点中选举出了⼀个leader,所有跟系统管理相关的决策都是由leader发出,peer同步leader的决策,这样所有的peer状态是⼀致的,当leader所在的peer异常,重新选举出...原创 2019-07-29 23:26:42 · 14789 阅读 · 0 评论 -
etcd的raft实现之tracker&quorum
1.前言在阅读本文之前请现阅读《etcd的raft实现之log》,笔者的etcd的raft系列通过一个点(就是log)进行展开,能够让读者比较容易的理解etcd的raft实现,解决读者无从下手的难题。在开始分析之前,先做一些名词解释,在《etcd的raft实现之log》中提到的概念本文就不在重复了:Peer:原意是同龄人或者同辈份的人,在raft中是参与选举和投票的节点,寓意raft节...原创 2019-08-24 20:16:50 · 16486 阅读 · 1 评论