k8s 核心原理分析
本文内容
- API Server 原理分析
- Controller Manager原理分析
- Scheduler 调度器原理分析
- kubelet 运行机制分析
一. k8s API Server原理分析
1) API Server 作用:
- 集群内各模块间数据交互和通信的中心枢纽,是系统的"数据总线"
API Server提供k8s各类资源对象的增删改查以及Watch等http rest接口
2) API Server 功能特性:
- 集群管理的API入口
- 资源配额控制的入口
- 提供了完善的集群安全机制
API server进程运行在master节点上,命令行工具kubectl就是和API Server进行交互
3) k8s集群各个模块之间如何通信?
- 集群内各个功能模块通过API Server将信息存入etcd,当需要获取和操作这些数据时,则通过API Server提供的REST接口来实现,从而实现各模块之间的信息交互
模块间通信样例如下
kubelet进程与API Server的交互 :每个Node节点上的kubelet每隔一个时间周期,就会调用一次API Server的REST接口报告自身状态,API Server接收到这些信息后,将节点状态信息更新到etcd中
二. Controller Manager 原理分析
1) Controller Manager 作用
- 集群内部的管理控制中心
- 负责集群内部Node,Pod副本,服务端点,命名空间,服务账号,资源定额等的管理
当某个Node意外宕机时,Controller Manager会及时发现此故障并执行自动化修复流程,确保集群始终处于预期的工作状态
2) Controller Manager 结构
所属控制器 | 描述 |
---|---|
Replication Controller | 副本控制器 |
Node Controller | 节点控制器 |
ResourceQuota Controller | 资源控制器 |
Namespace Controller | 命名空间控制器 |
ServiceAccount Controller | 准入控制器 |
Token Controller | token控制器 |
Service Controller | 服务控制器 |
Endpoint Controller | 端点控制器 |
各控制器原理分析
1. Replication Controller
RC 简介
- 副本控制器,简称RC
- 作用就是确保集群中任何一个RC关联的Pod副本数量在任何时候保持预设值
Pod可以通过修改它的标签来脱离RC的控制
该方法可以用于将Pod从集群中迁移,数据修复等调试,对于一个被迁移的Pod副本,RC会创建一个新的Pod副本来替换被迁移的副本
RC 作用
- 重新调度:确保集群中不多不少,仅有N个Pod实例
- 弹性伸缩:修改spec.replicas属性,很容易扩大或缩小副本数量
- 滚动更新:逐个替换Pod的方式来辅助进行服务的滚动更新,这样即便在滚动更新的过程中发生了不可预料的错误,Pod集合的更新也都在可控的范围内
2. Node Controller
简介
- 节点控制器
- 通过 API Server 实时获取Node的相关信息,实现管理和监控集群中的各个Node节点的相关控制功能
kubelet 进程在启动时通过API Server注册自身的节点信息,并且定时向API Server汇报状态信息,API Server接受到这些信息后,将这些信息存储到etcd中
节点的健康状态包括:就绪,未就绪,未知
3. ResourceQuota Controller
简介
- 资源配额管理器
- 确保指定的资源对象在任何时候都不会超量占用系统资源,避免某些业务进程的设计或实现的缺陷导致整个系统的运行紊乱甚至意外宕机
支持以下三个层次的资源配额管理
- 容器级别:对cup和内存进行限制
- Pod级别:对一个Pod内所有容器的可用资源进行限制
- namespace级别:对pod数量,RC数量,service数量,resourceQuota数量,secret数量,可持有的pv数量进行限制
k8s的配额管理是通过AdmissionController准入控制来实现的,准入控制提供了两种方式进行配额约束
- LimitRanger: 作用于pod和container
- ResourceQuota: 作用于namespace
如果pod定义时声明了LimitRanger,那么用户通过AIPservice请求修改/创建资源时,准入控制会计算当前配额的使用情况,如果不符合配额约束,则修改/创建资源失败
4.Namespace Controller
简介
- 用户通过APIServer可以创建新的namespace并保存在etcd中,Namespace Controller定时通过APIserver读取这些Namespace信息
- 如果NameSpace被API标识为优雅删除,则将该Namespace的状态设置成Terminating并保存到etcd中,同时Namespace Controller删除该Namespace下的ServiceAccount,RC,Pod,Sercret,persistentVoluem,ListRange,ResourceQuota和Event等资源对象
5.Endpoint Controller
简介
- Endpoints表示一个Service对应的所有Pod副本的访问地址,kube-proxy进程获取每个Service的Endpoints,从而实现了Service的负载均衡功能
- Endpoints Controller是负责生成和维护所有Endpoints对象的控制器
作用
- 负责监听Service和对应的Pod副本的变化
- 如果检测到Service被删除,则删除和该Service同名的Endpoints对象
- 如果检测到新的Service被创建或修改,则根据该Service信息获得相关的Pod列表,然后创建或更新Service对应的Endpoints对象
6.Service Controller
简介
- Service Controller其实是k8s集群和外部云平台之间的一个接口控制器
- Service Controller监听Service的变化
- 如果是一个LoadBalancer类型的Service,则Service Controller确保外部的云平台上该Service对应的LoadBalancer实例被相应的创建,删除以及更新路由转发表
三. Scheduler 原理分析
简介
- 负责Pod调度
- 将待调度的Pod按照特定的调度算法和调度策略绑定到集群中的某个合适的Node上,并将绑定信息写入etcd
调度流程
- 1.预选调度过程 : 即遍历所有的目标Node,通过预选策略,筛选出符合要求的候选Node
- 2.确定最优节点 : 在第一步基础上,通过优选策略,计算出每个候选节点的积分,积分最高者胜出
预选策略
- NoDiskConflict : 判断是否存在磁盘冲突
- PodFitsResources : 判断Node剩余资源是否满足要求
- PodSelectorMatches : 判断Node是否包含待调度Pod的指定标签
- PodFitsHost : 判断待调度Pod指定的节点名称是否和Node名称一致
- CheckNodeLabelPresence : 判断列出的标签在备选Node中存在时,是否选择该Node
- CheckServiceAffinity : 判断备选Node是否包含指定标签,或包含和待调度Pod在相同Service和Namespace下Pod所在节点的标签列表
- PodFitsPorts : 判断待调度Pod所需的端口是否在在Node中被占用
优选策略
- LeastRequestedPriority : 用于选出资源消耗最小的节点
- CalculateNodeLabelPriority : 用于判断列出的标签在备选节点存在时,是否选择该备选节点
- BalanceResourceAllocation :用于选出各项资源使用率最均衡的节点
四. kubelet 运行机制分析
简介
- 在k8s集群中,每个Node节点上都会启动一个kubelet服务进程,该进程用于处理Master节点下发到本节点的任务,管理Pod以及Pod中的容器
- 每个kubelet进程会在API Server上注册节点自身信息,定期想Master节点汇报节点资源的使用情况,并通过cAdvisor监控容器和节点资源
作用
- 节点管理
- Pod管理
- 容器健康检查
- 资源监控
节点管理
- 节点通过kubelet的启动参数来决定是否向API Server注册自己
- 当前每个kubelet被授予创建和修改任何节点的权限,但是在实践中,它仅仅创建和修改自己
- 当集群资源不足时,用户很容易通过kubelet的自注册模式来实现扩容
kubelet在启动时通过API Server注册节点信息,并定时向API Server发送节点的新消息,API Server在接受到这些信息后,将其写入etcd,通过kubelet的启动参数可设置每隔多长时间向API Server报告节点自身状态,默认为10s
Pod管理
1.kubelet如何获取自身Node所要运行的Pod清单?
- 文件 : 通过获取指定路径下的配置文件,并定期检查该文件,指定路径通过启动参数配置
- HTTP :通过获取指定URL下的数据,并定期轮询该URL,指定URL通过启动参数配置
- API Server : 通过API Server监听etcd目录,同步Pod列表
本章只讨论通过API Server获取Pod清单的方式
2.kubelet是如何创建和修改Pod任务的?流程大致是怎样?
- 1)为该Pod创建一个数据目录
- 2)从API Server读取Pod清单
- 3)为该Pod挂载外部卷
- 4)下载Pod用到的secret
- 5)检查已经运行在节点的Pod,如果该Pod中没有容器或Pause容器没有启动,则先停止Pod里所有容器的进程,如果有Pod中需要删除的容器,则删除这些容器
- 6)用k8s的pause镜像为每个Pod创建一个Pause容器,该Pause容器用于接管Pod中其他容器的网络
- 7)对Pod中的每个容器做以下处理
- 为容器计算一个hash值,然后用容器的名字去查询对应Docker容器的hash值,若查找到容器并且二者hash值不一样,则停止容器中的进程,并停止与之关联的pause
容器进程,若两个hash值相同,则不做任何处理 - 如果容器被终止了,且容器没有指定任何重启策略,则不做任何处理
- 调用docker client下载容器镜像,调用docker client运行容器
- 为容器计算一个hash值,然后用容器的名字去查询对应Docker容器的hash值,若查找到容器并且二者hash值不一样,则停止容器中的进程,并停止与之关联的pause
容器健康检查
1.kubelet如何检查容器的检查状态?
- 存活探针:判断容器是否健康
如果存活探针探测到容器不健康,那么kubelet将删除容器,并根据容器的重启策略做相应处理
- 就绪探针:判断容器是否启动完成
如果就绪探针探测到容器没就绪,则该Pod的状态将被修改,Endpoint Controller将从Service的Endpoint中删除包含该容器所在的Pod的IP地址的Endpoint条目
2.kubelet如何实现存活探针和就绪探针的?
- 命令:在容器内部执行一个命令,如果该命令的退出状态码为0,则表示容器健康
- TCP: 通过容器的IP地址和端口号执行TCP检查,如果端口可以被访问,则表示容器健康
- HTTP: 通过容器的IP地址和端口号以及路径调用http get方法,如果响应大于等于200且小于等于400,则表示容器健康
资源监控
1.是如何实现资源监控的?
- Heapster为k8s提供了一个基本的监控平台,它是集群级别的监控和事件数据集成器
- Heapster的Pod通过kubelet发现所有运行在集群中的节点,并查看来自这些节点的资源使用状况信息
- kubelet通过cAdvisor获取其所在节点以及容器的数据,Heapster通过带着关联标签的Pod分组这些信息,这些数据被推送到一个可配置的后端,用于存储和可视化展示
2.kubelet使用到的cAdvisor是什么?
- cAdivsor是一个开源的分析容器资源使用率和性能特性的代理工具,它被集成到k8s中,cAdvisor通过它所在Node的Root容器,采集并分析该Node的全面使用状况
kubelet作为连接master和各Node之间的桥梁,管理运行在Node上的Pod和容器,kubelet将每个Pod转换成它的成员容器,同时从cAdvisor获取单独的容器使用统计信息,然后通过该REST API暴露这些聚合后的Pod资源使用统计信息