自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(58)
  • 收藏
  • 关注

原创 Kubernetes API的流编解码器StreamSerializer

从数据流中读取数据并解码API对象的解码器本文命名为流解码器,我们日常说的流是字节流,那么流解码器可以看做是API对象流,每调用一次返回一个API对象。如果想把字节流变成API对象流,首先需要将字节流变成json/yaml/protobuf序列化格式对象流,即先从字节流中读取一个一个的json/yaml/protobuf对象。然后再用解码器将json/yaml/protobuf对象解码成API对象就完成了。...

2022-07-02 11:59:40 589 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 675

原创 Kubespray离线安装Kubernetes的几种方法

kubespray推荐的方法kubespray离线安装kubernetes需要在内网搭建文件服务器、镜像仓库、包源以及按需的PyPi服务器和Helm仓库,本质上与在线安装没什么区别,只是将下载文件、镜像、包的地址覆盖为内部地址。这种方法比较正规,适用于绝大部分场景。使用cache这是利用kubespray的缓存机制实现的离线安装方法。首先需要在一个可以访问互联网的环境配置download_run_once=true部署一个最小集群,从而在ansible节点获得所需的所有文件和镜像的缓存。然后再将

2022-02-21 23:02:05 2127 1

原创 通过部署学习Kubernetes之关闭交换空间

前言Kubernetes从1.8版本之后必须关闭系统交换空间,否则将不能工作(kubelet)。本文将通过kubespray源码分析如何关闭系统交换空间,更重要的是分析为什么要关闭交换空间。本文引用源码为kubespray:v2.18.0版本,操作系统类型只针对CentOS做解析,其他发行版读者按需自行分析。关闭系统交换空间关闭系统交换空间是kubespray的一个role, 源码链接:kubespray/0010-swapoff.yml at v2.18.0 · kubernetes-si

2022-01-25 22:46:04 731

原创 Kubernetes的RecognizingDecoder解析

前言在Serializer文章中提到了,Serializer虽然抽象了序列化/反序列化的接口,但是反序列化不同格式的数据需要不同的Serializer对象,并不是很通用。有没有一种类型可以反序列化任意格式的数据呢?答案是有的,但是在介绍这个“万能解码器”之前,需要引入RecognizingDecoder接口。本文引用源码为kubernetes的release-1.21分支。RecognizingDecoder如果笔者自己实现“万能解码器”,我抽象一个接口用于判断解码器是否能够解码当前格式的数

2021-06-08 22:17:42 1999 1

原创 Kubernetes的Serializer解析

前言序列化和反序列化在很多项目中都有应用,Kubernetes也不例外。Kubernetes中定义了大量的API对象,为此还单独设计了一个包,方便多个模块引用。API对象在不同的模块之间传输(尤其是跨进程)可能会用到序列化与反序列化,不同的场景对于序列化个格式又不同,比如grpc协议用protobuf,用户交互用yaml(因为yaml可读性强),etcd存储用json。Kubernetes反序列化API对象不同于我们常用的json.Unmarshal()函数(需要传入对象指针),Kubernetes需要

2021-06-08 22:12:42 3725

原创 一张图看懂kube-scheduler

利用SharedIndedInformer过滤未调度的Pod放入调度队列 利用SharedIndexInformer过滤已调度的Pod更新调度缓存 从调度队列取出一个待调度的Pod,通过Pod.Spec.SchedulerName获取调度框架 调度框架是配置好的调度插件集合,既可以通过扩展调度插件的方式扩展调度能力,也可以通过调度扩展器 调度算法利用调度缓存的快照以及输入的调度框架,为Pod选择最优的节点 如果调度算法执行失败,将Pod放入调度队列的不可调度自队列;如果调度算法执行成功,通知调度缓

2021-06-07 21:38:03 2412

原创 kube-scheduler的Configurator解析

前言调度器配置中解析了kube-scheduler的各种配置,但是自始至终都没有看到如何根据配置构造调度器。虽然调度器文章中提到了构造函数,但是其核心实现是Configurator,本文将解析Configurator构造调度器的过程。虽然意义远没有调度队列、调度框架、调度插件等重大,但是对于了解调度器从生到死整个过程来说是必要一环,况且确实能学到点东西。ConfiguratorConfigurator定义Configurator类似于Scheduler的工厂,但是一般的工厂类很少会有这么多的

2021-06-07 21:30:09 2381

原创 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 5315

原创 kube-scheduler的Scheduler解析

前言调度算法只对调度周期从PreFilter到Score扩展点进行抽象和实现,那么调度算法又是如何与其他扩展点配合实现Pod的调度呢?这就是本文重点解析的内容,kube-scheduler定义了Scheduler类型,它实现了调度Pod的全流程。本文引用源码为kubernetes的release-1.21分支。SchedulerScheduler定义Scheduler要想实现调度一个Pod的全流程,那么必须有调度队列、调度缓存、调度框架、调度插件、调度算法等模块的支持。所以,Schedu

2021-06-01 21:30:05 3526

原创 kube-scheduler的ScheduleAlgorithm解析

前言调度框架和调度插件将调度流程抽象为若干的阶段,每个阶段称之为一个扩展点,也就是用户可以在每个阶段扩展自定义的调度插件。由于调度框架和调度插件相对比较复杂,如果将调度视为一种接口(interface),那么输入应该是一个Pod和全量的Node,输出是为Pod分配的节点。至于接口的使用者就可以弱化调度框架和调度插件的概念,这是一种友好且通用的抽象。再者,Pod.Spec.SchedulerName可以选择调度框架来调度该Pod,虽然不同的Pod的调度框架有所不同,但是调用调度插件的流程大部分都是一致

2021-06-01 21:21:54 3107

原创 kube-scheduler的EventHandlers解析

前言笔者已经在调度队列、调度框架、调度插件、调度缓存以及调度扩展器等文章中解析了kube-scheduler基本的调度原理与实现,但是有没有发现几个问题?需要调度的Pod是怎么进入调度队列的? 调度完成的Pod是如何被更新到调度缓存的? Node的上线、下线等状态更新是如何更新到调度缓存的? 调度插件依赖的各种资源(比如PV)是如何影响调度的?只有解答了以上问题后,才能把kube-scheduler各个功能模块串接起来,形成闭环。本文的目标就是解析kube-scheduler是如何感知调度依

2021-05-31 22:12:26 3207

原创 kube-scheduler的Extender解析

前言kube-scheduler基于Kubernetes管理的资源(比如CPU、内存、PV等)进行调度,但是,当需要对在Kubernetes外部管理的资源进行调度时,在Extender之前没有任何机制可以做到这一点。有一种方法可以让kubernetes具有扩展性,就是增加HTTP调度扩展程序。有三种方法可以向kube-scheduler添加新的调度规则:更新现有的或添加新的调度插件并重新编译,这个在调度插件和调度框架可以找到答案; 开发一个自定义的kube-scheduler,该进程可代替标准

2021-05-31 22:00:13 4164

原创 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 3550

原创 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 2936

原创 Controller(Kubernetes)的ControllerRefManager解析

前言名词解释中已经解释了什么是Controller,那么ControllerRef就是对Controller的引用。在单进程编程中引用一般等同于指针(指针是对象的唯一标识),但是分布式系统中引用一般是对象的唯一键,这个唯一键可能是多维度的(以K8S为例:NS、Name、Kind等)。ControllerRefManager从名词上理解就是管理对象的Controller引用,而本文的Controller指的是对象的父对象(Owner),所以ControllerRefManager用来管理对象的Onwer引

2021-03-31 22:21:46 3233 1

原创 Controller(Kubernetes)的ControllerExpectations解析

前言本文涉及的部分名词参看名词解释,此处还要强调两个概念:Controller和Controllee,在本文其实二者是同一个意思,代表XxxController(比如DeploymentController)管理的Xxx(比如Deployment)对象。ControllerExpectations可以看做是XxxExpectations,只是各种Xxx的Expectations接口是相同的,就用ControllerExpectations统一实现了。要想理解Kubernetes的Controller

2021-03-28 13:47:42 4081 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 3978 1

原创 kube-scheduler的Framework解析

前言在阅读本文之前,建议先看看调度框架官方文档和调度框架设提案,也有必要先看看调度插件,便于理解本文内容。本文提取以官方文档中笔者认为比较重要的信息,并做了批注:kubernetes-scheduler已添加了许多功能,这使得代码越来越大,逻辑也越来越复杂。一个复杂的调度程序很难维护,其错误也很难找到和修复,并且那些自己修改调度程序的用户很难赶上并集成新的版本更新。当前kube-scheduler提供了webhooks来扩展器功能(Extender),但是能力有限。调度器功能越来越复杂,很难维护

2021-03-20 09:42:13 5501

原创 kube-scheduler的Plugin解析

前言下图是维基百科关于Plug-in (computing)示例插件框架,关于插件机制实现的原理不了解的读者可以看看,本文不赘述了。但是上图中几个知识点本文会提及,所以此处重点说明一下:宿主应用(Host Application): kube-scheduler就是宿主应用,因为所有插件都是给kube-scheduler使用的。 插件管理器(Plugin Manager): 原理上讲Scheduling Profile(后文会有介绍)充当了插件管理器的角色,因为它可以配置使能/禁止插件的.

2021-03-14 16:17:04 8175 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 8828 2

原创 client-go(kubernetes)的ListerWatcher解析

前言ListerWatcher是Lister和Watcher的结合体,前者负责列举全量对象,后者负责监视(本文将watch翻译为监视)对象的增量变化。为什么要有这个接口?原因很简单,提交访问效率。众所周知,kubernetes所有API对象都存储在etcd中,并只能通过apiserver访问。如果很多客户端频繁的列举全量对象(比如列举所有的Pod),这会造成apiserver不堪重负。那么如果在客户端做本地缓存如何?至少在没有任何状态变化的情况下只需要读取本地缓存即可,效率提升显而易见。通过列举全量对象

2021-03-04 22:27:40 10590 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 11340 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 11542

原创 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 16656 1

原创 kube-scheduler的SchedulingQueue解析

前言到今天为止,笔者从事集群调度领域大约有7年多。突然想看看kubernetes的调度器是如何实现的,主要还是抱着学习的态度,看看kubernetes的调度实现在自己的工作中是否有可借鉴的地方。调度设计一般缺少不了队列的设计,好的队列设计会让调度事半功倍。所以本文以调度队列为突破口,研究调度队列的设计与实现,为后续深入理解调度器的实现做准备。理解调度队列的设计,多半都能推导出调度器的实现,因为调度器的本质就是从队列中取出、决策(放置)然后再送到另一个队列的过程。有一点读者需要知道,虽然kuber

2020-12-29 18:19:52 15950 2

原创 konfig:采用ConfigMap实现线上配置热更新

前言利用kubernetes部署应用越来越流行,而运行在kubernetes中的服务需要的各种各样的配置如何才能实现热更新?难道需要在kubernetes中再部署zookeeper或者etcd之类的服务么?本文采用的方案是利用ConfigMap作为服务配置的持久化方案,并利用kubernetes提供的watch能力主动发现ConfigMap更新并及时更新到服务的配置中。这样运维人员只需要利用kubernetes的控制台(cli或者web)修改线上服务的配置,比如修改日志等级、降级、调整阈值等等。本文

2020-12-05 08:50:30 15608

原创 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 14989

原创 Apollo:云规模计算的可扩展协同调度

摘要在云规模的计算群集上有效地调度数据并行计算作业对于作业性能、系统吞吐量和资源利用率至关重要。随着集群规模和具有各种特征的更复杂的workload的增长,这变得越来越具有挑战性。本文介绍了Apollo,这是一种高度可扩展协同调度框架,已部署到Microsoft的生产集群上,可每天高效地在数万台计算机上调度数以千计的计算(数百万个任务)。该框架通过松散协调的机制利用全局群集信息以分布式方式执行调度决策。每个调度决策都会考虑未来的资源可用性,并在一个统一的模型中一起优化各种性能和系统因素。Apollo具有

2020-08-30 15:04:48 15018

原创 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 14911

原创 Sparrow:分布式低延迟调度

1.摘要大型数据分析框架正在朝着缩短任务执行时间和提高并行度的方向发展来提供低延迟,任务调度器面临的主要挑战是在几百毫秒内完成高度并行的作业调度,这需要在合适的机器上每秒调度数百万个任务,同时提供毫秒级的延迟和高可用性。本文证明了去中心化、随机抽样方法可提供最佳性能,同时避免了中心化设计存在吞吐量和高可用的问题。本文在110台计算机集群上部署Sparrow,并证明Sparrow的性能与理想的调度程序的误差在12%以内。2.介绍当今的数据分析集群运行的时间越来越短,作业的任务越来越多。在对低延迟交

2020-06-05 23:24:42 15660

原创 利⽤⽆锁队列实现的协程池,简约⽽不简单

前言众所周知,golang协程的创建、销毁、调度是非常轻量的,但是即便再轻量,规模大了开销也不能忽视的。比如利用协程处理http请求,每个请求用一个协程处理,当QPS上万的时候,资源消耗还是比较大的。协程池和线程池一样,池子中都是热协程,需要的时候取出来,用完后归还,避免了高频率的创建和销毁。同时协程池还能将空闲超时的协程销毁来释放资源,并且还有一定保护能力,通过设定协程最大数量避免无休止的创建协程把系统资源消耗殆尽。总之,golang虽然提供了非常轻量且容易使用的协程编程环境,但是不同的应用场

2020-05-20 22:14:16 14686

原创 站在巨人的肩膀上-像kubernetes一样用etcd存储自定义对象

背景众所周知,kubernetes利用etcd存储API对象,例如Pod、Deployment、StatefulSet等等。笔者认为kubernetes这种API对象的设计方案当前来看非常先进,基于etcd实现对象存储是这个设计方案的关键基础。笔者和很多读者都有这样一些需求:自己设计的系统也希望采用etcd; 系统也想采用kubernetes设计的API对象思想,这些对象是为系统设计的,...

2019-10-18 22:51:10 15486 7

原创 深入剖析kubernetes的API对象类型定义

目录1.背景2.分析2.1api2.2metav12.2.1MetaType2.2.3ListMeta2.3runtime2.3.1schema2.3.2Object3.总结1.背景在初学kuberentes的时候,笔者作为码农就非常好奇它的代码实现。于是开始git clone代码,首先就被kuberentes的代码仓库搞蒙了,kuberent...

2019-10-14 22:53:09 20477 5

原创 etcd的raft实现之node

1.前言在阅读本文之前希望先阅读笔者的《etcd的raft实现之log》和《etcd的raft实现之tracker&quorum》,没有前两篇文章的背景知识,本文提到的一些概念可能难以理解。当然,如果读者已经有一定的相关知识可以直接略过。node给人第一个印象应该是raft节点功能的实现,其实并不是很准确。在笔者看来,node应该是raft的接口类,如果把raft看做一个库/包的话...

2019-09-19 23:43:54 15585

原创 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 16377 1

原创 etcd的raft实现之log

1.前言raft是什么我想应该不需要我过多解释,网上的文章也多如牛毛,raft的实现也不在少数,笔者唯独选择etcd这个实现版本,原因很简单:个人梦想开发一个分布式操作系统,这个分布式操作系统的核心需要一个高可靠、高性能的对象存储。etcd是一个非常优秀的项目,很多其他优秀的项目(比如kubernetes)都是基于etcd开发,所以我开始更深入的了解etcd。在开始本文正式内容之前,笔者现...

2019-08-21 23:43:04 17009 2

原创 golang的“双向继承”让编程更优雅

1.背景笔者开发⼀套分布式系统的时候,在管理端实现了raft算法来避免整个系统的单点故障,整个系统的⼤致描述如下:管理端的所有节点状态是⼀致的,所以⽤peer定义管理端节点是⽐较贴切的; 在管理端所有节点中选举出了⼀个leader,所有跟系统管理相关的决策都是由leader发出,peer同步leader的决策,这样所有的peer状态是⼀致的,当leader所在的peer异常,重新选举出...

2019-07-29 23:26:42 14746

原创 细节决定成败之C++成员变量、构造函数初始化顺序

笔试题class Runnable {protected: Runnable () : thread(NULL) { pthread_create(&thread, NULL, Runnable::Run, this); } ~Runnable () { if (NULL != thread) { // Destro...

2019-04-22 23:04:08 15207

翻译 一个去中心化的数据中心操作系统模型

目录前言3.一个去中心化的数据中心操作系统模型3.1定义和概念3.2要求3.2.1效率要求3.2.2安全要求3.2.3其他要求3.3分布式对象3.4资源命名3.5资源管理3.6永久存储3.7并发访问3.8总结前言本文是Malte Schwarzkopf的博士论文《Operating system support for warehouse...

2019-01-11 23:11:52 16374

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除