几乎所有的对象都包含了上面四大类属性。
Java里面会有包管理,每个包里面会有不同的类,我们会将相同类型的类放在一个包里面,kubernets也是一样的,针对每一个被管理的对象,它有一个kind,kubermets会将相同功能,相同目的的这些对象放到一个group里面,kind定义了它是什么,group是将不同对象的一个组织方式。
version是用来支持api向前兼容的一个设定,版本是不断演进的,kubernets会在第一个版本把这个模型的版本设计为v1aplpha1,它是一个alpha版本,随着版本的演进,它会不断的去提升这个版本,如果是一个demo的版本,那么永远都在alpha的阶段,v1alpha1->v1alpha2->v1alpha3,如果觉得功能相对成熟了,你可以拿去试一试,基本快到生产就绪了,它会变成beta,它会变为v1beta1,v1beta1->v1beta2->v1beta3,直到认为这个功能已经生产就绪了,这个模型基本上不会改变了,这个时候会将他变为v1。
所以它会有不断的版本演进,但是版本演进要做向前兼容,那么kubernetes对每个对象都增加了version的控制,所以当一个对象从v1alpha1到v1alpha2的演进的时候,在这个过度版本它会对两个版本都支持,也就是可以从v1alpha1的版本去访问它,也可以从v1alpha2的版本访问它,但是在kubernetes里面在apiserver的层面,它实现了conversion的方法,用来负责不同版本之间的转化,所谓version就是用来控制版本的。
所以整个typemeta就定义了一个对象是哪一个组的,什么类型的,哪一个版本的,所以基本就定义了对象是什么。
定义了对象的原数据,namespace是用来放置对象的,对象可以通过namespace做隔离。
任何的kubernetes的对象会分为两类,一类像节点这种对象,一个计算节点是属于整个集群的,这类对象是nonnamespace,它的namespace值永远都是空的。
还有一种是pod,service,都是归属于某个租户/用户的,这些对象属于namespace。
一个对象namespace+name就代表了在整个集群当中唯一值。
typemeta定义了我是啥,metadata定义了我是谁。
一个对象,当我们创建的时候,把这个对象的请求发送到apiserver,apiserver经过认证鉴权存入到etcd,如果删除这个对象,也是经过一样的链路,它最后从etcd中删除掉,这个删除本身是物理删除,相当于etcd当中这条数据就抹掉了,这个对象就消失了。
如果写了控制器监控这个对象,那么会监听这个对象的创建,这个对象创建了就去做一些事情,对象删除了就会去做另外一些事情,我们不能够相信系统永远都在工作,假设控制器出错了,或者控制器在升级,这个时候控制器没有在工作,这个时候去删除对象,假设这个对象消失了,那么这个事件已经消失了,在这个对象删除之后,再去启动我的控制器,控制器是看不到之前这个对象删除的事件,因为在控制器启动之前这个事件已经发生了,在启动新的控制器实例的时候,没有这个消息通知,所以就丢失了对象删除的这样一个事件。
所以fanalizer本质上是资源锁,一个对象加了finalizer,在删除对象的时候不会做物理删除,它会做逻辑删除,其实也就是在它属性的事件戳里面deletetimestamp置为在删除那一刻的时间戳。
这样的好处是当用户去删除对象,如果这个对象有finalzer,那么这个对象不会消失,然后这个控制器可以捕获这个事件,即使是控制器在维护,然后重新启动之后就能够看到这个事件了,当发现一个对象deletetimestamp不为空,说明用户想删除它,那么控制器里面就可以去做一些逻辑处理。
resourceversion
它其实也是一把锁,在微服务场景下如果有多个组件去修改一个对象,怎么保证对象的访问安全。
也就是多个进程去修改一个对象的时候,怎么样保证它的安全。
第一种就是加锁,加锁之后再去修改,其他进程或者线程要去访问同样对象的时候要去等待锁,如果拿不到锁就要阻塞,这种方式带来了什么问题呢?首先它特别的安全,其次很多线程会阻塞,特别是高并发的时候,一个人拿到锁,其他人要访问同样的资源,那么它就需要去做等待,这样一个系统很多进程就会处于阻塞状态,所以整个系统的效率较低。
还有一种就是乐观锁,能不能通过一种方式记录一个版本信息,当两个线程去访问同一个对象的时候,这个时候给对象添加一个版本号,比如v1,那么拿到的都是这个对象的v1版本,这个时候两个人要同时去修改这个对象,这两个修改对象虽然同时发生,但是请求都会发给apiserver这一端,当apiserver这一端接收到请求的时候,它一定会一个先处理,一个后处理,它还是顺序执行的。这个时候当它处理第一个请求的时候,它会看到在v1的版本上去做修改的,你要去将一个属性更新掉,这个请求是合法的,那么apiserver会将这个请求处理掉,将这个属性更新,并且将版本变为v2,在处理第二个请求的时候,它一样会去看第二个请求带的版本号是什么,当前server端的版本变为v2了,说明之前发来的请求是非法的,是基于一个老版本的数据做修改的,所以会拒绝这个请求。
所以resourceversion就是这样一个版本信息,它就是一个乐观锁,它维护了对象的版本信息,每个组件要去修改同一个对象的时候要带着版本过来,由apiserver来判断是不是基于最新版本做修改的,如果不是就拒绝,如果是的话就接受,这样多个组件就可以以无锁的状态来修改同一个对象。
apiserver拒绝了一个请求,那么客户端有义务拿到最新的版本重试,这样的话系统就是以无锁的状态运行起来。
在查询对象的时候可以通过标签过滤器去查询的。
spec是用户输入的,也就是我期望你是什么状态。
每个对象都有控制器,status是由控制器去做配置的,配置完成以后写回到这个对象,status是由控制器去控制的。
可以看到将不同的对象放到不同的group里面,支撑核心业务的放在core/v1里面,需要做应用管理放在apps/v1。