解析kubernetes Aggregated API Servers

简介: kubernetes的 Aggregated API是什么呢?它是允许k8s的开发人员编写一个自己的服务,可以把这个服务注册到k8s的api里面,这样,就像k8s自己的api一样,你的服务只要运行在k8s集群里面,k8s 的Aggregate通过service名称就可以转发到你写的service里面去了。

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: true

group: custom-metrics.metrics.k8s.io

groupPriorityMinimum: 1000

versionPriority: 15

service:

name: api

namespace: custom-metrics

version: 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 respond

if 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 handler

proxyHandler := &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] = proxyHandler

s.GenericAPIServer.Handler.NonGoRestfulMux.Handle(proxyPath, proxyHandler)

s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandlePrefix(proxyPath+"/", proxyHandler)


// if we're dealing with the legacy group, we're done here

if 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 endpoint

groupPath := "/apis/" + apiService.Spec.Group

groupDiscoveryHandler := &apiGroupHandler{

codecs: Codecs,

groupName: apiService.Spec.Group,

lister: s.lister,

delegate: s.delegateHandler,

contextMapper: s.contextMapper,

}

// aggregation is protected

s.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

1

结合上面的例子就是/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.Dial

default:

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。

本文转自CSDN-解析kubernetes Aggregated API Servers

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
27天前
|
存储 缓存 算法
淘宝买家秀 API 深度开发:多模态内容解析与合规推荐技术拆解
本文详解淘宝买家秀接口(taobao.reviews.get)的合规调用、数据标准化与智能推荐全链路方案。涵盖权限申请、多模态数据清洗、情感分析、混合推荐模型及缓存优化,助力开发者提升审核效率60%、商品转化率增长28%,实现UGC数据高效变现。
|
30天前
|
XML 数据采集 API
用Lxml高效解析XML格式数据:以天气API为例
免费Python教程:实战解析中国天气网XML数据,详解Lxml库高效解析技巧、XPath用法、流式处理大文件及IP封禁应对策略,助你构建稳定数据采集系统。
146 0
|
1月前
|
API 开发者 数据采集
高效获取淘宝商品详情:API 开发实现链接解析的完整技术方案
2025反向海淘新机遇:依托代购系统,聚焦小众垂直品类,结合Pandabay数据选品,降本增效。系统实现智能翻译、支付风控、物流优化,助力中式养生茶等品类利润翻倍,新手也能快速入局全球市场。
高效获取淘宝商品详情:API 开发实现链接解析的完整技术方案
|
1月前
|
数据采集 存储 供应链
第三方电商数据 API 数据来源深度解析:合规与稳定背后的核心逻辑
本文揭秘第三方电商数据API的底层逻辑:通过官方授权、生态共享与合规采集三重来源,结合严格清洗校验,确保数据稳定、合规、高质。企业选型应关注来源合法性与场景匹配度,避开数据陷阱,实现真正数据驱动增长
|
1月前
|
存储 监控 安全
132_API部署:FastAPI与现代安全架构深度解析与LLM服务化最佳实践
在大语言模型(LLM)部署的最后一公里,API接口的设计与安全性直接决定了模型服务的可用性、稳定性与用户信任度。随着2025年LLM应用的爆炸式增长,如何构建高性能、高安全性的REST API成为开发者面临的核心挑战。FastAPI作为Python生态中最受青睐的Web框架之一,凭借其卓越的性能、强大的类型安全支持和完善的文档生成能力,已成为LLM服务化部署的首选方案。
|
2月前
|
安全 NoSQL API
拼多多:通过微信支付API实现社交裂变付款的技术解析
基于微信JSAPI构建社交裂变支付系统,用户发起拼单后生成预订单与分享链接,好友代付后通过回调更新订单并触发奖励。集成微信支付、异步处理、签名验签与Redis关系绑定,提升支付成功率与裂变系数,实现高效安全的闭环支付。
376 0
|
2月前
|
存储 算法 API
唯品会智能分仓API技术解析:基于收货地址自动匹配最近仓库
唯品会智能分仓API通过地理编码与Haversine距离算法,自动将订单匹配至最近仓库,提升配送效率、降低成本。本文详解其技术原理、实现步骤与应用优势,助力开发者构建高效物流系统。(239字)
209 0
|
2月前
|
人工智能 供应链 API
淘宝API商品详情接口全解析:从基础数据到深度挖掘
淘宝API商品详情接口不仅提供基础数据,更通过深度挖掘实现从数据到洞察的跨越。开发者需结合业务场景选择合适分析方法,利用AI标签、区块链溯源等新技术,最终实现数据驱动的电商业务创新。
|
2月前
|
JSON 缓存 自然语言处理
多语言实时数据微店商品详情API:技术实现与JSON数据解析指南
通过以上技术实现与解析指南,开发者可高效构建支持多语言的实时商品详情系统,满足全球化电商场景需求。

热门文章

最新文章

推荐镜像

更多