kubernetes之kube-ApiServer代码分析

一、概述:

  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:

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

三、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进行注册

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

  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里面去。

时间: 2025-01-31 10:51:00

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

Alipay UED推出网站代码分析插件:Monster

Monster 是 Alipay UED 推出的网站代码分析.质量检测及评分的浏览器扩展,它能智能分析CSS.JS.HTML内容并生动形象展示网页得分情况(类似YSlow).它是一个开源项目,您可以在GoogleCode中心检出MonsterForChrome项目源代码.不久会推出Firefox版扩展. Monster主要检测规则: 检测是否有重复ID的标签: 检测是否使用内联标签嵌套块级标签,如a嵌套div: 检测https协议页面,是否使用了http协议的图片.JS.CSS等: 检测comp

Javascript日期级联组件代码分析及demo

最近研究下JS日期级联效果 感觉还不错,然后看了下kissy也正好有这么一个 组件,也看了下源码,写的还不错,通过google最早是在2011年 淘宝的虎牙(花 名)用原审JS写了一个(貌似据说是从YUI那边重构下的) 具体的可以看他的 博 客园 , 感觉kissy组件源码 思路也是和YUI类似 所以我今天的基本思路也和他们 的一样 只是通过自己分析下及用自己的方式包装下. 基本原理 1.传参中有 '年份下拉框dom节点', '月份下拉框dom节点', '天数下拉框dom 节点', "开始日期&

C语言中的数组和指针汇编代码分析实例

  这篇文章主要介绍了C语言中的数组和指针汇编代码分析实例,本文用一则C语言例子来得到对应的汇编代码,并一一注解每句汇编代码的含义,需要的朋友可以参考下 今天看<程序员面试宝典>时偶然看到讲数组和指针的存取效率,闲着无聊,就自己写了段小代码,简单分析一下C语言背后的汇编,可能很多人只注重C语言,但在实际应用当中,当出现问题时,有时候还是通过分析汇编代码能够解决问题.本文只是为初学者,大牛可以飘过~ C源代码如下: 代码如下: #include "stdafx.h" int

传智播客c/c++公开课学习笔记--C语言与木马恶意代码分析和360安全防护揭秘

黑客代码分析与预防 笔记 [课程简介] C/C++语言是除了汇编之外,最接近底层的计算机语言,目前windows,linux,iOS,Android等主流操作系统都是用C/C++编写的,所以很多病毒.木马也都是用C/C++实现的.课程的目的就是通过C语言揭秘木马和各种远程控制软件的实现原理以及如何防护.  [课程知识点] 1.木马入侵系统的方式: 2.木马入侵到宿主目标后的关键行为分析: 3.可信任端口以及端口扫描技术: 4.远程控制的实现代码实现: 5.恶意代码中使用TCP.UDP协议与防火墙

【ARM】Uboot代码分析

一.摘要 这篇文章主要对BootLoader(UBoot)的源码进行了分析,并对UBoot的移植略作提及.  BootLoader的总目标是正确调用内核的执行,由于大部分的BoorLoader都依赖于CPU的体系结构.因此大部分的BootLoader都分为两个步骤启动.依赖于CPU体系结构(如设备初始化等)的代码都放在stage1.而stage2一般使用C语言实现,能够实现更加复杂的功能,代码的可移植性也提高. 二.本文提纲 1. 摘要 2. 本文提纲 3. UBoot启动过程 4. Stage

谁有基于用户的推荐系统或者协同过滤的算法和代码分析啊

问题描述 求个大数据的大神给个基于用户的推荐系统或者协同过滤的算法和代码分析啊我有部分代码但是不知道怎么在Eclipse上实现求解答啊1.publicclassAggregateAndRecommendReducerextendsReducer<VarLongWritable,VectorWritable,VarLongWritable,RecommendedItemsWritable>{...publicviodreduce(VarLongWritablekey,Iterable<Ve

免费的Lucene 原理与代码分析完整版下载

Lucene是一个基于Java的高效的全文检索库.那么什么是全文检索,为什么需要全文检索?目前人们生活中出现的数据总的来说分为两类:结构化数据和非结构化数据.很容易理解,结构化数据是有固定格式和结构的或者有限长度的数据,比如数据库,元数据等.非结构化数据则是不定长或者没有固定格式的数据,如图片,邮件,文档等.还有一种较少的分类为半结构化数据,如XML,HTML等,在一定程度上我们可以将其按照结构化数据来处理,也可以抽取纯文本按照非结构化数据来处理.非结构化数据又称为全文数据.,对其搜索主要有两种

【C/C++学院】0907-象棋五子棋代码分析/寻找算法以及排序算法

象棋五子棋代码分析 编译代码报错: 错误 1 error MSB8031: Building an MFC project for a non-Unicode character set is deprecated. You must change the project property to Unicode or download an additional library. See http://go.microsoft.com/fwlink/p/?LinkId=286820 for mo

AngularJS PhoneCat代码分析

AngularJS 官方网站提供了一个用于学习的示例项目:PhoneCat.这是一个Web应用,用户可以浏览一些Android手机,了解它们的详细信息,并进行搜索和排序操作. 本文主要分析 AngularJS 官方网站提供的一个用于学习的示例项目 PhoneCat 的构建.测试过程以及代码的运行原理.希望能够对 PhoneCat 项目有一个更加深入全面的认识.这其中包括以下内容: 该项目如何运行起来的 该项目如何进行前端单元测试 AngularJS 相关代码分析 以下内容如有理解不正确,欢迎指正

meter资源监控器开发——关键代码分析

代码分析也无需事无巨细皆列而剖之,只要找到关键所在也就是了:又不然列一堆的声明上来,纵然有人有耐心看下去,我也没耐心写下去啊.特别关注了三 个类,Stats.MonitorPerformancePanel.MonitorGraph.分别是获取解析得到的数据.监控器面板显示和监视器上的 图像绘制.下面选取了一些关键代码来进行分析: 首先是Stats.java,下面是计算内存使用率的方法 public static int calculateMemoryLoad(Status stat) {   d