kubernetes的 Aggregated API是什么呢?它是允许k8s的开发人员编写一个自己的服务,可以把这个服务注册到k8s的api里面,这样,就像k8s自己的api一样,你的服务只要运行在k8s集群里面,k8s 的Aggregate通过service名称就可以转发到你写的service里面去了。
这个设计理念:
第一是增加了api的扩展性,这样k8s的开发人员就可以编写自己的API服务器来公开他们想要的API。集群管理员应该能够使用这些服务,而不需要对核心库存储库进行任何更改。
第二是丰富了APIs,核心kubernetes团队阻止了很多新的API提案。通过允许开发人员将他们的API作为单独的服务器公开,并使集群管理员能够在不对核心库存储库进行任何更改的情况下使用它们,这样就无须社区繁杂的审查了
第三是开发分阶段实验性API的地方,新的API可以在单独的聚集服务器中开发,当它稳定之后,那么把它们封装起来安装到其他集群就很容易了。
第四是确保新API遵循kubernetes约定:如果没有这里提出的机制,社区成员可能会被迫推出自己的东西,这可能会或可能不遵循kubernetes约定。

一句话阐述就是:

Aggregator for Kubernetes-style API servers: dynamic registration, discovery summarization, secure proxy

动态注册、发现汇总、和安全代理。好了基本概念说清楚了,下面就说说实现。
如果你已经已经阅读我上一篇blog就知道,proxy的巨大作用。下面看看这个聚合api的神奇之处。
先看怎么使用,然后再看源代码

apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:name: v1alpha1.custom-metrics.metrics.k8s.io
spec:insecureSkipTLSVerify: truegroup: custom-metrics.metrics.k8s.iogroupPriorityMinimum: 1000versionPriority: 15service:name: apinamespace: custom-metricsversion: v1alpha1

上面定义了资源类型为APIService,service名称为api,空间为custom-metrics的一个资源聚合接口。
下面带大家从源代码的角度来看你
pkg/apiserver/apiservice_controller.go
和k8s其它controller一样,watch变化分发到add、update和delete方法这套原理在此就不赘述了,如果有兴趣可以看我之前写的blog。

apiServiceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc:    c.addAPIService,UpdateFunc: c.updateAPIService,DeleteFunc: c.deleteAPIService,})serviceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc:    c.addService,UpdateFunc: c.updateService,DeleteFunc: c.deleteService,})

主要监听两种资源apiService和service,分别看看

func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService) error {// if the proxyHandler already exists, it needs to be updated. The aggregation bits do not// since they are wired against listers because they require multiple resources to respondif proxyHandler, exists := s.proxyHandlers[apiService.Name]; exists {proxyHandler.updateAPIService(apiService)if s.openAPIAggregationController != nil {s.openAPIAggregationController.UpdateAPIService(proxyHandler, apiService)}return nil}proxyPath := "/apis/" + apiService.Spec.Group + "/" + apiService.Spec.Version// v1. is a special case for the legacy API.  It proxies to a wider set of endpoints.if apiService.Name == legacyAPIServiceName {proxyPath = "/api"}// register the proxy handlerproxyHandler := &proxyHandler{contextMapper:   s.contextMapper,localDelegate:   s.delegateHandler,proxyClientCert: s.proxyClientCert,proxyClientKey:  s.proxyClientKey,proxyTransport:  s.proxyTransport,serviceResolver: s.serviceResolver,}proxyHandler.updateAPIService(apiService)if s.openAPIAggregationController != nil {s.openAPIAggregationController.AddAPIService(proxyHandler, apiService)}s.proxyHandlers[apiService.Name] = proxyHandlers.GenericAPIServer.Handler.NonGoRestfulMux.Handle(proxyPath, proxyHandler)s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandlePrefix(proxyPath+"/", proxyHandler)// if we're dealing with the legacy group, we're done hereif apiService.Name == legacyAPIServiceName {return nil}// if we've already registered the path with the handler, we don't want to do it again.if s.handledGroups.Has(apiService.Spec.Group) {return nil}// it's time to register the group aggregation endpointgroupPath := "/apis/" + apiService.Spec.GroupgroupDiscoveryHandler := &apiGroupHandler{codecs:        Codecs,groupName:     apiService.Spec.Group,lister:        s.lister,delegate:      s.delegateHandler,contextMapper: s.contextMapper,}// aggregation is protecteds.GenericAPIServer.Handler.NonGoRestfulMux.Handle(groupPath, groupDiscoveryHandler)s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandle(groupPath+"/", groupDiscoveryHandler)s.handledGroups.Insert(apiService.Spec.Group)return nil
}

上面path是

proxyPath := "/apis/" + apiService.Spec.Group + "/" + apiService.Spec.Version

结合上面的例子就是/apis/custom-metrics.metrics.k8s.io/v1alpha1.
而处理方法请求的handle就是

proxyHandler := &proxyHandler{contextMapper:   s.contextMapper,localDelegate:   s.delegateHandler,proxyClientCert: s.proxyClientCert,proxyClientKey:  s.proxyClientKey,proxyTransport:  s.proxyTransport,serviceResolver: s.serviceResolver,}proxyHandler.updateAPIService(apiService)

上面的updateAPIService就是更新这个proxy的后端service

func (r *proxyHandler) updateAPIService(apiService *apiregistrationapi.APIService) {if apiService.Spec.Service == nil {r.handlingInfo.Store(proxyHandlingInfo{local: true})return}newInfo := proxyHandlingInfo{restConfig: &restclient.Config{TLSClientConfig: restclient.TLSClientConfig{Insecure:   apiService.Spec.InsecureSkipTLSVerify,ServerName: apiService.Spec.Service.Name + "." + apiService.Spec.Service.Namespace + ".svc",CertData:   r.proxyClientCert,KeyData:    r.proxyClientKey,CAData:     apiService.Spec.CABundle,},},serviceName:      apiService.Spec.Service.Name,serviceNamespace: apiService.Spec.Service.Namespace,}newInfo.proxyRoundTripper, newInfo.transportBuildingError = restclient.TransportFor(newInfo.restConfig)if newInfo.transportBuildingError == nil && r.proxyTransport.Dial != nil {switch transport := newInfo.proxyRoundTripper.(type) {case *http.Transport:transport.Dial = r.proxyTransport.Dialdefault:newInfo.transportBuildingError = fmt.Errorf("unable to set dialer for %s/%s as rest transport is of type %T", apiService.Spec.Service.Namespace, apiService.Spec.Service.Name, newInfo.proxyRoundTripper)glog.Warning(newInfo.transportBuildingError.Error())}}r.handlingInfo.Store(newInfo)
}

这个restConfig就是调用service的客户端参数,其中

ServerName: apiService.Spec.Service.Name + "." + apiService.Spec.Service.Namespace + ".svc",

就是具体的service。
而上面watch service的变化就是为了动态更新这个apiservice后端handler所用的service。

解析kubernetes Aggregated API Servers相关推荐

  1. k8s aggregated api的编写思路

    参考k8s官方的sample-apiserver进行编写(项目地址:GitHub - kubernetes/sample-apiserver: Reference implementation of ...

  2. ios5中apple增加了解析JSON的api——NSJSONSerialization。

    ios5中apple增加了解析JSON的api--NSJSONSerialization.网上已经有人做过测试,NSJSONSerialization在效率上完胜SBJSON.TouchJSON.YA ...

  3. 深入了解Kubernetes REST API的工作方式

    关于Kubernetes REST API的工作方式: 在哪里以及如何定义从REST路径到处理REST调用的函数的映射? 与etcd的交互发生在哪里? 从客户端发出请求到保存在etcd中对象的端到端路 ...

  4. kubernetes 实用 api list

    2019独角兽企业重金招聘Python工程师标准>>> kubernetes 实用 api list 博客分类: Kubernetes 收集整理一些可能较常用的api,结合kuber ...

  5. 图文并茂——从Kubernetes的诞生背景到什么是Kubernetes, 带你深度解析Kubernetes

    在云原生技术发展的浪潮之中,Kubernetes作为容器编排领域的事实标准和云原生领域的关键项目,其诞生与完善有着对应的技术历史背景,了解这个过程,对于系统的理解Kubernetes的核心思想.架构设 ...

  6. kubernetes的api操作和kubectl的源码剖析

    1.kubernetes的api文档的网址: https://kubernetes.io/docs/concepts/overview/kubernetes-api/ 2.kubernetes的go语 ...

  7. Argo 项目入驻 CNCF,一文解析 Kubernetes 原生工作流

    作者 | 遥鹭.郡宝 **导读:**近期,CNCF 技术监督委员会(Technical Oversight Committee,TOC)投票决定接受 Argo 作为孵化级别的托管项目.作为一个新加入的 ...

  8. git项目比对_Argo 项目入驻 CNCF,一文解析 Kubernetes 原生工作流

    作者 | 遥鹭.郡宝 导读:近期,CNCF 技术监督委员会(Technical Oversight Committee,TOC)投票决定接受 Argo 作为孵化级别的托管项目.作为一个新加入的项目,A ...

  9. 云原生之深入解析Kubernetes应用包管理器Helm的保姆级教程和实战

    一.Helm 简介 ① 什么是 Helm? 我们可以将 Helm 看作 Kubernetes 下的 apt-get/yum,Helm 是 kubernetes 的包管理器,Helm 仓库里面只有配置清 ...

最新文章

  1. 用WINHEX合并两个或多个BIN文件
  2. springboot requestmapping 正则_SpringBoot实现优雅的后端接口
  3. Problem for Nazar
  4. linux基础学习(九)
  5. 中切片工具怎么使用_PS软件中钢笔工具的使用,附视频
  6. bzoj 1369: Gem 树形dp
  7. ###《Effective STL》--Chapter2
  8. 2019年Java编程开发值得学习的10大技术
  9. Spring JSF集成教程
  10. crontab 周日_linux之crontab命令
  11. Develop系列-API Guides-简介-应用基础
  12. python-爬取贴吧的时候表情的处理。
  13. 大麻和烟草对表观基因组产生双重影响
  14. 笑对人生,坐看云起云落
  15. 计算机桌面图标不可以移动怎么调,电脑桌面图标不能随意拖动,怎么随意拖动桌面图标...
  16. iOS内存分配与五大区域
  17. 小白如何上手几款微信小程序UI组件库
  18. 电源原副边电气间隔和爬电距离
  19. Android Facebook登录,进来看就对了
  20. 嵌入式开发教程哪家好?linux嵌入式系统开发

热门文章

  1. 树莓派系统烧录,连接电脑,电脑远程桌面控制树莓派(树莓派无屏幕,校园网)
  2. 1.pymysql Warning: (1366, Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\xB1\\xEA...' 解决办法
  3. 基于51单片机的智能电子秤设计
  4. 自己动手玩转深度学习项目
  5. 代理商模式还能走多远?
  6. 魔域服务器修改和宝宝数据,魔域21个修改版本方法一,合BB所需副BB评分如何设定为最高...
  7. OkHttp实现多线程断点续传下载,单例模式下多任务下载管理器,一起抛掉sp,sqlite的辅助吧
  8. 用python来画出高光谱遥感影像的3D立体图
  9. 如何解决QQ在线客服未启用问题
  10. 产品经理会被问到的十道面试题