Kubernetes API的流编解码器StreamSerializer 从数据流中读取数据并解码API对象的解码器本文命名为流解码器,我们日常说的流是字节流,那么流解码器可以看做是API对象流,每调用一次返回一个API对象。如果想把字节流变成API对象流,首先需要将字节流变成json/yaml/protobuf序列化格式对象流,即先从字节流中读取一个一个的json/yaml/protobuf对象。然后再用解码器将json/yaml/protobuf对象解码成API对象就完成了。...
Kubernetes的NodeLifecycleController如何管理污点 需要强调的是,本文的污点指的是NoExecute污点,这种污点会驱逐已经运行的pod,这可以从NoExecute字面意思看的出来。《kube-scheduler调度插件》的TaintToleration在Filter阶段会过滤掉pod无法容忍的NoSchedule和NoExecute污点,也就是说调度器不会调度pod到无法容忍污点node上,那NodeLifecycleController管理还要管理NoExecute干什么呢?道理很简单,node的污点会更新,pod的容忍度也会更新,调度器不会因为no
Kubespray离线安装Kubernetes的几种方法 kubespray推荐的方法kubespray离线安装kubernetes需要在内网搭建文件服务器、镜像仓库、包源以及按需的PyPi服务器和Helm仓库,本质上与在线安装没什么区别,只是将下载文件、镜像、包的地址覆盖为内部地址。这种方法比较正规,适用于绝大部分场景。使用cache这是利用kubespray的缓存机制实现的离线安装方法。首先需要在一个可以访问互联网的环境配置download_run_once=true部署一个最小集群,从而在ansible节点获得所需的所有文件和镜像的缓存。然后再将
通过部署学习Kubernetes之关闭交换空间 前言Kubernetes从1.8版本之后必须关闭系统交换空间,否则将不能工作(kubelet)。本文将通过kubespray源码分析如何关闭系统交换空间,更重要的是分析为什么要关闭交换空间。本文引用源码为kubespray:v2.18.0版本,操作系统类型只针对CentOS做解析,其他发行版读者按需自行分析。关闭系统交换空间关闭系统交换空间是kubespray的一个role, 源码链接:kubespray/0010-swapoff.yml at v2.18.0 · kubernetes-si
Kubernetes的RecognizingDecoder解析 前言在Serializer文章中提到了,Serializer虽然抽象了序列化/反序列化的接口,但是反序列化不同格式的数据需要不同的Serializer对象,并不是很通用。有没有一种类型可以反序列化任意格式的数据呢?答案是有的,但是在介绍这个“万能解码器”之前,需要引入RecognizingDecoder接口。本文引用源码为kubernetes的release-1.21分支。RecognizingDecoder如果笔者自己实现“万能解码器”,我抽象一个接口用于判断解码器是否能够解码当前格式的数
Kubernetes的Serializer解析 前言序列化和反序列化在很多项目中都有应用,Kubernetes也不例外。Kubernetes中定义了大量的API对象,为此还单独设计了一个包,方便多个模块引用。API对象在不同的模块之间传输(尤其是跨进程)可能会用到序列化与反序列化,不同的场景对于序列化个格式又不同,比如grpc协议用protobuf,用户交互用yaml(因为yaml可读性强),etcd存储用json。Kubernetes反序列化API对象不同于我们常用的json.Unmarshal()函数(需要传入对象指针),Kubernetes需要
一张图看懂kube-scheduler 利用SharedIndedInformer过滤未调度的Pod放入调度队列 利用SharedIndexInformer过滤已调度的Pod更新调度缓存 从调度队列取出一个待调度的Pod,通过Pod.Spec.SchedulerName获取调度框架 调度框架是配置好的调度插件集合,既可以通过扩展调度插件的方式扩展调度能力,也可以通过调度扩展器 调度算法利用调度缓存的快照以及输入的调度框架,为Pod选择最优的节点 如果调度算法执行失败,将Pod放入调度队列的不可调度自队列;如果调度算法执行成功,通知调度缓
kube-scheduler的Configurator解析 前言调度器配置中解析了kube-scheduler的各种配置,但是自始至终都没有看到如何根据配置构造调度器。虽然调度器文章中提到了构造函数,但是其核心实现是Configurator,本文将解析Configurator构造调度器的过程。虽然意义远没有调度队列、调度框架、调度插件等重大,但是对于了解调度器从生到死整个过程来说是必要一环,况且确实能学到点东西。ConfiguratorConfigurator定义Configurator类似于Scheduler的工厂,但是一般的工厂类很少会有这么多的
KubeSchedulerConfiguration解析 前言kube-scheduler如何配置调度框架和调度插件中提到的插件(比如使能或禁止哪些插件?)?如何配置调度队列的排序函数以及退避时间?本文将详细解析kube-scheduler的配置,在kube-scheduler中,配置也是一种API对象(其实在Kubernetes中都是这种设计,万物皆可API化),它被定义在k8s.io/kubernetes/pkg/scheduler/apis/config包中。本文引用源码为kubernetes的release-1.21分支。KubeSchedul
kube-scheduler的Scheduler解析 前言调度算法只对调度周期从PreFilter到Score扩展点进行抽象和实现,那么调度算法又是如何与其他扩展点配合实现Pod的调度呢?这就是本文重点解析的内容,kube-scheduler定义了Scheduler类型,它实现了调度Pod的全流程。本文引用源码为kubernetes的release-1.21分支。SchedulerScheduler定义Scheduler要想实现调度一个Pod的全流程,那么必须有调度队列、调度缓存、调度框架、调度插件、调度算法等模块的支持。所以,Schedu
kube-scheduler的ScheduleAlgorithm解析 前言调度框架和调度插件将调度流程抽象为若干的阶段,每个阶段称之为一个扩展点,也就是用户可以在每个阶段扩展自定义的调度插件。由于调度框架和调度插件相对比较复杂,如果将调度视为一种接口(interface),那么输入应该是一个Pod和全量的Node,输出是为Pod分配的节点。至于接口的使用者就可以弱化调度框架和调度插件的概念,这是一种友好且通用的抽象。再者,Pod.Spec.SchedulerName可以选择调度框架来调度该Pod,虽然不同的Pod的调度框架有所不同,但是调用调度插件的流程大部分都是一致
kube-scheduler的EventHandlers解析 前言笔者已经在调度队列、调度框架、调度插件、调度缓存以及调度扩展器等文章中解析了kube-scheduler基本的调度原理与实现,但是有没有发现几个问题?需要调度的Pod是怎么进入调度队列的? 调度完成的Pod是如何被更新到调度缓存的? Node的上线、下线等状态更新是如何更新到调度缓存的? 调度插件依赖的各种资源(比如PV)是如何影响调度的?只有解答了以上问题后,才能把kube-scheduler各个功能模块串接起来,形成闭环。本文的目标就是解析kube-scheduler是如何感知调度依
kube-scheduler的Extender解析 前言kube-scheduler基于Kubernetes管理的资源(比如CPU、内存、PV等)进行调度,但是,当需要对在Kubernetes外部管理的资源进行调度时,在Extender之前没有任何机制可以做到这一点。有一种方法可以让kubernetes具有扩展性,就是增加HTTP调度扩展程序。有三种方法可以向kube-scheduler添加新的调度规则:更新现有的或添加新的调度插件并重新编译,这个在调度插件和调度框架可以找到答案; 开发一个自定义的kube-scheduler,该进程可代替标准
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
kube-scheduler的WaitingPod解析 前言本文的等待Pod不是调度队列中等待调度的Pod,在调度队列中的Pod类型是PodInfo。本文的等待Pod是在调度插件中PermitPlugin返回等待的Pod,虽然当前没有PermitPlugin的实现,但这不影响我们理解kube-scheduler如何处理多个插件同时返回等待的情况。毕竟有任何插件返回拒绝,Pod就会返回调度队列,全部返回批准,Pod就会进入绑定周期,所以kube-scheduler需要管理至少一个PermitPlugin返回等待并且其他PermitPlugin都返回批准的Pod
Controller(Kubernetes)的ControllerRefManager解析 前言名词解释中已经解释了什么是Controller,那么ControllerRef就是对Controller的引用。在单进程编程中引用一般等同于指针(指针是对象的唯一标识),但是分布式系统中引用一般是对象的唯一键,这个唯一键可能是多维度的(以K8S为例:NS、Name、Kind等)。ControllerRefManager从名词上理解就是管理对象的Controller引用,而本文的Controller指的是对象的父对象(Owner),所以ControllerRefManager用来管理对象的Onwer引
Controller(Kubernetes)的ControllerExpectations解析 前言本文涉及的部分名词参看名词解释,此处还要强调两个概念:Controller和Controllee,在本文其实二者是同一个意思,代表XxxController(比如DeploymentController)管理的Xxx(比如Deployment)对象。ControllerExpectations可以看做是XxxExpectations,只是各种Xxx的Expectations接口是相同的,就用ControllerExpectations统一实现了。要想理解Kubernetes的Controller
Controller(Kubernetes)的PodControl解析 前言阅读本文前请参看名词解释。PodControl是XxxController操作Pod的接口,比如ReplicaSetController创建、删除Pod。熟悉Clientset的读者肯定会质疑有必要再定义接口来操作Pod么?直接用Clientset提供的接口不就可以了么?答案肯定是有必要的,否则笔者就没必要介绍它了。因为很多Controller的子对象都是Pod,比如Job、Deamonset、ReplicaSet等等。这些Controller对于Pod都有类似的操作,比如设置Pod的拥有者(这
kube-scheduler的Framework解析 前言在阅读本文之前,建议先看看调度框架官方文档和调度框架设提案,也有必要先看看调度插件,便于理解本文内容。本文提取以官方文档中笔者认为比较重要的信息,并做了批注:kubernetes-scheduler已添加了许多功能,这使得代码越来越大,逻辑也越来越复杂。一个复杂的调度程序很难维护,其错误也很难找到和修复,并且那些自己修改调度程序的用户很难赶上并集成新的版本更新。当前kube-scheduler提供了webhooks来扩展器功能(Extender),但是能力有限。调度器功能越来越复杂,很难维护
kube-scheduler的Plugin解析 前言下图是维基百科关于Plug-in (computing)示例插件框架,关于插件机制实现的原理不了解的读者可以看看,本文不赘述了。但是上图中几个知识点本文会提及,所以此处重点说明一下:宿主应用(Host Application): kube-scheduler就是宿主应用,因为所有插件都是给kube-scheduler使用的。 插件管理器(Plugin Manager): 原理上讲Scheduling Profile(后文会有介绍)充当了插件管理器的角色,因为它可以配置使能/禁止插件的.