Kubernetes 源码分析 -- API Server之编解码

--------------------- 
作者:weixin_34037977 
来源:CSDN 
原文:https://blog.csdn.net/weixin_34037977/article/details/87058105

在Kubernetes源码分析-- API Server之API Install篇中,我们了解到K8S可以支持多版本的API,但是Rest API的不同版本中接口的输入输出参数的格式是有差别的,Kubernetes是怎么处理这个问题的呢?另外Kubernetes支持yaml、json两个格式的配置,同时又能够支持json、yaml和pb等格式的编解码进行协议传输,那么Kubernetes又是如何实现各种数据对象的序列化、反序列化的呢?

runtime.Scheme

为了同时解决数据对象的序列化、反序列化与多版本数据对象的兼容和转换问题,Kubernetes设计了一套复杂的机制,首先,它设计了runtime.Scheme这个结构体(k8s.io/apimachinery/pkg/runtime/schema.go),以下是对它的定义。

// Scheme defines methods for serializing and deserializing API objects, a type
// registry for converting group, version, and kind information to and from Go
// schemas, and mappings between Go schemas of different versions. A scheme is the
// foundation for a versioned API and versioned configuration over time.
//
// In a Scheme, a Type is a particular Go struct, a Version is a point-in-time
// identifier for a particular representation of that Type (typically backwards
// compatible), a Kind is the unique name for that Type within the Version, and a
// Group identifies a set of Versions, Kinds, and Types that evolve over time. An
// Unversioned Type is one that is not yet formally bound to a type and is promised
// to be backwards compatible (effectively a "v1" of a Type that does not expect
// to break in the future).
//
// Schemes are not expected to change at runtime and are only threadsafe after
// registration is complete.
type Scheme struct {
	// versionMap allows one to figure out the go type of an object with
	// the given version and name.
	gvkToType map[schema.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.
	typeToGVK map[reflect.Type][]schema.GroupVersionKind

	// unversionedTypes are transformed without conversion in ConvertToVersion.
	unversionedTypes map[reflect.Type]schema.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.
	fieldLabelConversionFuncs map[schema.GroupVersionKind]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 converting behavior.
	converter *conversion.Converter

	// versionPriority is a map of groups to ordered lists of versions for those groups indicating the
	// default priorities of these versions as registered in the scheme
	versionPriority map[string][]string

	// observedVersions keeps track of the order we‘ve seen versions during type registration
	observedVersions []schema.GroupVersion

	// schemeName is the name of this scheme.  If you don‘t specify a name, the stack of the NewScheme caller will be used.
	// This is useful for error reporting to indicate the origin of the scheme.
	schemeName string
}

  

  runtime.Scheme是带版本的API与带版本的配置文件的基础。
  runtime.Scheme定义了以下内容:

    序列化和反序列化API对象的方法

    类型登记处:用于在不同版本的Go shemas之间转换group 、version和kind信息

  从上述代码中可以看到,typeToGVK与gkvToType属性就是为了解决数据对象的序列化与反序列化问题,converter属性则负责不同版本的数据对象转换问题;unversionedKind用于映射哪些能够在任意group和version情况下的类型,key是一个string,也就是kind;fieldLabelConversionFuncs:用于解决数据对象的属性名称的兼容性转换和检验,比如讲需要兼容Pod的spec.Host属性改为spec.nodeName的情况。

  Kubernetes这个设计思路简单方便地建解决多版本的序列化和数据转换问题,下面是runtime.Scheme里序列化、反序列化的核心方法New()的代码:通过查找gkvToType里匹配的诸多类型,以反射方法生成一个空的数据对象:

// New returns a new API object of the given version and name, or an error if it hasn‘t
// been registered. The version and kind fields must be specified.
func (s *Scheme) New(kind schema.GroupVersionKind) (Object, error) {
	if t, exists := s.gvkToType[kind]; exists {
		return reflect.New(t).Interface().(Object), nil
	}

	if t, exists := s.unversionedKinds[kind.Kind]; exists {
		return reflect.New(t).Interface().(Object), nil
	}
	return nil, NewNotRegisteredErrForKind(s.schemeName, kind)
}

  

由于这个方法的实现,也让Scheme实现了ObjectCreater接口。

注意到runtime.Scheme只是实现了一个序列化与类型转换的框架API,提供了注册资源数据类型与转换函数的功能,那么具体的资源数据对象、转换函数又是在哪个包里实现的呢?答案是k8s.io/api/{resource}/{version}/register.go,而核心资源在k8s.io/api/core/v1/register.go中完成注册,以核心资源为例说明一下目录下的关键的代码

  types.go:k8s.io/api/core/v1/types.go
  定义了Rest API接口中设计的所有核心的数据类型
  register.go 负责将types.go里定义的数据类型注册到runtime.Scheme里。

  在register.go中,我们看到这里可以看到两个定义:

var (
	// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
	// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
	SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes)
	localSchemeBuilder = &SchemeBuilder
	AddToScheme        = localSchemeBuilder.AddToScheme
)

  但是只提供了注册的方法,其实还没有执行注册的过程。什么时候执行这个过程呢?

待抄。。。

明天继续。。。

原文地址:https://www.cnblogs.com/waken-captain/p/10560862.html

时间: 2024-11-05 14:49:00

Kubernetes 源码分析 -- API Server之编解码的相关文章

Android中AsyncTask基本用法与源码分析(API 23)

原文链接 http://sparkyuan.github.io/2016/03/23/AsyncTask源码剖析(API 23)/ 转载请注明出处 Android的UI是线程不安全的,想在子线程中更新UI就必须使用Android的异步操作机制,直接在主线程中更新UI会导致程序崩溃. Android的异步操作主要有两种,AsyncTask和Handler.AsyncTask是一个轻量的异步类,简单.可控.本文主要结合API 23的源码讲解一下AsyncTask到底是什么. 基本用法 声明:Andr

kafka源码分析之一server启动分析

1. 分析kafka源码的目的 深入掌握kafka的内部原理 深入掌握scala运用 2. server的启动 如下所示(本来准备用时序图的,但感觉时序图没有思维图更能反映,故采用了思维图): 2.1 启动入口Kafka.scala 从上面的思维导图,可以看到Kafka的启动入口是Kafka.scala的main()函数: def main(args: Array[String]): Unit = { try { val serverProps = getPropsFromArgs(args)

Netty3 源码分析 - NIO server绑定过程分析

一个框架封装的越好,越利于我们快速的coding,但是却掩盖了很多的细节和原理,但是源码能够揭示一切.服务器端代码在指定好ChannelFactory,设定好选项,而后Bootstrap.bind操作就会开启server,接受对端的连接.所以有必要对这后面的过程分析清楚,下图是关键流程.先是构建一个默认的Pipeline,为我们接下来要创建的监听通道服务,这个Pipeline里面会加入一个Binder的上行事件处理器:接下来创建了至关中的NioServerSocketChannel,在构造的过程

兄弟连区块链教程open-ethereum-pool矿池源码分析API分析

ApiServer相关定义 type ApiConfig struct { Enabled bool `json:"enabled"` Listen string `json:"listen"` StatsCollectInterval string `json:"statsCollectInterval"` HashrateWindow string `json:"hashrateWindow"` HashrateLarge

Django源码分析之server

乍见 Django内置的server基本包括两部分:django.core.servers和django.core.handlers 相识 servers.basehttp是Django自身提供的一个用于开发测试的server模块,其中提供的WSGIServer.ServerHandler.WSGIRequestHandler其实都是属于WSGI server,django只不过是对python内置的WSGI模块simple_server做的一层包装. handlers package包括bas

Netty3 源码分析 - NIO server接受连接请求过程分析

当服务器端的server Channel绑定某个端口之后,就可以处理来自客户端的连接请求,而且在构建 NioServerSocketChannelFactory 的时候已经生成了对应的 BossPool 和 WorkerPool,前者管理的 NioServerBoss 就是专门用来接受客户端连接的Selector封装,当,下面是关键的代码: 1. AbstractNioSelector中的run方法代表这个boss thread的核心工作. public void run() { thread 

【Canal源码分析】Canal Server的启动和停止过程

本文主要解析下canal server的启动过程,希望能有所收获. 一.序列图 1.1 启动 1.2 停止 二.源码分析 整个server启动的过程比较复杂,看图难以理解,需要辅以文字说明. 首先程序的入口在CanalLauncher的main方法中. 2.1 加载配置文件 String conf = System.getProperty("canal.conf", "classpath:canal.properties"); Properties properti

nova api源码分析(一)

说明: 源码版本:H版 参考文档:http://www.choudan.net/2013/12/09/OpenStack-WSGI-APP%E5%AD%A6%E4%B9%A0.html 一.前奏 nova api本身作为一个WSGI服务器,对外提供HTTP请求服务,对内调用nova的其他模块响应相应的HTTP请求.分为两大部分,一是创建该服务器时加载的app,这个用来处理请求:一是服务器本身的启动与运行. 目录结构如下: 首先,nova api是作为一个WSGI服务,肯定要查看它的启动过程,查看

Docker源码分析(五):Docker Server的创建

1.Docker Server简介 Docker架构中,Docker Server是Docker Daemon的重要组成部分.Docker Server最主要的功能是:接受用户通过Docker Client发送的请求,并按照相应的路由规则实现路由分发. 同时,Docker Server具备十分优秀的用户友好性,多种通信协议的支持大大降低Docker用户使用Docker的门槛.除此之外,Docker Server设计实现了详尽清晰的API接口,以供Docker用户选择使用.通信安全方面,Docke