informer内部机制

在这里插入图片描述
k8s有一个非常核心的组件:”apiserver“ 所有对象的访问都由apiserver去操作,所谓的informer会提供一个list和watch机制(informer在启动以后会发起一个长链接请求apiserver,通常会第一时间list,接下来会watch,监听apiserver对象的任何变化)
apiserver是一个json的序列化数据,程序要消费这个数据,则需要反序列化(字符串转换为go对象),上图中Reflector,是通过反射机制实现的,会解析对象的key,apiserver中的json tag,添加对象至环状的buffer里边,会通知informer来处理,首先会对序列化好的对象(namespace)放到一个store里边,并通过索引indexer来进行管理,这样后续访问k8s对象的时候就不用去找apiserver访问,直接可以通过本地Localstore获取,减少对apiserver的访问,同时对象的变化会通过event注册到event handler,然后放到workqueue里边,另外一边从woker里边获取数据来进行处理。

注意点:
任何控制器都应该用shareinformer,所有的对象只要在客户端(控制器),所有对象在本地已有缓存,由shareinformer来保证本地缓存和apiserver一致性,例如二开控制器时,尽量减少对apiserver的操作,如果更新操作可以通过apiserver来刷新数据,Thread Safe store为本地内存里边的。

控制器原理

在这里插入图片描述

可以理解为生产者与消费者模型,任何的k8s对象都会生成informer(观察框架)和lister(获取全量数据的框架),当我们去生成控制器时,例如基于Kubebuild,或者社区的cilmconpler仿写控制器,第一步就是通过lister和informer去观察监听某一个对象,监听的对象就会有一些event(如Add、Delete、Update),不同的event可以注册handler,发生event把对象的key(namespace和name)取出来放到Ratelimitq里面,另外一边会启gorouting,可以配置多个worker,不停的从queue里边获取数据,只要队列里边有数据,说明对象变化还未被处理,worker主要工作就是完成配置,直到队列里空为止,如果出错,就会以ratelimit方式enqueue回去。

控制器协同工作原理

在这里插入图片描述

背景:
如果单纯创建一个Pod资源,也是可行的,但在我们生产环境中,一个Pod是无法达到k8s本身平台的机制,例如:故障自愈,高可用(冗余部署)负载均衡(service)等,所以k8s有控制器这样一个更高阶的资源抽象-deployment,以此来描述应用的部署交付。

Controller Manager介绍:
Controller Manager 是集群的大脑,是确保整个集群动起来的关键;
作用是确保 Kubernetes 遵循声明式系统规范,确保系统的真实状态(ActualState)与用户定义的期望状态(Desired State)一致;
Controller Manager 是多个控制器的组合,每个 Controller 事实上都是一个control loop,负责侦听其管控的对象,当对象发生变更时完成配置;
Controller 配置失败通常会触发自动重试,整个集群会在控制器不断重试的机制下确保最终一致性( Eventual Consistency)。

1.创建一个deploy并查看events
说明:events也是k8s里的一种资源,可以理解为每个对象资源的边车模式,用来描述某个对象最近发生过什么事件?
~]# kubectl describe deploy/notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a -nproject-1
Events:
Type    Reason             Age   From                   Message
----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  55s   deployment-controller  Scaled up replica set notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d to 1

~]# kubectl get replicasets -nproject-1 notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d 
NAME                                                       DESIRED   CURRENT   READY   AGE
notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d   1         1         1       29m

2.查看rs的events事件
~]# kubectl describe replicasets notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d -nproject-1
Events:
  Type    Reason            Age    From                   Message
  ----    ------            ----   ----                   -------
  Normal  SuccessfulCreate  8m16s  replicaset-controller  Created pod: notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d-wjdf5

~]# kubectl get pod notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d-wjdf5 -nproject-1
NAME                                                             READY   STATUS    RESTARTS   AGE
notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d-wjdf5   2/2     Running   0          30m

3.查看Pod的events事件
~]# kubectl describe pod notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d-wjdf5 -nproject-1
  Events:
  Type    Reason     Age    From     Message
  ----    ------     ----   ----     -------
  Normal  Scheduled  9m19s  volcano  Successfully assigned project-1/notebook-1eb8a446-f9e5-11ec-afe4-0000008b3b4a-7fcf7bdc4d-wjdf5 to 10.8.0.23
  Normal  Pulling    9m17s  kubelet  Pulling image "x.x.x.x:31104/ti-platform/notebook-pytorch:1.5.1-gpu-cu101-py3"
  Normal  Pulled     9m17s  kubelet  Successfully pulled image "x.x.x.x:31104/ti-platform/notebook-pytorch:1.5.1-gpu-cu101-py3" in 188.51269ms
  Normal  Created    9m17s  kubelet  Created container notebook-instance
  Normal  Started    9m17s  kubelet  Started container notebook-instance
  Normal  Pulling    9m17s  kubelet  Pulling image "x.x.x.x:31104/ti-platform/socat:latest"
  Normal  Pulled     9m17s  kubelet  Successfully pulled image "x.x.x.x:31104/ti-platform/socat:latest" in 174.286585ms
  Normal  Created    9m17s  kubelet  Created container notebook-dockerd
  Normal  Started    9m17s  kubelet  Started container notebook-dockerd

定义deploy资源——>声明replicas——>image声明——>应用运行

创建了dp资源对象之后,发给apiserver组件,apiserver会进行认证鉴权(读取本地配置文件),之后会存储到etcd数据库中,接下来就是集群的大脑controller manager组件开始干活了,具体也可通过查看日志kubectl logs -f kube-controller-manager-x.x.x.x -nkube-system,它的行为主要依赖deployment里的yaml定义(例如:需要5个副本,运行nginx镜像),然后会创建一个replicasets对象,包括pod的模板,副本数,创建RS之后会发到apiserver,controller manager里边也有一个ReplicaSet Controller,它也在监听apiserver,发现有一个rs的创建请求,发现pod不存在,就新建一个Pod,创建完之后查看pod详细信息有一个nodeName属性,这时调度器来做调度,它背后的逻辑一直是watch资源的对象(例如目前介绍的Pod),它首先会过滤当前集群不符合调度pod资源的节点,其次在符合要求的节点里选择打分比较高的节点,整个调度结束之后会把结果返回给apiserver;接下来由节点上的kubelet组件干活,首先会看apiserver中的pod信息,对比本地是否存在该容器pod,不存在的话说明是一个新pod,然后执行创建pod的动作:k8s启动docker不会挂载网络,使用cni插件,只启runtime,例如pod需外挂存储,k8s也有对应的csi插件来实现。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐