解析kubernetes Aggregated API Servers

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
全局流量管理 GTM,标准版 1个月
简介: 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

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
23天前
|
自然语言处理 数据可视化 API
淘宝商品评论 API 接口:深度解析用户评论,优化产品与服务
淘宝是领先的中国电商平台,其API为开发者提供商品信息、交易记录及用户评价等数据访问服务。对于获授权的开发者和商家,可通过申请API权限、获取并解析评论数据来进行情感分析和统计,进而优化产品设计、提升服务质量、增强用户互动及调整营销策略。未授权用户可能受限于数据访问。
|
22天前
|
Kubernetes API 调度
Kubernetes 架构解析:理解其核心组件
【8月更文第29天】Kubernetes(简称 K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。它提供了一个可移植、可扩展的环境来运行分布式系统。本文将深入探讨 Kubernetes 的架构设计,包括其核心组件如何协同工作以实现这些功能。
48 0
|
27天前
|
消息中间件 Kafka API
【Kafka消费新风潮】告别复杂,迎接简洁之美——深度解析Kafka新旧消费者API大比拼!
【8月更文挑战第24天】Apache Kafka作为一个领先的分布式流处理平台,广泛用于实时数据管道和流式应用的构建。随着其发展,消费者API经历了重大更新。旧消费者API(包括“低级”和“高级”API)虽提供灵活性但在消息顺序处理上存在挑战。2017年引入的新消费者API简化了接口,自动管理偏移量,支持更强大的消费组功能,显著降低了开发复杂度。通过对比新旧消费者API的代码示例可以看出,新API极大提高了开发效率和系统可维护性。
112 58
|
21天前
|
存储 JSON API
淘系API接口(解析返回的json数据)商品详情数据解析助力开发者
——在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦! 淘宝API接口(如淘宝开放平台提供的API)允许开发者获取淘宝商品的各种信息,包括商品详情。然而,需要注意的是,直接访问淘宝的商品数据API通常需要商家身份或开发者权限,并且需要遵循淘宝的API使用协议。
淘系API接口(解析返回的json数据)商品详情数据解析助力开发者
|
18天前
|
XML JSON API
淘宝京东商品详情数据解析,API接口系列
淘宝商品详情数据包括多个方面,如商品标题、价格、图片、描述、属性、SKU(库存量单位)库存、视频等。这些数据对于买家了解商品详情以及卖家管理商品都至关重要。
|
21天前
|
Java API
Java 8新特性:Lambda表达式与Stream API的深度解析
【7月更文挑战第61天】本文将深入探讨Java 8中的两个重要特性:Lambda表达式和Stream API。我们将首先介绍Lambda表达式的基本概念和语法,然后详细解析Stream API的使用和优势。最后,我们将通过实例代码演示如何结合使用Lambda表达式和Stream API,以提高Java编程的效率和可读性。
|
25天前
|
数据采集 API 开发工具
淘系商品详情数据解析(属性youhui券sku详情图等)API接口开发系列
在电商领域,特别是像淘宝(淘系)这样的平台,商品详情数据对于商家、开发者以及数据分析师来说至关重要。这些数据包括但不限于商品属性、优惠券信息、SKU(Stock Keeping Unit)详情、商品图片、售后保障等。然而,直接访问淘宝的内部API接口通常需要特定的权限和认证,这通常只对淘宝的合作伙伴或内部开发者开放。 不过,对于需要这些数据的第三方开发者或商家,有几种方式可以间接获取或解析淘系商品详情数据: ——在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
|
20天前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
55 0
|
20天前
|
监控 测试技术 API
|
22天前
|
存储 数据采集 API
提升店铺好评秘籍:淘宝商品评论接口与电商 API 接口的深度解析
该接口名为item_review,用于获取淘宝商品评论信息,支持HTTP GET或POST请求,体验API为c0b.cc/R4rbK2。主要请求参数包括商品ID(num_iid)、排序方式(sort)、页码(page)。响应参数涵盖评论内容(rate_content)、评论日期(rate_date)、评论图片(pics)、买家昵称(display_user_nick)、商品属性(auction_sku)

推荐镜像

更多