kubelet 介绍
一、kubelet简介
kubelet 的主要功能就是定时从某个地方获取节点上 pod/container 的期望状态(运行什么容器、运行的副本数量、网络或者存储如何配置等等),并调用对应的容器平台接口达到这个状态。
之所以有pod的概览,即给容器提供这一层封装,主要是因为容器推荐的用法是里面只运行一个进程,而一般情况下某个应用都由多个组件构成的。
比较经典的一张图:
Kubelet组件运行在Node节点上,维持运行中的Pods以及提供kubernetes运行时环境,主要完成以下使命:
1.监视分配给该Node节点的pods
2.挂载pod所需要的volumes
3.下载pod的secret
4.通过docker/rkt来运行pod中的容器
5.调用cni接口为pod创建ip、路由
6.周期的执行pod中为容器定义的liveness探针
7.上报pod的状态给系统的其他组件
8.上报Node的状态
二、kubelet功能模块
在 v1.12 中,kubelet 组件有18个主要的 manager(kubernetes/pkg/kubelet/kubelet.go):
certificateManager
cgroupManager
containerManager
cpuManager
nodeContainerManager
configmapManager
containerReferenceManager
evictionManager
nvidiaGpuManager
imageGCManager
kuberuntimeManager
hostportManager
podManager
proberManager
secretManager
statusManager
volumeManager
tokenManager
比较好的一张图:
整个kubelet可以按照上图所示的模块进行划分,模块之间相互配合完成Kubelet的所有功能.下面对上图中的模块进行简要的介绍.
Kubelet对外暴露的端口,通过该端口可以获取到kubelet的状态
10250 kubelet API –kublet暴露出来的端口,通过该端口可以访问获取node资源以及状态,另外可以配合kubelet的启动参数contention-profiling enable-debugging-handlers来提供了用于调试和profiling的api。
4194 cAdvisor –kublet通过该端口可以获取到本node节点的环境信息以及node上运行的容器的状态等内容
10255 readonly API –kubelet暴露出来的只读端口,访问该端口不需要认证和鉴权,该http server提供查询资源以及状态的能力.
10248 /healthz –kubelet健康检查,通过访问该url可以判断Kubelet是否正常work, 通过kubelet的启动参数–healthz-port –healthz-bind-address来指定监听的地址和端口.
核心功能模块
PLEG
PLEG全称为PodLifecycleEvent,PLEG会一直调用container runtime获取本节点的pods,之后比较本模块中之前缓存的pods信息,比较最新的pods中的容器的状态是否发生改变,当状态发生切换的时候,生成一个eventRecord事件,输出到eventChannel中。syncPod模块会接收到eventChannel中的event事件,来触发pod同步处理过程,调用contaiener runtime来重建pod,保证pod工作正常.
cAdvisor
cAdvisor集成在kubelet中,起到收集本Node的节点和启动的容器的监控的信息,启动一个Http Server服务器,对外接收rest api请求.cAvisor模块对外提供了interface接口,可以通过interface接口获取到node节点信息,本地文件系统的状态等信息,该接口被imageManager,OOMWatcher,containerManager等所使用
GPUManager
对于Node上可使用的GPU的管理,当前版本需要在kubelet启动参数中指定feature-gates中添加Accelerators=true,并且需要才用runtime=Docker的情况下才能支持使用GPU,并且当前只支持NvidiaGPU,GPUManager主要需要实现interface定义的Start()/Capacity()/AllocateGPU()三个函数
OOMWatcher
系统OOM的监听器,将会与cadvisor模块之间建立SystemOOM,通过Watch方式从cadvisor那里收到的OOM信号,并发生相关事件
ProbeManager
探针管理,依赖于statusManager,livenessManager,containerRefManager,实现Pod的健康检查的功能.当前支持两种类型的探针:LivenessProbe和ReadinessProbe,
LivenessProbe:用于判断容器是否存活,如果探测到容器不健康,则kubelet将杀掉该容器,并根据容器的重启策略做相应的处理
ReadinessProbe: 用于判断容器是否启动完成
探针有三种实现方式
execprobe:在容器内部执行一个命令,如果命令返回码为0,则表明容器健康
tcprobe:通过容器的IP地址和端口号执行TCP检查,如果能够建立TCP连接,则表明容器健康
httprobe:通过容器的IP地址,端口号以及路径调用http Get方法,如果响应status>=200 && status<=400的时候,则认为容器状态健康
StatusManager
该模块负责pod里面的容器的状态,接受从其它模块发送过来的pod状态改变的事件,进行处理,并更新到kube-apiserver中.
Container/RefManager
容器引用的管理,相对简单的Manager,通过定义map来实现了containerID与v1.ObjectReferece容器引用的映射.
EvictionManager
evictManager当node的节点资源不足的时候,达到了配置的evict的策略,将会从node上驱赶pod,来保证node节点的稳定性.可以通过kubelet启动参数来决定evict的策略.另外当node的内存以及disk资源达到evict的策略的时候会生成对应的node状态记录.
ImageGC
imageGC负责Node节点的镜像回收,当本地的存放镜像的本地磁盘空间达到某阈值的时候,会触发镜像的回收,删除掉不被pod所使用的镜像.回收镜像的阈值可以通过kubelet的启动参数来设置.
ContainerGC
containerGC负责NOde节点上的dead状态的container,自动清理掉node上残留的容器.具体的GC操作由runtime来实现.
ImageManager
调用kubecontainer.ImageService提供的PullImage/GetImageRef/ListImages/RemoveImage/ImageStates的方法来保证pod运行所需要的镜像,主要是为了kubelet支持cni.
VolumeManager
负责node节点上pod所使用的volume的管理.主要涉及如下功能
Volume状态的同步,模块中会启动gorountine去获取当前node上volume的状态信息以及期望的volume的状态信息,会去周期性的sync volume的状态,另外volume与pod的生命周期关联,pod的创建删除过程中volume的attach/detach流程.更重要的是kubernetes支持多种存储的插件,kubelet如何调用这些存储插件提供的interface.涉及的内容较多,更加详细的信息可以看kubernetes中volume相关的代码和文档.
containerManager
负责node节点上运行的容器的cgroup配置信息,kubelet启动参数如果指定–cgroupPerQos的时候,kubelet会启动gorountie来周期性的更新pod的cgroup信息,维持其正确.实现了pod的Guaranteed/BestEffort/Burstable(BestEffort:POD中的所有容器都没有指定CPU和内存的requests和limits,默认为0,Burstable:POD中只要有一个容器,这个容器requests和limits的设置同其他容器设置的不一致,requests < limits, Guaranteed:POD中所有容器都必须统一设置了limits,并且设置参数都一致,如果有一个容器要设置requests,那么所有容器都要设置,并设置参数同limits一致,requests = limits. )三种级别的Qos,通过配置kubelet可以有效的保证了当有大量pod在node上运行时,保证node节点的稳定性.
runtimeManager
containerRuntime负责kubelet与不同的runtime实现进行对接,实现对于底层container的操作,初始化之后得到的runtime实例将会被之前描述的组件所使用.
当前可以通过kubelet的启动参数–container-runtime来定义是使用docker还是rkt.runtime需要实现的接口定义在src/k8s.io/kubernetes/pkg/kubelet/apis/cri/services.go文件里面
podManager
podManager提供了接口来存储和访问pod的信息,维持static pod和mirror pods的关系,提供的接口如下所示
跟其他Manager之间的关系,podManager会被statusManager/volumeManager/runtimeManager所调用,并且podManager的接口处理流程里面同样会调用secretManager以及configMapManager.
三、Cgroups介绍
Cgroups是control groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如:cpu,memory,IO等等)的机制。跟容器相关的功能主要涉及以下
· 限制进程组可以使用的资源数量(Resource limiting)。比如:memory子系统可以为进程组设定一个memory使用上限,一旦进程组使用的内存达到限额再申请内存,就会出发OOM(out of memory)。
· 进程组的优先级控制(Prioritization)。比如:可以使用cpu子系统为某个进程组分配特定cpu share。
· 记录进程组使用的资源数量(Accounting)。比如:可以使用cpuacct子系统记录某个进程组使用的cpu时间。
· 进程组隔离(Isolation)。比如:使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间。
Limits/request
Request: 容器使用的最小资源需求,作为容器调度时资源分配的判断依赖。只有当节点上可分配资源量>=容器资源请求数时才允许将容器调度到该节点。但Request参数不限制容器的最大可使用资源。
Limit: 容器能使用资源的资源的最大值,设置为0表示使用资源无上限。
当前可以设置的有memory/cpu, kubernetes版本增加了localStorage在1.8版本中的策略.
Pod Qos
Qos服务质量分成三个级别
BestEffort、Burstable、Guaranteed
Kuberntes管理的node资源中cpu为可压缩资源,当node上运行的pod cpu负载较高的时候,出现资源抢占,会根据设置的limit值来分配时间片.Kubernetes管理的node资源memory/disk是不可压缩资源,当出现资源抢占的时候,会killer方式来释放pod所占用的内存以及disk资源.当非可压缩资源出现不足的时候,kill掉pods的Qos优先级比较低的pods.通过OOM score来实现,Guaranteed pod,OOM_ADJ设置为-998, BestEffort 设置的OOM_ADJ为1000, Burstable级别的POD设置为2-999.
Evict策略
当系统资源不足的时候,kubelet会通过evict策略来驱逐本节点的pod来使得node节点的负载不是很高, 保证系统组件的稳定性.
当前支持的驱逐信号Eviction Signal为
memory.available
nodefs.available
nodefs.inodesFree
imagefs.available
imagefs.inodesFree
四、节点资源介绍
Node Capacity - 已经作为NodeStatus.Capacity提供,这是从节点实例读取的总容量,并假定为常量。
System-Reserved- 为未由Kubernetes管理的流程预留计算资源。目前,这涵盖了/系统原始容器中集中的所有进程。
Kubelet Allocatable - 计算可用于调度的资源(包括计划和非计划资源)。这个价值是这个提案的重点。
Kube-Reserved - 为诸如docker守护进程,kubelet,kube代理等的Kubernetes组件预留的计算资源。
可分配的资源数据将由Kubelet计算并报告给API服务器。它被定义为:
[Allocatable] = [Node Capacity] - [Kube-Reserved] – [System-Reserved] – [Hard-Eviction-Threshold]
其中Kube-Reserved、System-Reserved和Hard-Eviction-Threshold可以看kubelet的配置信息。
调度pod时,调度程序将使用Allocatable代替Capacity,Kubelet将在执行准入检查Admission checks时使用它。
五、静态static pod
静态POD直接由某个节点上的kubelet程序进行管理,不需要api server介入,静态POD也不需要关联任何RC,完全是由kubelet程序来监控,当kubelet发现静态POD停止掉的时候,重新启动静态POD。
EvictManager模块在系统资源紧张的时候, 根据pod的Qos以及pod使用的资源会选择本节点的pod killer,来释放资源, 但是静态pod被killer之后,并不会发生重启的现象, 设置pod的yaml中定义加入如下内容,
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
并且kubelet的启动参数打开feature gateway(–feature-gates=ExperimentalCriticalPodAnnotation=true).