一、概述:

  kube-ApiServer相当于是k8集群的一个入口,不论通过kubectl还是使用remote api 直接控制,都要经过apiserver。apiserver说白了就是一个server负责监听指定的端口(http/https协议),之后处理不同的请求,只不过加上的很多控制;apiserver是k8s系统中所有对象的增删查改盯的http/restful式服务端,其中盯是指watch操作【watch是apiserver中的重要操作之一】。数据最终存储在分布式一致的etcd存储内,apiserver本身是无状态的,提供了这些数据访问的认证鉴权、缓存、api版本适配转换等一系列的功能。

二、restful基础

  对于http服务和使用go语言实现方式,可以看go-restful的文档例子

  k8s存放在etcd内的存储对象是api.Pod对象(无版本),从不同版本的请求路径标示来操作,例如api/v1,最后获取到的是不同版本,例如v1.Pod的json文本。这里就经历了几个过程,包括:

    1、http client访问/api/v1/pod/xyz, 想要获取到这个Pod的数据

    2、从etcd获取到api.Pod对象

    3、api.Pod对象转换为v1.Pod对象

    4、v1.Pod对象序列化为json或yaml文本

    5、文本通过http的response体,返回给http client

  其中用于处理业务数据的关键数据结构是APIGroupVersion:

 // APIGroupVersion is a helper for exposing rest.Storage objects as http.Handlers via go-restful
// It handles URLs of the form:
// /${storage_key}[/${object_name}]
// Where 'storage_key' points to a rest.Storage object stored in storage.
// This object should contain all parameterization necessary for running a particular API version
//重点数据结构
type APIGroupVersion struct {
//最重要的数据结构,该map的key是用于对,value是rest.Storage结构,用于对接etcd存储,
//在初始化注册时,会把这个map化开,化为真正的rest服务到存储的一条龙服务
Storage map[string]rest.Storage Root string // GroupVersion is the external group version
// 包含api/v1这样的string,用于标示这个实例
GroupVersion unversioned.GroupVersion // RequestInfoResolver is used to parse URLs for the legacy proxy handler. Don't use this for anything else
// TODO: refactor proxy handler to use sub resources
RequestInfoResolver *RequestInfoResolver // OptionsExternalVersion controls the Kubernetes APIVersion used for common objects in the apiserver
// schema like api.Status, api.DeleteOptions, and api.ListOptions. Other implementors may
// define a version "v1beta1" but want to use the Kubernetes "v1" internal objects. If
// empty, defaults to GroupVersion.
OptionsExternalVersion *unversioned.GroupVersion Mapper meta.RESTMapper // Serializer is used to determine how to convert responses from API methods into bytes to send over
// the wire.
//对象序列化和反序列化器
Serializer runtime.NegotiatedSerializer
ParameterCodec runtime.ParameterCodec Typer runtime.ObjectTyper
Creater runtime.ObjectCreater
//可以转换任意一种对象到另一种,只要你事先注入了相应的转换函数
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
Convertor runtime.ObjectConvertor
Copier runtime.ObjectCopier
Linker runtime.SelfLinker Admit admission.Interface
Context api.RequestContextMapper MinRequestTimeout time.Duration // SubresourceGroupVersionKind contains the GroupVersionKind overrides for each subresource that is
// accessible from this API group version. The GroupVersionKind is that of the external version of
// the subresource. The key of this map should be the path of the subresource. The keys here should
// match the keys in the Storage map above for subresources.
SubresourceGroupVersionKind map[string]unversioned.GroupVersionKind
}

三、API分组、多版本的初始化注册(Rest)

  

  k8s采用ApiGroup来管理所有的api分组和版本升级,目前的API分组包括:

    1、核心组,REST路径在/api/v1,但这个路径不是固定的,v1是当前的版本。与之相对应的代码里面的apiVersion字段的值为v1.

    2、扩展组,REST路径在/apis/extensions/$version, 相应的代码里面的apiversion:extensions/$VERSION(eg:apiVersion:extensions/v1beta1),这里的API对象可能会被重新分组;

    3、"componentconfig" 和 "metrics"这些组

  在这个文档里面讲述了实现ApiGroup的几个目标,包括api分组演化,对旧版API的向后兼容(Backwards compatibility),包括用户可以自定义自己的api等。接下来我们看看他么是怎么初始化注册的,这里都是缩减版代码,去掉了其他部分。

  1. api注册入口:

    kubernets/pkg/master/master.go
    func New(c *Config)(*Master, error) {
    m.InstallAPIs(c)
    }

  2.根据Config往APIGroupsInfo内增加组信息,然后通过InstallAPIGroups进行注册

 func (m *Master) InstallAPIs(c *Config) {
if err := m.InstallAPIGroups(apiGroupsInfo); err != nil {
glog.Fatalf("Error in registering group versions:%v", err)
}
}

  3.转换为APIGroupVersion这个关键数据结构,然后进行注册

func (s *GenericAPIServer) installAPIGroup(apiGroupInfo *APIGroupInfo) error {
apiGroupVersion, err := s.getAPIGroupVersion(apiGroupInfo, groupVersion, apiPrefix)
if err := apiGroupVersion.InstallREST(s.HandlerContainer); err != nil {
return fmt.Errorf("Unable to setup API %v: %v", apiGroupInfo, err)
}
}

  4.APIGroupVersion 关键数据结构

kubernetes/pkg/apiserver/apiserver.go
type APIGroupVersion struct {
Storage map[string]rest.Storage
Root string
//GroupVersion is the external group version
GroupVersion unversioned.GroupVersion
}

  5.实际注册的Storage的map如下:

kubernetes/pkg/master/master.go
m.v1ResourcesStorage = map[string]rest.Storage{
"pods": podStorage.Pod,
"pods/attach": podStorage.Attach,
"pods/status": podStorage.Status,
"pods/log": podStorage.Log,
"pods/exec": podStorage.Exec,
"pods/portforward": podStorage.PortForward,
"pods/proxy": podStorage.Proxy,
"pods/binding": podStorage.Binding,
"bindings": podStorage.Binding,

  那么,这里的map[string]rest.Storage最后是怎么变成一个具体的API来提供服务的呢?例如这么一个URL:

    GET /api/v1/namespaces/{namespace}/pods/{name}
 
k8s使用的一个第三方库github.com/emicklei/go-restful,里面提供了一组核心的对象,看例子
数据结构 功能 在k8s内的位置
restful.Container 代表一个http rest服务对象,包括一组restful.WebService genericapiserver.go - GenericAPIServer.HandlerContainer
restful.WebService 由多个restful.Route组成,处理这些路径下所有的特殊的MIME类型等 api_installer.go - NewWebService()
restful.Route 路径——处理函数映射map api_installer.go - registerResourceHandlers
  • 实际注册过程

    kubernetes/pkg/apiserver/api_installer.go
    func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storage, ws *restful.WebService, proxyHandler http.Handler) (*unversioned.APIResource, error) {
    }

    最终的API注册过程是在这个函数中完成的,把一个rest.Storage对象转换为实际的getter, lister等处理函数,并和实际的url关联起来。

4.etcd存储的操作(ORM)

  上面已经基本厘清了从http请求 -> restful.Route -> rest.Storage这条线路,那rest.Storage仅仅是一个接口,有何德何能,可以真正的操作etcd呢?

  这段也是牵涉到多个文件,但还比较清晰,首先,所有的对象都有增删改查这些操作,如果为Pod单独搞一套,Controller单独搞一套,那代码会非常重复,不可复用,所以存储的关键目录是在这里:

  kubernetes/pkg/registry/generic/etcd/etcd.go

  这个文件定义了所有的对etcd对象的操作,get,list,create等,但具体的对象是啥,这个文件不关心;etcd客户端地址,这个文件也不关心。这些信息都是在具体的PodStorage对象创建的时候注入的。以Pod为例子,文件在:

   kubernetes/pkg/registry/pod/etcd/etcd.go

  这里的NewStorage方法,把上述的信息注入了etcd里面去,生成了PodStorage这个对象。

  // REST implements a RESTStorage for pods against etcd
  type REST struct {
  *etcdgeneric.Etcd
  proxyTransport http.RoundTripper
  }

  由于PodStorage.Pod是一个REST类型,而REST类型采用了Go语言的struct匿名内部成员,天然就拥有Get, List等方法。

    kubernetes/pkg/apiserver/api_installer.go

  最后在这里把PodStorage转换成了Getter对象,并最终注册到ApiGroup里面去。

kubernetes之kube-ApiServer代码分析的更多相关文章

  1. sidecar-inject代码分析

    Istio通过对serviceMesh中的每个pod注入sidecar,来实现无侵入式的服务治理能力.其中,sidecar的注入是其能力实现的重要一环(本文主要介绍在kubernetes集群中的注入方 ...

  2. Kubernetes client-go DeltaFIFO 源码分析

    概述Queue 接口DeltaFIFO元素增删改 - queueActionLocked()Pop()Replace() 概述 源码版本信息 Project: kubernetes Branch: m ...

  3. Android代码分析工具lint学习

    1 lint简介 1.1 概述 lint是随Android SDK自带的一个静态代码分析工具.它用来对Android工程的源文件进行检查,找出在正确性.安全.性能.可使用性.可访问性及国际化等方面可能 ...

  4. pmd静态代码分析

    在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...

  5. [Asp.net 5] DependencyInjection项目代码分析-目录

    微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...

  6. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)

    Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...

  7. 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)

    构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...

  8. STM32启动代码分析 IAR 比较好

    stm32启动代码分析 (2012-06-12 09:43:31) 转载▼     最近开始使用ST的stm32w108芯片(也是一款zigbee芯片).开始看他的启动代码看的晕晕呼呼呼的. 还好在c ...

  9. 常用 Java 静态代码分析工具的分析与比较

    常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...

  10. SonarQube-5.6.3 代码分析平台搭建使用

    python代码分析 官网主页: http://docs.sonarqube.org/display/PLUG/Python+Plugin Windows下安装使用: 快速使用: 1.下载jdk ht ...

随机推荐

  1. 不是技术牛人,如何拿到国内IT巨头的Offer

    原地址:http://blog.csdn.net/lsldd/article/details/13506263 不久前,byvoid面阿里星计划的面试结果截图泄漏,引起无数IT屌丝的羡慕敬仰.看看这些 ...

  2. linux之SQL语句简明教程---CREATE INDEX

    索引 (Index) 可以帮助我们从表格中快速地找到需要的资料.举例来说,假设我们要在一本园艺书中找如何种植青椒的讯息.若这本书没有索引的话,那我们是必须要从头开始读,直到我们找到有关种直青椒的地方为 ...

  3. 北京西服定做_衬衫定制_关于我们_Dimoon TLR.

    北京西服定做_衬衫定制_关于我们_Dimoon TLR.

  4. iOS Xcode工程目录的 folder 和 group的区别(蓝色和黄色文件夹的区别)

    1. 来自 http://blog.csdn.net/fanjunxi1990/article/details/9352917 XCode工程目录里面,有时你会发现2个不同颜色的文件夹,一种是蓝色的, ...

  5. pl/sql查询中文乱码

    1.设置系统环境变量 变量名:NLS_LANG 变量值:SIMPLIFIED CHINESE_CHINA.ZHS16GBK 2.修改注册表 regedit->hkey_local_machine ...

  6. how to translate the text of push button

    Background:In a project, the need to translate the buttons on the screen, as shown below,the followi ...

  7. swift锁屏播放,音乐进度更新,专辑,歌手名显示

    我自己用的音乐播放器是自带的AVPlayer 导入头文件#import <MediaPlayer/MediaPlayer.h> 远程控制事件接收与处理- (void)viewWillApp ...

  8. 依赖注入及AOP简述(八)——混合请求模式 .

    2.3.    混合请求模式 上一节讲到了FQCN(全类名)请求模式会带来依赖定义的柔软性较差的问题,因此字符串和全类名混合的模式又应运而生了.比如刚才的Spring中的API方式声明注入点的例子就可 ...

  9. Apache Lens —— 统计数据分析查询接口

    Lens 提供了一个统一数据分析接口.通过提供一个跨多个数据存储的单一视图来实现数据分析任务切分,同时优化了执行的环境.无缝的集成 Hadoop 实现类似传统数据仓库的功能. 该项目主要特性: 简单元 ...

  10. JQuery————基础&&基础选择器

    环境搭建 搭建一个jQuery的开发环境非常方便,可以通过下列几个步骤进行. 下载jQuery文件库 在jQuery的官方网站(http://jquery.com)中,下载最新版本的jQuery文件库 ...