一、基本功能
(1)Kubelet的工作内容
Kubelet是唯一一直作为常规系统组件来运行的组件,他的工作就是创建Pod实例并监控。当Schedule选择好要调度的节点,并通过Api-Server更新Pod资源的定义信息后,目标节点的Kubelet会监听到Api-Server发来的通知,然后创建并运行Pod的容器。随后他会持续监控运行的容器,实时向Api-Server报告他们的状态、事件和资源消耗。
Kubelet也是运行容器存活探针的组件,当探针报错时,他会重启容器。最后一点,当Pod从Api-Server删除时,Kubelet会终止容器,并通知Api-Server,Pod已经被终止了。
Kubelet运行静态Pod
前面我们说到,Kubelet在哪创建什么Pod完全是由Api-Server通知给他的。实际上他还能主动的创建Pod,它可以通过本地指定目录下的Pod资源清单来运行Pod。这也就解释了前面埋的点,为什么可以提前以Pod的形式部署Control Plane的组件。
在kubernetes集群中,每个Node节点(又称Minion)上都会启动一个kubelet服务进程。该进程用于处理Master节点下发到本节点的任务,管理Pod和其中的容器。每个kubelet进程会在API Server上注册节点自身信息,定期向Master节点汇报节点资源的使用情况,并通过cAdvisor监控容器和节点资源。
二、Kubelet和容器交互
在 Kubernetes1.5 之前 Docker 作为第一个容器运行时,Kubelet 通过内嵌 dockershim操作容器API,在 v1.6.0 后, Kubernetes开始默认启用 CRI(容器运行时接口)。
CRI 为 kubelet 提供一套抽象的容器调度的接口,CRI 主要承接 kubelet 对容器的操作。CRI 得通信协议是 gRPC,当时主要考虑到性能问题。加入 CRI 后 kubelet 的架构如下图所示。
kubelet 启动时便会初始化 CRI 客户端 ,与容器运行时建立连接并确认 CRI 的版本。CRI 容器运行时主要描述了三种服务的行为 Sandbox、Container、Image。
创建 pod 的过程中,都会通过 CRI 与容器运行时进行交互
创建 sandbox
创建容器
拉取镜像
CRI 提供了一种标准化的接口,用于与底层容器运行时进行交互。这对与发展和状大 Kubernetes 生态系统非常重要:
Kubernetes 控制平面与容器管理的具体实现解耦,可以独立升级或者切换容器运行时,方便扩展和优化。
Kubernetes 作为一个跨云、跨平台和多环境的容器编排系统,在不同的环境和场景下使用不同的容器平台。CRI 的出现,保证平台的多样性和灵活性。
CRI接口可以分为两组:
- RuntimeService:主要是跟容器相关的操作,比如创建、启动、删除容器,执行exec命令等
- ImageManagerService:主要是容器镜像相关的操作,比如拉取镜像、删除镜像等
CRI设计的一个重要原则,就是确保这个接口本身,只关注容器,不关注Pod,在CRI的设计里并没有一个直接创建Pod或者启动Pod的接口
三、节点管理
通过设置kubelet的启动参数“--register-node”,来决定是否自动主动地向API Server注册自己,默认为true。
当前每个kubelet被授予创建和修改任务节点的权限,但实践中,它仅仅创建和修改自己。未来将会限制这一权限,仅允许它修改和创建其所在节点的权限。
在集群运行过程中,如果遇到资源不足的情况,则用户很容易通过添加机器及利用kubelet的自注册模式来实现扩容。
如果系统管理员希望手动创建节点信息,则可以通过设置--register-node=false即可。
四、Pod管理
kubelet通过以下几种方式获取自身Node上所需要运行的Pod清单。
文件:kubelet启动参数"--config"指定的配置文件目录下的文件,通过--file-check-frequency设置检查该文件目录的时间间隔,默认为20s。
HTTP端点(URL):通过"--manifest-url"参数设置,通过--http-check-frequency设置检查时间间隔,默认为20s。
API Server:kubelet通过API Server监听etcd目录,同步Pod列表。
kubelet监听etcd,所以针对Pod的操作将会被kubelet监听到。如果发现有新的绑定到本节点的Pod,则按照Pod清单的要求创建该Pod。
如果发现本地Pod被修改,则kubelet会做出相应的修改,比如删除Pod中的某个容器时,则通过Docker Client删除该容器。
如果发现删除本节点的Pod,则删除相应的Pod,并通过Docker Client删除Pod中的容器。
kubelet读取监听到的信息,如果是创建和修改Pod任务,则做如下处理:
1)为该Pod创建一个数据目录。
2)从API Server读取该Pod清单。
3)为该Pod挂载外部卷(External Volume)
4)下载Pod用到的Secret。
5)检查已运行在节点中的Pod,如果该Pod没有容器或Pause容器没有启动,则先停止Pod里所有容器的进程。如果在Pod中有需要删除的容器,则删除这些容器。
6)用"kubernetes/pause"镜像为每个Pod创建一个容器。该Pause容器用于接管Pod中所有其它容器的网络。
7)为Pod中的每个容器做如下处理:
为容器计算一个hash值,然后用容器的名字去查询对应Docker容器的hash值。这里的hash值可以理解为是依据容器的定义文件所生成的。对比两个hash值,发现有不同则会停止Docker中容器的进程,并停止与之关联的Pause容器的进程。若二者相同,则不做任何处理。
如果容器被终止了,且没有指定restartPolicy重启策略,则不做任何处理。
调用Docker Client下载容器镜像,调用Docker Client运行容器。
五、容器健康状态检查
LivenessProbe
用于判断容器是否存活(running状态)。
如果LivenessProbe探针探测到容器非健康,则kubelet将杀掉该容器,并根据容器的重启策略做相应处理。
如果容器不包含LivenessProbe探针,则kubelet认为该探针的返回值永远为“success”。
ReadinessProbe
- 用于判断容器是否启动完成(read状态),可以接受请求。
- 如果ReadnessProbe探针检测失败,则Pod的状态将被修改。Endpoint Controller将从Service的Endpoint中删除包含该容器所在Pod的Endpoint。