上一篇文章中,我们主要去介绍了 codec 是如何完成 decode 和 encode 操作的,即对象的序列化和反序列化的过程。 在 decode 操作的核心过程中, 首先会将对象从请求中反序列化,然后在转化为目标版本(一般是内部版本),然后在进行处理。encode 操作的过程中, 首先将对象(一般为内部版本对象)转化为目标版本,然后再序列化到响应数据流中。
在这篇文章里,我们主要来介绍 schema,schema 是 kubernetes 资源管理的核心数据结构。由以前文章我们了解到 kubernetes 会将其管理的资源划分为 group/version/kind 的概念,我们可以将资源在内部版本和其他版本中相互转化,我们可以序列化和反序列化的过程中识别资源类型,创建资源对象,设置默认值等等。这些 group/version/kind 和资源 model 的对应关系,资源 model 的默认值函数,不同版本之间相互转化的函数等等全部由 schema 维护。可以说 schema 是组织 kubernetes 资源的核心,其数据结构如下:
核心代码定义如下:
// kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go
type Scheme struct {
gvkToType map[schema.GroupVersionKind]reflect.Type
typeToGVK map[reflect.Type][]schema.GroupVersionKind
unversionedTypes map[reflect.Type]schema.GroupVersionKind
unversionedKinds map[string]reflect.Type
fieldLabelConversionFuncs map[schema.GroupVersionKind]FieldLabelConversionFunc
defaulterFuncs map[reflect.Type]func(interface{})
converter *conversion.Converter
versionPriority map[string][]string
observedVersions []schema.GroupVersion
schemeName string
}
从上面的图解以及源码来看 schema 结构主要有以下关键点:
由上面的 schema 的数据结构看,它是一个 struct 的类型,另外它还实现了一些接口,使得 schema 可以创建资源对象,给资源对象赋默认值,识别资源对象类型,完成资源对象本版之间的转换,完成资源的 label 标签转化等。其接口实现如下图:
接口实现的函数核心代码定义如下:
// kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go
func (s *Scheme) Convert(in, out interface{}, context interface{}) error{...}
func (s *Scheme) ConvertToVersion(in Object, target GroupVersioner) (Object, error){...}
func (s *Scheme) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error){...}
func (s *Scheme) Default(src Object){...}
func (s *Scheme) New(kind schema.GroupVersionKind) (Object, error) {...}
func (s *Scheme) ObjectKinds(obj Object) ([]schema.GroupVersionKind, bool, error){...}
func (s *Scheme) Recognizes(gvk schema.GroupVersionKind) bool{...}
从上面的图解以及源码来看 schema 实现接口主要有以下关键点:
目前先我们写到这里,在下一篇文章中我们继续来介绍 kubernetest 资源是如何注册到 schema 之中的。