上一篇文章中,我们主要去介绍了 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 结构主要有以下关键点:
包含 map 类型的 gvkToType 属性来维护 GVK 和 model 对象类型的关系。
包含 map 类型的 typeToGVK 属性来维护 model 对象类型和 GVK 的关系。
包含 map 类型的 defaulterFuncs 属性维护 model 对象类型和默认值函数的关系。
包含 conversion.Converter 指针类型的 converter 属性实现资源不同版本的转化。
map 类型的 fieldLabelConversionFuncs 属性维护 GVK label 标签转换函数的关系。
包含 string 类型的 schemaName 属性用来定义 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 实现接口主要有以下关键点:
实现 runtime.ObjectCreater 接口定义的方法完成资源的创建。
实现 runtime.ObjectDefaulter 接口定义的方法完成资源的赋默认值。
实现 runtime.ObjectConvert 接口定义的方法完成资源不同版本之间的相互转换。
实现 runtime.ObjecTyper 接口定义的方法完成资源的类型识别。
目前先我们写到这里,在下一篇文章中我们继续来介绍 kubernetest 资源是如何注册到 schema 之中的。