【kubernetes v1.21】(kube-apiserver 5)API Aggregation、Endpoints路由与OpenAPI深度分析
Part 5: API Aggregation、Endpoints路由与OpenAPI深度分析
一、模块定位:API Aggregation与Endpoints业务职责
1.1 API Aggregation——Kubernetes API扩展的核心枢纽
API Aggregation(API聚合)是Kubernetes API扩展体系的核心机制,它允许第三方API服务(Aggregated API Server)无缝接入Kubernetes API层级,使集群的API能力可动态扩展。kube-aggregator作为API聚合的实现模块,承担以下核心职责:
- 统一API入口:所有Kubernetes API请求(包括内置资源和扩展资源)统一通过kube-apiserver的聚合层进入,客户端无需感知后端服务的分布
- 动态路由分发:根据APIService资源的定义,将请求路由到本地处理(Local)或远程代理(Proxy),实现透明的请求分发
- API发现聚合:将所有注册的APIService信息聚合为统一的
/apis发现端点,客户端可一次性获取所有可用API组 - OpenAPI规范聚合:将各后端API服务的OpenAPI规范下载、合并为统一的OpenAPI文档
- APIService生命周期管理:管理APIService资源的CRUD,并通过控制器监控其可用性状态
1.2 Endpoints——REST API的HTTP处理层
Endpoints模块(k8s.io/apiserver/pkg/endpoints)是Kubernetes API Server的HTTP请求处理核心,负责将REST Storage对象暴露为HTTP端点。其核心职责包括:
- 路由注册:将
rest.Storage接口映射为HTTP路由,按照GroupVersion组织URL路径结构 - HTTP Handler生成:为每个REST动词(GET/LIST/CREATE/UPDATE/DELETE/WATCH/CONNECT)生成对应的HTTP处理函数
- 请求解析与响应序列化:处理请求参数解码、内容协商(Content Negotiation)、响应编码
- 准入控制集成:在CREATE/UPDATE/DELETE等变更操作中集成Admission Control链
- Watch流式响应:实现基于HTTP长连接或WebSocket的Watch机制
1.3 两者的协作关系
API Aggregation位于请求链的顶层,作为"路由决策者";Endpoints模块位于请求链的底层,作为"请求执行者"。当Aggregator决定某个请求由本地处理时,请求会被委托给Endpoints层执行;当决定由远程服务处理时,请求会被Proxy转发。
二、模块整体结构
2.1 APIGroupVersion结构体
APIGroupVersion是Endpoints模块的核心结构体,它将一组REST Storage对象组织为一个API GroupVersion的HTTP服务:
type APIGroupVersion struct {
Storage map[string]rest.Storage // 资源路径 -> REST Storage映射
Root string // URL根路径(如"/apis")
GroupVersion schema.GroupVersion // 外部GroupVersion标识
OptionsExternalVersion *schema.GroupVersion // 选项对象的API版本
MetaGroupVersion *schema.GroupVersion // 元数据Group版本
RootScopedKinds sets.String // 集群级别资源Kind集合
Serializer runtime.NegotiatedSerializer // 内容协商序列化器
ParameterCodec runtime.ParameterCodec // 参数编解码器
Typer runtime.ObjectTyper // 类型识别器
Creater runtime.ObjectCreater // 对象创建器
Convertor runtime.ObjectConvertor // 版本转换器
ConvertabilityChecker ConvertabilityChecker // 版本可转换性检查
Defaulter runtime.ObjectDefaulter // 默认值填充器
Linker runtime.SelfLinker // SelfLink生成器
UnsafeConvertor runtime.ObjectConvertor // 不安全版本转换器
TypeConverter fieldmanager.TypeConverter // SSA类型转换器
EquivalentResourceRegistry runtime.EquivalentResourceRegistry // 等价资源注册表
Authorizer authorizer.Authorizer // 授权器
Admit admission.Interface // 准入控制器
MinRequestTimeout time.Duration // 最小请求超时
OpenAPIModels openapiproto.Models // OpenAPI模型
MaxRequestBodyBytes int64 // 请求体最大字节数
}
关键字段解析:
- Storage:核心映射表,key是资源路径(如"pods"、“pods/status”),value是实现
rest.Storage接口的对象。系统通过类型断言检测Storage支持哪些动词(Getter/Creater/Lister等) - Serializer:支持多种媒体类型(JSON/YAML/Protobuf)的协商序列化器,决定请求/响应的编码格式
- GroupVersion:标识该APIGroupVersion提供的API版本,如
apps/v1 - Admit:准入控制接口,在CREATE/UPDATE/DELETE操作前执行验证和变更
2.2 APIService类型体系
APIService是kube-aggregator的核心资源类型,定义了一个API扩展的注册信息:
// APIServiceSpec定义APIService的规格
type APIServiceSpec struct {
Service *ServiceReference // 指向后端服务的引用(nil表示本地)
Group string // API组名
Version string // API版本
CABundle []byte // 后端服务的CA证书
InsecureSkipTLSVerify bool // 是否跳过TLS验证
GroupPriorityMinimum int32 // 组优先级最低值
VersionPriority int32 // 版本优先级
}
// ServiceReference引用后端Kubernetes Service
type ServiceReference struct {
Namespace string // 服务命名空间
Name string // 服务名称
Port *int32 // 服务端口
}
// APIServiceStatus定义APIService的状态
type APIServiceStatus struct {
Conditions []APIServiceCondition // 可用性条件列表
}
// APIServiceCondition描述可用性条件
type APIServiceCondition struct {
Type APIServiceConditionType // Available/Kubernetes
Status ConditionStatus // True/False/Unknown
Reason string
Message string
LastTransitionTime metav1.Time
}
类型体系关键特征:
- Local vs Proxy判定:当
Spec.Service == nil时,APIService为本地类型(由kube-apiserver内置处理),如v1.(核心v1组);否则为远程类型,需要代理到后端服务 - Available条件:AvailableController持续监控后端Service/Endpoints的健康状态,更新APIService的Available条件
- 优先级排序:GroupPriorityMinimum和VersionPriority决定API发现中的排序,影响PreferredVersion的选择
2.3 ProxyHandler/LocalHandler
proxyHandler结构体
type proxyHandler struct {
localDelegate http.Handler // 本地委托处理器
proxyCurrentCertKeyContent certKeyFunc // 代理客户端证书动态获取函数
proxyTransport *http.Transport // 代理传输层
serviceResolver ServiceResolver // 服务端点解析器
handlingInfo atomic.Value // 原子存储的proxyHandlingInfo
egressSelector *egressselector.EgressSelector // 出口选择器
}
proxyHandler通过atomic.Value存储proxyHandlingInfo,实现无锁的并发安全读取:
type proxyHandlingInfo struct {
local bool // 是否本地处理
name string // APIService名称
restConfig *restclient.Config // REST客户端配置
transportBuildingError error // 传输构建错误
proxyRoundTripper http.RoundTripper // 代理往返器
serviceName string // 后端Service名称
serviceNamespace string // 后端Service命名空间
serviceAvailable bool // 服务是否可用
servicePort int32 // 后端Service端口
}
apisHandler与apiGroupHandler
这两个处理器负责API发现端点:
- apisHandler:处理
/apis端点,返回所有API组的列表 - apiGroupHandler:处理
/apis/<group>端点,返回特定API组的版本信息
当没有APIService匹配时,apiGroupHandler将请求委托给delegate处理器。
2.4 InstallREST路由注册
InstallREST是APIGroupVersion的核心方法,负责将所有REST Storage注册为HTTP路由:
func (g *APIGroupVersion) InstallREST(container *restful.Container) ([]*storageversion.ResourceInfo, error) {
prefix := path.Join(g.Root, g.GroupVersion.Group, g.GroupVersion.Version)
installer := &APIInstaller{
group: g,
prefix: prefix,
minRequestTimeout: g.MinRequestTimeout,
}
apiResources, resourceInfos, ws, registrationErrors := installer.Install()
versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, staticLister{apiResources})
versionDiscoveryHandler.AddToWebService(ws)
container.Add(ws)
return removeNonPersistedResources(resourceInfos), utilerrors.NewAggregate(registrationErrors)
}
注册流程:
- 构造URL前缀(如
/apis/apps/v1) - 创建APIInstaller实例
- 调用
installer.Install()遍历所有Storage,为每个资源生成路由 - 在WebService上添加版本发现处理器
- 将WebService注册到go-restful Container
- 返回StorageVersion信息(用于存储版本迁移)
三、核心业务逻辑深度解析
3.1 API Aggregator三层委托路由机制
Kubernetes API Server采用了"委托链"(Delegation Chain)架构,形成三层路由委托:
第一层:APIAggregator(最外层)
- 处理所有
/apis/<group>/<version>请求 - 检查APIService注册表,决定路由方向
- Local APIService → 委托给下一层
- Remote APIService → 代理到后端服务
第二层:KubeAPIServer(中间层)
- 处理所有内置Kubernetes资源(Pods/Services/Deployments等)
- 通过APIGroupVersion.InstallREST注册路由
- 未匹配的请求继续委托
第三层:CRD APIServer(最内层)
- 处理CustomResourceDefinition定义的自定义资源
- 动态生成REST Storage和HTTP Handler
3.2 APIService发现与路由(Local vs Proxy)
AddAPIService——注册新APIService
当APIServiceRegistrationController检测到新的APIService资源时,调用AddAPIService:
func (s *APIAggregator) AddAPIService(apiService *v1.APIService) error {
// 1. 检查是否已存在proxyHandler
if proxyHandler, exists := s.proxyHandlers[apiService.Name]; exists {
proxyHandler.updateAPIService(apiService) // 更新已有handler
return nil
}
// 2. 构造代理路径
proxyPath := "/apis/" + apiService.Spec.Group + "/" + apiService.Spec.Version
if apiService.Name == legacyAPIServiceName { // "v1."特殊处理
proxyPath = "/api"
}
// 3. 创建并初始化proxyHandler
proxyHandler := &proxyHandler{...}
proxyHandler.updateAPIService(apiService)
s.proxyHandlers[apiService.Name] = proxyHandler
// 4. 注册到NonGoRestfulMux
s.GenericAPIServer.Handler.NonGoRestfulMux.Handle(proxyPath, proxyHandler)
s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandlePrefix(proxyPath+"/", proxyHandler)
// 5. 如果是legacy组,到此结束
if apiService.Name == legacyAPIServiceName {
return nil
}
// 6. 注册组级发现端点(仅首次)
if !s.handledGroups.Has(apiService.Spec.Group) {
groupPath := "/apis/" + apiService.Spec.Group
groupDiscoveryHandler := &apiGroupHandler{...}
s.GenericAPIServer.Handler.NonGoRestfulMux.Handle(groupPath, groupDiscoveryHandler)
s.handledGroups.Insert(apiService.Spec.Group)
}
return nil
}
proxyHandler.updateAPIService——路由信息更新
updateAPIService根据APIService的Spec决定路由行为:
func (r *proxyHandler) updateAPIService(apiService *apiregistrationv1api.APIService) {
if apiService.Spec.Service == nil {
// Local APIService:设置local=true,请求将委托给localDelegate
r.handlingInfo.Store(proxyHandlingInfo{local: true})
return
}
// Remote APIService:构建代理配置
newInfo := proxyHandlingInfo{
name: apiService.Name,
restConfig: &restclient.Config{
TLSClientConfig: restclient.TLSClientConfig{
Insecure: apiService.Spec.InsecureSkipTLSVerify,
ServerName: apiService.Spec.Service.Name + "." +
apiService.Spec.Service.Namespace + ".svc",
CertData: proxyClientCert,
KeyData: proxyClientKey,
CAData: apiService.Spec.CABundle,
},
},
serviceName: apiService.Spec.Service.Name,
serviceNamespace: apiService.Spec.Service.Namespace,
servicePort: *apiService.Spec.Service.Port,
serviceAvailable: apiregistrationv1apihelper.IsAPIServiceConditionTrue(
apiService, apiregistrationv1api.Available),
}
// 构建RoundTripper
newInfo.proxyRoundTripper, newInfo.transportBuildingError =
restclient.TransportFor(newInfo.restConfig)
r.handlingInfo.Store(newInfo)
}
proxyHandler.ServeHTTP——代理请求执行
关键设计要点:
- atomic.Value无锁读取:handlingInfo使用原子操作存储,避免读操作需要加锁,提升并发性能
- AuthProxy身份透传:通过
transport.NewAuthProxyRoundTripper将用户身份信息(用户名/组/额外信息)以HTTP头形式透传给后端服务 - Upgrade连接处理:检测WebSocket/SPDY升级请求,使用专用RoundTripper处理
- Discovery超时优化:对API发现请求(路径恰好3段,如
/apis/group/version)设置5秒超时,提升客户端响应速度 - Egress选择器:支持网络分区场景,通过egressSelector选择合适的出口拨号器
3.3 GroupVersion REST路由注册(GET/LIST/CREATE/UPDATE/DELETE/WATCH)
APIInstaller核心逻辑
APIInstaller.registerResourceHandlers是路由注册的核心方法,它根据Storage实现的接口自动推断支持的动词和路径:
步骤一:接口检测——推断动词支持
creater, isCreater := storage.(rest.Creater)
namedCreater, isNamedCreater := storage.(rest.NamedCreater)
lister, isLister := storage.(rest.Lister)
getter, isGetter := storage.(rest.Getter)
getterWithOptions, isGetterWithOptions := storage.(rest.GetterWithOptions)
gracefulDeleter, isGracefulDeleter := storage.(rest.GracefulDeleter)
collectionDeleter, isCollectionDeleter := storage.(rest.CollectionDeleter)
updater, isUpdater := storage.(rest.Updater)
patcher, isPatcher := storage.(rest.Patcher)
watcher, isWatcher := storage.(rest.Watcher)
connecter, isConnecter := storage.(rest.Connecter)
步骤二:命名空间判定——决定路径结构
namespaceScoped := scoper.NamespaceScoped()
根据namespaceScoped值,生成两种不同的路径结构:
-
集群级别资源(namespaceScoped=false,如Node/PersistentVolume):
- 资源路径:
/{resource} - 对象路径:
/{resource}/{name}
- 资源路径:
-
命名空间级别资源(namespaceScoped=true,如Pod/Service):
- 资源路径:
/namespaces/{namespace}/{resource} - 对象路径:
/namespaces/{namespace}/{resource}/{name} - 全命名空间路径:
/{resource}(LIST/WATCH跨命名空间)
- 资源路径:
步骤三:Actions生成
根据接口检测结果,生成Action列表:
| Action Verb | 接口要求 | 路径模式(命名空间资源) |
|---|---|---|
| LIST | rest.Lister | GET /namespaces/{ns}/{resource} |
| POST | rest.Creater | POST /namespaces/{ns}/{resource} |
| DELETECOLLECTION | rest.CollectionDeleter | DELETE /namespaces/{ns}/{resource} |
| WATCHLIST | rest.Lister + rest.Watcher | GET /watch/namespaces/{ns}/{resource} |
| GET | rest.Getter | GET /namespaces/{ns}/{resource}/{name} |
| PUT | rest.Updater | PUT /namespaces/{ns}/{resource}/{name} |
| PATCH | rest.Patcher | PATCH /namespaces/{ns}/{resource}/{name} |
| DELETE | rest.GracefulDeleter | DELETE /namespaces/{ns}/{resource}/{name} |
| WATCH | rest.Watcher | GET /watch/namespaces/{ns}/{resource}/{name} |
| CONNECT | rest.Connecter | * /namespaces/{ns}/{resource}/{name} |
步骤四:RequestScope构建
每个Action共享一个RequestScope,携带请求处理所需的全部上下文:
reqScope := handlers.RequestScope{
Serializer: a.group.Serializer,
ParameterCodec: a.group.ParameterCodec,
Creater: a.group.Creater,
Convertor: a.group.Convertor,
Defaulter: a.group.Defaulter,
Typer: a.group.Typer,
UnsafeConvertor: a.group.UnsafeConvertor,
Authorizer: a.group.Authorizer,
TableConvertor: tableProvider,
Resource: a.group.GroupVersion.WithResource(resource),
Subresource: subresource,
Kind: fqKindToRegister,
HubGroupVersion: schema.GroupVersion{Group: fqKindToRegister.Group, Version: runtime.APIVersionInternal},
MetaGroupVersion: metav1.SchemeGroupVersion,
MaxRequestBodyBytes: a.group.MaxRequestBodyBytes,
}
3.4 每个HTTP Handler的请求处理逻辑
3.4.1 GET Handler流程
GET Handler是最简单的读操作处理器,分为两种:GetResource和GetResourceWithOptions。
GetResource核心代码逻辑:
func GetResource(r rest.Getter, scope *RequestScope) http.HandlerFunc {
return getResourceHandler(scope,
func(ctx context.Context, name string, req *http.Request, trace *utiltrace.Trace) (runtime.Object, error) {
options := metav1.GetOptions{}
// 解析query参数
if values := req.URL.Query(); len(values) > 0 {
// export参数已废弃,返回错误
if len(values["export"]) > 0 {
return nil, errors.NewBadRequest("the export parameter is no longer supported")
}
// 解码其他参数到GetOptions
metainternalversionscheme.ParameterCodec.DecodeParameters(values, scope.MetaGroupVersion, &options)
}
return r.Get(ctx, name, &options)
})
}
关键特性:
- export参数废弃:v1.14后不再支持
?export=true参数 - Options解码:通过ParameterCodec将URL查询参数解码为GetOptions
- Subpath支持:GetterWithOptions支持subpath模式(如Proxy端点的路径参数)
3.4.2 CREATE Handler流程
CREATE Handler是最复杂的写操作处理器之一,涉及请求体解码、准入控制、FieldManager等。
CREATE Handler核心特性详解:
- 请求体大小限制:通过
MaxRequestBodyBytes限制请求体大小,防止DoS攻击 - GVK严格校验:请求体中的API版本必须与URL路径中的版本一致,否则返回400
- FieldManager与Server-Side Apply:当启用SSA时,Create操作会自动更新managedFields,跟踪字段管理者
- Mutating Admission Chain:变更准入控制器可修改请求对象(如注入默认值、添加标签)
- 对象过大自动降级:如果因managedFields导致对象超过etcd限制,自动清除managedFields重试
- OwnerReference去重:在变更准入前后两次去重OwnerReference,避免重复引用
- DryRun支持:当启用DryRun特性时,只验证不持久化
3.4.3 UPDATE Handler流程
UPDATE Handler处理PUT请求,实现资源全量替换:
UPDATE Handler特殊逻辑:
- Create-on-Update:当更新的对象不存在时,可能触发Create操作。此时需要额外检查Create授权
- withAuthorization双重授权:对create-on-update场景,先检查Create权限,再执行Validate Admission
- Transformer链:FieldManager和MutatingAdmission作为Transformer注入到Update流程,在存储前修改对象
- 名称校验:请求体中的对象名称必须与URL路径中的名称一致
3.4.4 DELETE Handler流程
DELETE Handler支持优雅删除(Graceful Deletion)和级联删除:
DELETE Handler关键特性:
- 优雅删除:通过DeleteOptions.GracePeriodSeconds支持优雅终止期
- 级联删除控制:OrphanDependents控制是否级联删除关联资源
- 异步删除响应:当资源未立即删除(如Namespace/Pod优雅删除)且请求级联删除时,返回202
- DeleteOptions双重来源:可从请求体或URL查询参数解析
- 删除审计:记录删除操作的审计事件
3.4.5 WATCH Handler流程
Watch Handler是Kubernetes最独特的特性之一,实现了基于HTTP长连接的资源变更事件流:
serveWatch流式处理详解:
Watch机制关键设计:
- 双协议支持:同时支持HTTP Chunked Transfer和WebSocket两种流式传输
- 帧编码:通过Framer将事件封装为帧,支持JSON/Protobuf等编码格式
- 超时抖动:
minRequestTimeout × (1.0 + rand.Float64())随机超时,避免大量Watch同时续期导致etcd压力 - Transform支持:Fixup函数支持Table转换等输出变换,且Table模式只在第一个事件输出表头
- Discovery请求短超时:对
/apis/<group>/<version>这类发现请求,设置5秒短超时 - 优雅退出:通过
req.Context().Done()和timeoutCh双重控制退出
3.5 OpenAPI/V2/V3规范生成
Kubernetes API Server同时支持OpenAPI V2(Swagger)和V3规范,通过聚合机制统一所有API服务的规范。
OpenAPI聚合架构
OpenAPI聚合核心流程:
- PrepareRun阶段:在
APIAggregator.PrepareRun()中创建OpenAPI聚合控制器 - Spec下载:AggregationController为每个远程APIService异步下载其OpenAPI规范
- 规范合并:将所有下载的规范与本地规范合并,处理冲突(路径冲突、定义冲突等)
- 端点注册:
/openapi/v2:返回聚合后的OpenAPI V2 JSON/YAML/openapi/v3:返回聚合后的OpenAPI V3 JSON/YAML(按GroupVersion分组)
- 动态更新:当APIService添加/更新/删除时,自动重新下载和合并规范
V2与V3端点区别:
| 特性 | OpenAPI V2 | OpenAPI V3 |
|---|---|---|
| 端点 | /openapi/v2 |
/openapi/v3 |
| 格式 | 单一文档 | 按GroupVersion分组 |
| Content-Type | application/json |
application/json |
| 结构 | Swagger 2.0 | OpenAPI 3.0 |
| 发现 | 全量一次性下载 | 支持增量/分组下载 |
3.6 Healthz/Ping健康检查
健康检查架构
Kubernetes API Server提供三类健康检查端点,对应不同的检查语义:
HealthChecker接口:
type HealthChecker interface {
Name() string
Check(req *http.Request) error
}
内置HealthChecker实现:
- PingHealthz:最简单的检查器,始终返回nil(健康)
- LogHealthz:检查日志系统是否阻塞(2分钟内未刷盘则不健康)
- InformerSyncHealthz:检查所有Informer是否完成初始同步
- NamedCheck:通用命名检查器,接受自定义检查函数
请求处理流程:
func handleRootHealth(name string, checks ...HealthChecker) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
excluded := getExcludedChecks(r) // 从?exclude=参数获取排除项
for _, check := range checks {
if excluded.Has(check.Name()) {
// 排除的检查项输出"excluded: ok"
continue
}
if err := check.Check(r); err != nil {
// 失败:输出"[-]name failed: reason withheld"
// 日志中记录详细错误
http.Error(w, ..., http.StatusInternalServerError)
return
}
// 成功:输出"[+]name ok"
}
// 全部通过:输出"ok"或详细列表(?verbose)
}
}
关键设计:
- 安全性:公开端点不暴露详细错误信息,仅在日志中记录
- 可排除:通过
?exclude=checkName可排除特定检查项 - 详细模式:
?verbose参数显示每个检查项的状态 - 独立端点:每个检查项有独立路径(如
/healthz/ping、/healthz/etcd) - 指标集成:所有健康检查端点通过
metrics.InstrumentHandlerFunc包装,记录请求指标
3.7 Metrics/Debug端点
Metrics端点
Kubernetes API Server通过Prometheus指标暴露系统运行数据:
/metrics:标准Prometheus指标端点,暴露请求延迟、请求量、etcd延迟等/metrics/slis:SLI(Service Level Indicator)专用指标
关键指标类别:
| 指标 | 说明 |
|---|---|
apiserver_request_total |
API请求总数(按verb/resource/code) |
apiserver_request_duration_seconds |
请求延迟分布 |
apiserver_request_slo_duration_seconds |
SLO相关延迟 |
etcd_request_duration_seconds |
etcd请求延迟 |
apiserver_watch_events |
Watch事件计数 |
apiserver_registered_watchers |
活跃Watch数 |
apiserver_storage_size_bytes |
etcd存储大小 |
Debug端点
/debug/pprof/:Go pprof性能分析端点(需授权)/debug/flags/:命令行标志查看/debug/api_priority_and_fairness/:API优先级和公平性调试信息
四、Mermaid架构图集
图1:Aggregator整体架构图
图2:APIService路由决策图
图3:GroupVersion路由注册图
图4:GET Handler流程图
图8:OpenAPI生成流程图
图9:Healthz架构图
图10:Proxy Handler时序图
图11:API Discovery图
图12:Delegate Chain路由图
五、APIService REST存储层深度解析
5.1 APIService的etcd存储
APIService资源通过genericregistry.Store实现etcd持久化:
type REST struct {
*genericregistry.Store
}
func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST {
strategy := apiservice.NewStrategy(scheme)
store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &apiregistration.APIService{} },
NewListFunc: func() runtime.Object { return &apiregistration.APIServiceList{} },
PredicateFunc: apiservice.MatchAPIService,
DefaultQualifiedResource: apiregistration.Resource("apiservices"),
CreateStrategy: strategy,
UpdateStrategy: strategy,
DeleteStrategy: strategy,
ResetFieldsStrategy: strategy,
TableConvertor: rest.NewDefaultTableConvertor(apiregistration.Resource("apiservices")),
}
// ...
return &REST{store}
}
存储映射:
| 字段 | 说明 |
|---|---|
NewFunc |
创建空APIService对象 |
NewListFunc |
创建空APIServiceList对象 |
PredicateFunc |
过滤/匹配函数(支持Label/Field选择器) |
CreateStrategy |
创建策略(验证、默认值填充) |
UpdateStrategy |
更新策略(验证、转换) |
DeleteStrategy |
删除策略(验证) |
5.2 Status子资源
APIService有专用的Status子资源端点(/apis/apiregistration.k8s.io/v1/apiservices/{name}/status),用于更新APIService的可用性状态:
type StatusREST struct {
store *genericregistry.Store
}
func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo,
createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc,
forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
// forceAllowCreate=false:status子资源不允许create-on-update
return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
}
Status子资源设计要点:
- 共享底层Store:与主资源共享同一个etcd存储,但使用独立的UpdateStrategy
- 禁止Create-on-Update:
forceAllowCreate=false确保status端点不会意外创建新对象 - 专用Strategy:StatusStrategy只验证status字段,不允许修改spec字段
- Table转换:ConvertToTable实现自定义表格输出,显示Service引用和Available状态
5.3 REST Storage注册
NewRESTStorage将APIService的REST存储注册到APIGroupInfo:
func NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource,
restOptionsGetter generic.RESTOptionsGetter, shouldServeBeta bool) genericapiserver.APIGroupInfo {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(
apiregistration.GroupName, aggregatorscheme.Scheme,
metav1.ParameterCodec, aggregatorscheme.Codecs)
// v1beta1版本
if shouldServeBeta && apiResourceConfigSource.VersionEnabled(v1beta1.SchemeGroupVersion) {
storage := map[string]rest.Storage{}
apiServiceREST := apiservicestorage.NewREST(aggregatorscheme.Scheme, restOptionsGetter)
storage["apiservices"] = apiServiceREST
storage["apiservices/status"] = apiservicestorage.NewStatusREST(aggregatorscheme.Scheme, apiServiceREST)
apiGroupInfo.VersionedResourcesStorageMap["v1beta1"] = storage
}
// v1版本
if apiResourceConfigSource.VersionEnabled(v1.SchemeGroupVersion) {
storage := map[string]rest.Storage{}
apiServiceREST := apiservicestorage.NewREST(aggregatorscheme.Scheme, restOptionsGetter)
storage["apiservices"] = apiServiceREST
storage["apiservices/status"] = apiservicestorage.NewStatusREST(aggregatorscheme.Scheme, apiServiceREST)
apiGroupInfo.VersionedResourcesStorageMap["v1"] = storage
}
return apiGroupInfo
}
注册结果:产生以下API端点:
GET /apis/apiregistration.k8s.io/v1/apiservices— 列出所有APIServiceGET /apis/apiregistration.k8s.io/v1/apiservices/{name}— 获取特定APIServicePOST /apis/apiregistration.k8s.io/v1/apiservices— 创建APIServicePUT /apis/apiregistration.k8s.io/v1/apiservices/{name}— 更新APIServicePATCH /apis/apiregistration.k8s.io/v1/apiservices/{name}— 部分更新APIServiceDELETE /apis/apiregistration.k8s.io/v1/apiservices/{name}— 删除APIServicePUT /apis/apiregistration.k8s.io/v1/apiservices/{name}/status— 更新APIService状态
六、控制器协作与PostStartHook
6.1 控制器启动
APIAggregator通过PostStartHook机制启动多个控制器:
| Hook名称 | 功能 | 说明 |
|---|---|---|
start-kube-aggregator-informers |
启动Informer工厂 | 启动Aggregator专用Informer和共享Informer |
apiservice-registration-controller |
APIService注册控制器 | 监控APIService变更,调用AddAPIService/RemoveAPIService |
apiservice-status-available-controller |
可用性控制器 | 检查后端Service/Endpoints,更新Available条件 |
apiservice-openapi-controller |
OpenAPI聚合控制器 | 下载并合并各APIService的OpenAPI规范 |
aggregator-reload-proxy-client-cert |
代理证书热重载 | 动态更新代理客户端证书 |
built-in-resources-storage-version-updater |
存储版本更新器 | 等待apiserver-identity就绪后更新StorageVersion |
6.2 APIServiceRegistrationController
6.3 AvailableConditionController
AvailableConditionController持续监控后端服务的可用性:
- Watch APIService/Service/Endpoints资源变化
- 对于远程APIService,检查对应Service是否有就绪的Endpoints
- 更新APIService的
Available条件:- True:后端服务有就绪Endpoints
- False:后端服务无就绪Endpoints或连接失败
- Unknown:尚未完成首次检查
七、请求处理全景总结
7.1 请求路径总结
| 请求路径 | 处理模块 | 处理方式 |
|---|---|---|
/api/v1/* |
Aggregator → proxyHandler(v1., local) → KubeAPIServer | 本地委托 |
/apis/<group>/<version>/*(内置组) |
Aggregator → proxyHandler(local) → KubeAPIServer | 本地委托 |
/apis/<group>/<version>/*(扩展组) |
Aggregator → proxyHandler(proxy) → Remote Server | 远程代理 |
/apis |
apisHandler | 聚合发现 |
/apis/<group> |
apiGroupHandler | 组级发现 |
/healthz |
healthz handlers | 健康检查 |
/openapi/v2 |
OpenAPI Aggregator | 规范聚合 |
/openapi/v3/* |
OpenAPI V3 Aggregator | V3规范 |
/metrics |
Prometheus handler | 指标暴露 |
本文档基于Kubernetes源码(kube-aggregator和apiserver模块)深度分析,涵盖API Aggregation、Endpoints路由、REST Handler、OpenAPI聚合、健康检查等核心子系统的架构设计与实现逻辑。
更多推荐


所有评论(0)