什么是Scheme

如果说RESTMapper管理的是GVR和GVK的关系,那么Scheme管理的就是GVK和Type的关系。系统中所有的Type都要注册到Scheme中,当然目前系统只有一个Scheme,即api.Scheme,定义在/pkg/api/register.go中:

1
2
//***定义Scheme***//
var Scheme = runtime.NewScheme()

我们先来看下Scheme结构体的定义,Scheme结构体定义在/pkg/runtime/scheme.go中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
type Scheme struct {
// versionMap allows one to figure out the go type of an object with
// the given version and name.
gvkToType map[unversioned.GroupVersionKind]reflect.Type
// typeToGroupVersion allows one to find metadata for a given go object.
// The reflect.Type we index by should *not* be a pointer.
//***kind, gvk: v1.ListOptions authorization.k8s.io/v1beta1, Kind=ListOptions***//
//***kind, gvk: v1.ListOptions apps/v1beta1, Kind=ListOptions***//
typeToGVK map[reflect.Type][]unversioned.GroupVersionKind
// unversionedTypes are transformed without conversion in ConvertToVersion.
unversionedTypes map[reflect.Type]unversioned.GroupVersionKind
// unversionedKinds are the names of kinds that can be created in the context of any group
// or version
// TODO: resolve the status of unversioned types.
unversionedKinds map[string]reflect.Type
// Map from version and resource to the corresponding func to convert
// resource field labels in that version to internal version.
//***field selector转换函数***//
fieldLabelConversionFuncs map[string]map[string]FieldLabelConversionFunc
// defaulterFuncs is an array of interfaces to be called with an object to provide defaulting
// the provided object must be a pointer.
//***默认值设置函数***//
defaulterFuncs map[reflect.Type]func(interface{})
// converter stores all registered conversion functions. It also has
// default coverting behavior.
//***聚合converter结构体***//
converter *conversion.Converter
// cloner stores all registered copy functions. It also has default
// deep copy behavior.
//***Fankang***//
//***聚合cloner结构体***//
cloner *conversion.Cloner
}

可以看出,Scheme除了管理GVK和Type的关系,还管理有默认设置函数,并聚合了converter及cloner。我们来详细看下每个字段的含义:

  • gvkToType: 存储gvk和Type的关系,一个gvk只能对应一个Type;
  • typeToGVK:存储Type和gvk的关系,一个type可能对应多个GVK;
  • unversionedTypes:记录unversioned的Type和GVK的关系,unversioned无需版本转换;
  • unversionedKinds:记录unversioned的GVK和Type的关系;
  • fieldLabelConversionFuncs:管理field selector的转换,如旧版本v1的spec.host需要转换成spec.nodeName(详见在/pkg/api/v1/conversion.go中的addConversionFuncs()函数);
  • defaulterFuncs:存储Type及其对应的默认值设置函数;
  • converter:用来转换不同版本的结构体值;
  • cloner:用来获取结构体值的拷贝。

Kubernetes内部组件的流通的结构体值使用的是内部版本,所有的外部版本都要向内部版本进行转换;内部版本必须转换成外部版本才能进行输出。外部版本之间不能直接转换。

从Scheme的定义可以看出,Scheme是个converter,也是个cloner,关于converter和cloner,后续分析。

NewScheme()

NewScheme()可以生成一个新的Scheme,其中cloner调用conversion.NewCloner()初始化,converter调用conversion.NewConverter()初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// NewScheme creates a new Scheme. This scheme is pluggable by default.
func NewScheme() *Scheme {
s := &Scheme{
gvkToType: map[unversioned.GroupVersionKind]reflect.Type{},
typeToGVK: map[reflect.Type][]unversioned.GroupVersionKind{},
unversionedTypes: map[reflect.Type]unversioned.GroupVersionKind{},
unversionedKinds: map[string]reflect.Type{},
cloner: conversion.NewCloner(),
fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{},
defaulterFuncs: map[reflect.Type]func(interface{}){},
}
//***converter使用的是nameFunc***//
s.converter = conversion.NewConverter(s.nameFunc)
s.AddConversionFuncs(DefaultEmbeddedConversions()...)
// Enable map[string][]string conversions by default
if err := s.AddConversionFuncs(DefaultStringConversions...); err != nil {
panic(err)
}
if err := s.RegisterInputDefaults(&map[string][]string{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields); err != nil {
panic(err)
}
if err := s.RegisterInputDefaults(&url.Values{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields); err != nil {
panic(err)
}
return s
}

AddUnversionedTypes()

AddUnversionedTypes()方法可以向Scheme注册unvertioned type,方法先调用AddKnownTypes(),然后填充unversionedTypes和unversionedKinds两个map,在/api/register.go中有调用。Unversioned type不需要进行转换。

1
2
3
4
5
6
7
8
9
10
11
12
func (s *Scheme) AddUnversionedTypes(version unversioned.GroupVersion, types ...Object) {
s.AddKnownTypes(version, types...)
for _, obj := range types {
t := reflect.TypeOf(obj).Elem()
gvk := version.WithKind(t.Name())
s.unversionedTypes[t] = gvk
if _, ok := s.unversionedKinds[gvk.Kind]; ok {
panic(fmt.Sprintf("%v has already been registered as unversioned kind %q - kind name must be unique", reflect.TypeOf(t), gvk.Kind))
}
s.unversionedKinds[gvk.Kind] = t
}
}

AddKnownTypes()

AddKnownTypes()为Scheme的type注册函数,参数为GV及types,其中types和GV先组成GVK,然后向gvkToType和typeToGVK填充Type和GVK的关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//***把types在Scheme中注册***//
func (s *Scheme) AddKnownTypes(gv unversioned.GroupVersion, types ...Object) {
if len(gv.Version) == 0 {
panic(fmt.Sprintf("version is required on all types: %s %v", gv, types[0]))
}
for _, obj := range types {
t := reflect.TypeOf(obj)
if t.Kind() != reflect.Ptr {
panic("All types must be pointers to structs.")
}
//***Elem()能对指针进行解引用***//
t = t.Elem()
if t.Kind() != reflect.Struct {
panic("All types must be pointers to structs.")
}
gvk := gv.WithKind(t.Name())
//***一个GVK只能对应一个type***//
s.gvkToType[gvk] = t
//***t, gvk: v1.Event /v1, Kind=Event***//
//***同一个type,可能对应多个gvk***//
s.typeToGVK[t] = append(s.typeToGVK[t], gvk)
}
}

AddKnownTypeWithName()

AddKnownTypeWithName()可以指定object对应的gvk。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//***可以指定obj的kind,而不用像AddKnownTypes()去反射获取type的name作为kind***//
func (s *Scheme) AddKnownTypeWithName(gvk unversioned.GroupVersionKind, obj Object) {
t := reflect.TypeOf(obj)
if len(gvk.Version) == 0 {
panic(fmt.Sprintf("version is required on all types: %s %v", gvk, t))
}
if t.Kind() != reflect.Ptr {
panic("All types must be pointers to structs.")
}
t = t.Elem()
if t.Kind() != reflect.Struct {
panic("All types must be pointers to structs.")
}
s.gvkToType[gvk] = t
s.typeToGVK[t] = append(s.typeToGVK[t], gvk)
}

KnownTypes()

KnownTypes()返回Scheme中具体版本下的gvk和type的map关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
//***通过gv在scheme中找到所有合适的types***//
//***具体gv下的kind唯一***//
func (s *Scheme) KnownTypes(gv unversioned.GroupVersion) map[string]reflect.Type {
types := make(map[string]reflect.Type)
for gvk, t := range s.gvkToType {
if gv != gvk.GroupVersion() {
continue
}
types[gvk.Kind] = t
}
return types
}

AllKnownTypes()

AllKnownTypes()返回Scheme中所有版本的gvk和type的map关系。

1
2
3
4
//***返回gvkToType***//
func (s *Scheme) AllKnownTypes() map[unversioned.GroupVersionKind]reflect.Type {
return s.gvkToType
}

ObjectKind() ObjectKinds()

ObjectKinds()通过obj的type获取对应的GVK(可能存在多个GVK);ObjectKind()则在ObjectKinds()的基础上返回第一个GVk。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//***获取obj的gvk***//
func (s *Scheme) ObjectKind(obj Object) (unversioned.GroupVersionKind, bool, error) {
gvks, unversionedType, err := s.ObjectKinds(obj)
if err != nil {
return unversioned.GroupVersionKind{}, false, err
}
return gvks[0], unversionedType, nil
}
//***通过obj的类型获取所有的gvk***//
func (s *Scheme) ObjectKinds(obj Object) ([]unversioned.GroupVersionKind, bool, error) {
v, err := conversion.EnforcePtr(obj)
if err != nil {
return nil, false, err
}
t := v.Type()
//***从typeToGVK中获取gvks***//
gvks, ok := s.typeToGVK[t]
if !ok {
return nil, false, NewNotRegisteredErr(unversioned.GroupVersionKind{}, t)
}
_, unversionedType := s.unversionedTypes[t]
return gvks, unversionedType, nil
}

Recognizes()

Recognizes()判断GVK在Scheme中是否有注册。

1
2
3
4
func (s *Scheme) Recognizes(gvk unversioned.GroupVersionKind) bool {
_, exists := s.gvkToType[gvk]
return exists
}

IsUnversioned()

IsUnversioned()判断obj是否属于unversioned。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//***判断obj是否是属于unversioned***//
func (s *Scheme) IsUnversioned(obj Object) (bool, bool) {
v, err := conversion.EnforcePtr(obj)
if err != nil {
return false, false
}
t := v.Type()
if _, ok := s.typeToGVK[t]; !ok {
return false, false
}
_, ok := s.unversionedTypes[t]
return ok, true
}

New()

New()可以创建一个gvk类型的结构体值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//***新建一个符合gvk的具体object***//
func (s *Scheme) New(kind unversioned.GroupVersionKind) (Object, error) {
//***versioned的情况***//
if t, exists := s.gvkToType[kind]; exists {
//***通过reflect.New(t).Interface().(Object)来生成新的object***//
return reflect.New(t).Interface().(Object), nil
}
//***unversioned的情况***//
if t, exists := s.unversionedKinds[kind.Kind]; exists {
return reflect.New(t).Interface().(Object), nil
}
return nil, NewNotRegisteredErr(kind, nil)
}

AddGenericConversionFunc()

AddGenericConversionFunc()是对converter的AddGenericConversionFunc()方法的封装,关于converter将在以后分析。

1
2
3
4
5
//***GenericConversionFunc可以理解为转换的快速通道***//
func (s *Scheme) AddGenericConversionFunc(fn conversion.GenericConversionFunc) {
//***调用converter的addGenericConversionFunc()***//
s.converter.AddGenericConversionFunc(fn)
}

AddIgnoredConversionType()

AddIgnoredConversionType()是对converter的RegisterIgnoredConversion()方法的封闭,关于converter将在以后分析。

1
2
3
4
func (s *Scheme) AddIgnoredConversionType(from, to interface{}) error {
//***需要忽略的类型转换***//
return s.converter.RegisterIgnoredConversion(from, to)
}

AddConversionFuncs()

AddConversionFuncs()可以向converter注册转换函数,关于converter将在以后分析。

1
2
3
4
5
6
7
8
9
10
//***向converter注册conversion函数***//
func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error {
for _, f := range conversionFuncs {
//***调用converter的RegisterConversionFunc()函数***//
if err := s.converter.RegisterConversionFunc(f); err != nil {
return err
}
}
return nil
}

AddGeneratedConversionFuncs()

AddGeneratedConversionFuncs()可以向converter注册GeneratedConversionFuncs,其中GeneratedConversionFuncs为自动生成的转换函数,关于converter将在以后分析。

1
2
3
4
5
6
7
8
9
//***向converter注册generatedConversion函数***//
func (s *Scheme) AddGeneratedConversionFuncs(conversionFuncs ...interface{}) error {
for _, f := range conversionFuncs {
if err := s.converter.RegisterGeneratedConversionFunc(f); err != nil {
return err
}
}
return nil
}

AddDeepCopyFuncs()

AddDeepCopyFuncs()可以向cloner注册克隆函数,关于cloner将在以后分析。

1
2
3
4
5
6
7
8
9
10
//***向cloner注册deepCopy函数***//
//***系统中未找到调用***//
func (s *Scheme) AddDeepCopyFuncs(deepCopyFuncs ...interface{}) error {
for _, f := range deepCopyFuncs {
if err := s.cloner.RegisterDeepCopyFunc(f); err != nil {
return err
}
}
return nil
}

AddGeneratedDeepCopyFuncs()

AddGeneratedDeepCopyFuncs()可以向cloner注册GeneratedDeepCopyFuncs,其中GeneratedDeepCopyFuncs为自动生成的克隆函数,关于cloner将在以后分析。

1
2
3
4
5
6
7
8
9
//***向cloner注册generatedDeepCopy函数***//
func (s *Scheme) AddGeneratedDeepCopyFuncs(deepCopyFuncs ...conversion.GeneratedDeepCopyFunc) error {
for _, fn := range deepCopyFuncs {
if err := s.cloner.RegisterGeneratedDeepCopyFunc(fn); err != nil {
return err
}
}
return nil
}

AddFieldLabelConversionFunc()

AddFieldLabelConversionFunc()可以向Scheme注册field selector转换函数。

1
2
3
4
5
6
7
8
9
//***字段转换函数***//
func (s *Scheme) AddFieldLabelConversionFunc(version, kind string, conversionFunc FieldLabelConversionFunc) error {
if s.fieldLabelConversionFuncs[version] == nil {
s.fieldLabelConversionFuncs[version] = map[string]FieldLabelConversionFunc{}
}
s.fieldLabelConversionFuncs[version][kind] = conversionFunc
return nil
}

AddStructFieldConversion()

AddStructFieldConversion()可以向converter注册struct字段转换函数,关于cloner将在以后分析。

1
2
3
4
//***struct成员转换函数***//
func (s *Scheme) AddStructFieldConversion(srcFieldType interface{}, srcFieldName string, destFieldType interface{}, destFieldName string) error {
return s.converter.SetStructFieldCopy(srcFieldType, srcFieldName, destFieldType, destFieldName)
}

RegisterInputDefaults()

RegisterInputDefaults()可以向convertor注册转换发生缺省时默认的处理方式函数。

1
2
3
func (s *Scheme) RegisterInputDefaults(in interface{}, fn conversion.FieldMappingFunc, defaultFlags conversion.FieldMatchingFlags) error {
return s.converter.RegisterInputDefaults(in, fn, defaultFlags)
}

AddDefaultingFuncs()

AddDefaultingFuncs()可以向converter注册DefaultingFunc函数,DefaultingFunc函数可以设置相关结构体值的默认值。

1
2
3
4
5
6
7
8
9
10
//***添加设置默认值函数***//
func (s *Scheme) AddDefaultingFuncs(defaultingFuncs ...interface{}) error {
for _, f := range defaultingFuncs {
err := s.converter.RegisterDefaultingFunc(f)
if err != nil {
return err
}
}
return nil
}

Default()

Default()可以对object设置默认值。

1
2
3
4
5
6
//***设置src默认值***//
func (s *Scheme) Default(src Object) {
if fn, ok := s.defaulterFuncs[reflect.TypeOf(src)]; ok {
fn(src)
}
}

Copy()

Copy()是对cloner.DeepCopy()的封装,可以拷贝一个object。

1
2
3
4
5
6
7
8
9
10
11
12
13
//***深度拷贝src***//
func (s *Scheme) Copy(src Object) (Object, error) {
dst, err := s.DeepCopy(src)
if err != nil {
return nil, err
}
return dst.(Object), nil
}
// Performs a deep copy of the given object.
func (s *Scheme) DeepCopy(src interface{}) (interface{}, error) {
return s.cloner.DeepCopy(src)
}

Convert()

Convert()是对converter.Convert()的封装。

1
2
3
4
5
6
7
8
9
//***转换函数***//
func (s *Scheme) Convert(in, out interface{}, context interface{}) error {
flags, meta := s.generateConvertMeta(in)
meta.Context = context
if flags == 0 {
flags = conversion.AllowDifferentFieldTypeNames
}
return s.converter.Convert(in, out, flags, meta)
}

ConvertFieldLabel()

ConvertFieldLabel()可以对field selector进行转换。

1
2
3
4
5
6
7
8
9
10
11
//***转换field selector标签***//
func (s *Scheme) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
if s.fieldLabelConversionFuncs[version] == nil {
return "", "", fmt.Errorf("No field label conversion function found for version: %s", version)
}
conversionFunc, ok := s.fieldLabelConversionFuncs[version][kind]
if !ok {
return "", "", fmt.Errorf("No field label conversion function found for version %s and kind %s", version, kind)
}
return conversionFunc(label, value)
}

ConvertToVersion()

ConvertToVersion()可以把in转换成合适的版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
func (s *Scheme) ConvertToVersion(in Object, target GroupVersioner) (Object, error) {
return s.convertToVersion(true, in, target)
}
func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) (Object, error) {
// determine the incoming kinds with as few allocations as possible.
t := reflect.TypeOf(in)
if t.Kind() != reflect.Ptr {
return nil, fmt.Errorf("only pointer types may be converted: %v", t)
}
t = t.Elem()
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("only pointers to struct types may be converted: %v", t)
}
kinds, ok := s.typeToGVK[t]
if !ok || len(kinds) == 0 {
return nil, NewNotRegisteredErr(unversioned.GroupVersionKind{}, t)
}
//***从多个gvk中选择出符合target的要求的gvk***//
gvk, ok := target.KindForGroupVersionKinds(kinds)
if !ok {
// try to see if this type is listed as unversioned (for legacy support)
// TODO: when we move to server API versions, we should completely remove the unversioned concept
if unversionedKind, ok := s.unversionedTypes[t]; ok {
if gvk, ok := target.KindForGroupVersionKinds([]unversioned.GroupVersionKind{unversionedKind}); ok {
return copyAndSetTargetKind(copy, s, in, gvk)
}
return copyAndSetTargetKind(copy, s, in, unversionedKind)
}
// TODO: should this be a typed error?
return nil, fmt.Errorf("%v is not suitable for converting to %q", t, target)
}
// target wants to use the existing type, set kind and return (no conversion necessary)
for _, kind := range kinds {
if gvk == kind {
return copyAndSetTargetKind(copy, s, in, gvk)
}
}
// type is unversioned, no conversion necessary
if unversionedKind, ok := s.unversionedTypes[t]; ok {
if gvk, ok := target.KindForGroupVersionKinds([]unversioned.GroupVersionKind{unversionedKind}); ok {
return copyAndSetTargetKind(copy, s, in, gvk)
}
return copyAndSetTargetKind(copy, s, in, unversionedKind)
}
out, err := s.New(gvk)
if err != nil {
return nil, err
}
if copy {
copied, err := s.Copy(in)
if err != nil {
return nil, err
}
in = copied
}
flags, meta := s.generateConvertMeta(in)
meta.Context = target
if err := s.converter.Convert(in, out, flags, meta); err != nil {
return nil, err
}
setTargetKind(out, gvk)
return out, nil
}