kubernetes之kube-ApiServer代码分析

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 一、概述:  kube-ApiServer相当于是k8集群的一个入口,不论通过kubectl还是使用remote api 直接控制,都要经过apiserver。apiserver说白了就是一个server负责监听指定的端口(http/https协议),之后处理不同的请求,只不过加上的很多控制;apiserver是k8s系统中所有对象的增删查改盯的http/restful式服务端,其中盯是指watch操作【watch是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里面去。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
5月前
|
Kubernetes 负载均衡 Cloud Native
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived
289 0
|
负载均衡 Kubernetes Cloud Native
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived(二)
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived
300 0
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived(二)
|
Kubernetes 负载均衡 Cloud Native
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived(一)
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived
277 0
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived(一)
|
Kubernetes Cloud Native 容器
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived(三)
云原生|kubernetes|kubeadm部署高可用集群(二)---kube-apiserver高可用+etcd外部集群+haproxy+keepalived
172 0
|
Kubernetes Ubuntu API
Kubernetes API 分析 ( Kube-apiserver )
kubernetes 概览 以下是 k8s 的整体架构,在 master 节点上主要是 kube-apiserver(整合了 kube-aggregator),还有 kube-scheduler,以及 kube-controller-manager,包括后端存储 etcd。
2584 0
|
1天前
|
Kubernetes Cloud Native Ubuntu
云原生之旅:Kubernetes集群搭建与应用部署
【8月更文挑战第65天】本文将带你进入云原生的世界,通过一步步指导如何在本地环境中搭建Kubernetes集群,并部署一个简单的应用。我们将使用Minikube和Docker作为工具,探索云原生技术的魅力所在。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和实践技巧。
|
5天前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
|
1月前
|
存储 Kubernetes 负载均衡
CentOS 7.9二进制部署K8S 1.28.3+集群实战
本文详细介绍了在CentOS 7.9上通过二进制方式部署Kubernetes 1.28.3+集群的全过程,包括环境准备、组件安装、证书生成、高可用配置以及网络插件部署等关键步骤。
181 3
CentOS 7.9二进制部署K8S 1.28.3+集群实战
|
1月前
|
Kubernetes 负载均衡 前端开发
二进制部署Kubernetes 1.23.15版本高可用集群实战
使用二进制文件部署Kubernetes 1.23.15版本高可用集群的详细教程,涵盖了从环境准备到网络插件部署的完整流程。
53 2
二进制部署Kubernetes 1.23.15版本高可用集群实战
|
1月前
|
存储 Kubernetes 测试技术
k8s使用pvc,pv,sc关联ceph集群
文章介绍了如何在Kubernetes中使用PersistentVolumeClaim (PVC)、PersistentVolume (PV) 和StorageClass (SC) 来关联Ceph集群,包括创建Ceph镜像、配置访问密钥、删除默认存储类、编写和应用资源清单、创建资源以及进行访问测试的步骤。同时,还提供了如何使用RBD动态存储类来关联Ceph集群的指南。
50 7
下一篇
无影云桌面