Illustration of deserialization and conversion in api multi-version in kubernetes

In the previous article, I analyzed how kubernetes performs multi-version management. A key design decoder is mentioned, which is responsible for deserializing the request object into a specific data model. Today, let's understand how it internally implements multi-version management. , Conversion design points

1. The key design of version management

1.1 From topology transformation to star transformation

In normal web development, most of the time, everyone is forward-compatible and updated. In most cases, when the version is updated, it will evolve independently. If you want to convert between multiple versions, the following situation will usually occur. image.pngIf we want to If each version is adapted to all other versions, the complexity will increase exponentially. In kubernetes, it is solved through the design of an internal version. The internal version is a stable version, and all versions are only for target version to implement the conversion, regardless of other versions

1.2 Conversion of Compatible Designs

image.pngThen if a version needs to evolve independently, or add some new fields, modify field names and other destructive updates, then a conversion mechanism is needed to be responsible for the field or data between the current version and the internal version. convert

1.3 The ultimate reflection of transformation

image.pngIn fact, the core goal of conversion is to complete the acquisition of data from the fields of the target object, and then finally perform assignment operations for the corresponding fields of the target object through a series of operations. To complete this operation, you need to use reflection to achieve it. to obtain the corresponding conversion function, execute the conversion function, and complete the target assignment

2. Implementation of key designs

In order to realize the above scheme, the following components are designed in kubernetes: Scheme (responsible for the registration and management of each version), Convert (conversion implementation), Serializer (to realize the deserialization of the corresponding version), let us look at its key designs in turn

2.1 Convert

image.png

Convert realizes the conversion from one target object to another target object. In order to achieve this conversion, kubernetes mainly uses reflection and different versions of conversion functions to complete the conversion.

1. First, we obtain the corresponding attribute field through the target function, and then perform the calculation and assignment operation for the field. 2. If the corresponding field needs to be converted, the corresponding conversion function will be called to perform the assignment operation. If no conversion is required, then will be assigned directly through reflection

2.2 External version to internal version conversion

image.pngWhen building a rest interface, each rest interface will hold a constructor that generates the current version object. When the request comes in, it will first obtain the corresponding decoder through the target version. The decoder will use the current GroupVersionKind for the first step of parsing. First, the byte array is parsed into the current version, and then after parsing into the target object, it will be converted according to the target version

2.3 Scheme

image.pngScheme is responsible for the unified registration and management of each resource version, provides other components with access to corresponding resource objects according to GVK, and also provides operations such as obtaining versions through resource objects. It also holds convert objects internally, which wraps the conversion from source objects to target objects. operate

Scheme object is a composite data structure, which realizes various results, such as typer, defaulter, creater, etc. In many places, the corresponding parameters are filled by directly passing scheme. Its internal key data structure is as follows

Mapping of GVKs to resource types, and which GVKs are supported by the current resource type

	gvkToType map[schema.GroupVersionKind]reflect.Type

	typeToGVK map[reflect.Type][]schema.GroupVersionKind

When you create an object, you can directly instantiate the corresponding object through New

func (s *Scheme) New(kind schema.GroupVersionKind) (Object, error) {
	if t, exists := s.gvkToType[kind]; exists {
		// 利用反射来创建对象
		return reflect.New(t).Interface().(Object), nil
	}
	// 省略相关代码
}

Default initialization function

	defaulterFuncs map[reflect.Type]func(interface{})

Complete the initialization operation according to the corresponding type

func (s *Scheme) Default(src Object) {
	if fn, ok := s.defaulterFuncs[reflect.TypeOf(src)]; ok {
		fn(src)
	}
}

Provide conversion function registration interface, register in convert

func (s *Scheme) AddConversionFunc(a, b interface{}, fn conversion.ConversionFunc) error {
	return s.converter.RegisterUntypedConversionFunc(a, b, fn)
}

3. Learning summary

image.pngThe implementation is undoubtedly complicated. As an industrial design, there are many edge cases that need to be taken care of. Everyone sees different things. This may be the fun of reading the source code. From the above, we can see that the core is actually three points. : Deserialize the HTTP data into the resource object of the current URL, then the target resource object executes the initialization default value function, and finally handles the differences between different versions through convert, and finally operates the internal version in a unified manner. Now, I hope it will be helpful to you > WeChat account: baxiaoshi2020 > Follow the bulletin number to read more source code analysis articles 21 days greenhouse> For more articles, pay attention to www.sreguide.com > This article is published by OpenWrite , a multi- post blog platform

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324072396&siteId=291194637