apiserver源码分析——启动流程

本文详细描述了KubernetesAPIServer的启动过程,包括创建GenericAPIServer、实例化Instance和AggregatorServer,以及安装核心资源组和旧版API的过程,重点阐述了ApiGroup的注册机制和go-restful框架的应用。

}

storage[“customresourcedefinitions”] = customResourceDefinitionStorage

storage[“customresourcedefinitions/status”] = customresourcedefinition.NewStatusREST(Scheme, customResourceDefinitionStorage)

apiGroupInfo.VersionedResourcesStorageMap[v1beta1.SchemeGroupVersion.Version] = storage

}

//另一个版本的类似,不作展示

//InstallAPIGroup注册

if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {

return nil, err

}

}

KubeAPIServer

KubeAPIServer处理k8s内置资源请求,它的创建流程与APIExtensionServer类似,包含下面几个步骤

  • 创建GeneriAPIServer

  • 实例化Instance

  • installLegacyAPI

  • installAPI

其中Instance是KubeAPIServer的Server对象。KubeAPIServer创建和Install的APIGroup需要调用两个方法,一个是installLegacyAPI,另一个是installAPI,原因在于k8s的apiGroup分了/api和/apis两种。初期的资源其实没有apiGroup这个概念,而后期引入了groupVersion为了兼容原有的才把旧的资源类型的URI地址都归属于/api这个路径下的,新的全部在/apis这个路径下,因此在创建注册APIGroup时都分了两类。代码如下

func CreateKubeAPIServer(kubeAPIServerConfig *controlplane.Config, delegateAPIServer genericapiserver.DelegationTarget) (*controlplane.Instance, error) {

kubeAPIServer, err := kubeAPIServerConfig.Complete().New(delegateAPIServer)

if err != nil {

return nil, err

}

return kubeAPIServer, nil

}

//代码位于 /vendor/k8s.io/kube-aggregrator/pkg/apiserver/apiserver.go

func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*Instance, error) {

//创建Generic

s, err := c.GenericConfig.New(“kube-apiserver”, delegationTarget)

//1.14版本的是Master,当前版本是Instance

m := &Instance{

GenericAPIServer: s,

ClusterAuthenticationInfo: c.ExtraConfig.ClusterAuthenticationInfo,

}

//实例化核心API

if c.ExtraConfig.APIResourceConfigSource.VersionEnabled(apiv1.SchemeGroupVersion) {

legacyRESTStorageProvider := corerest.LegacyRESTStorageProvider{

StorageFactory: c.ExtraConfig.StorageFactory,

ProxyTransport: c.ExtraConfig.ProxyTransport,

KubeletClientConfig: c.ExtraConfig.KubeletClientConfig,

EventTTL: c.ExtraConfig.EventTTL,

ServiceIPRange: c.ExtraConfig.ServiceIPRange,

SecondaryServiceIPRange: c.ExtraConfig.SecondaryServiceIPRange,

ServiceNodePortRange: c.ExtraConfig.ServiceNodePortRange,

LoopbackClientConfig: c.GenericConfig.LoopbackClientConfig,

ServiceAccountIssuer: c.ExtraConfig.ServiceAccountIssuer,

ExtendExpiration: c.ExtraConfig.ExtendExpiration,

ServiceAccountMaxExpiration: c.ExtraConfig.ServiceAccountMaxExpiration,

APIAudiences: c.GenericConfig.Authentication.APIAudiences,

}

if err := m.InstallLegacyAPI(&c, c.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider); err != nil {

return nil, err

}

}

restStorageProviders := []RESTStorageProvider{…}

//InstallAPIs,内部包含InstallAPIGroup

if err := m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders…); err != nil {

return nil, err

}

}

注册核心apiGroups

进入m.InstallLegacyAPI,这个方法包含了实例化ApiGroupInfo和InstalAPIGroup两个操作,这部分资源是k8s的核心资源

func (m *Instance) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) error {

//实例化ApiGroupInfo

legacyRESTStorage, apiGroupInfo, err := legacyRESTStorageProvider.NewLegacyRESTStorage(restOptionsGetter)

if err != nil {

return fmt.Errorf(“error building core storage: %v”, err)

}

controllerName := “bootstrap-controller”

coreClient := corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig)

bootstrapController := c.NewBootstrapController(legacyRESTStorage, coreClient, coreClient, coreClient, coreClient.RESTClient())

m.GenericAPIServer.AddPostStartHookOrDie(controllerName, bootstrapController.PostStartHook)

m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook)

//相当于调用InstallAPIGroup

if err := m.GenericAPIServer.InstallLegacyAPIGroup(genericapiserver.DefaultLegacyAPIPrefix, &apiGroupInfo); err != nil {

return fmt.Errorf(“error in registering group versions: %v”, err)

}

return nil

}

实例化APIGroupInfo的代码局部如下,代码篇幅较长,只摘取pod一部分的源码展示,代码位于/pkg/registry/core/rest/storage_core.go

func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generic.RESTOptionsGetter) (LegacyRESTStorage, genericapiserver.APIGroupInfo, error) {

apiGroupInfo := genericapiserver.APIGroupInfo{

PrioritizedVersions: legacyscheme.Scheme.PrioritizedVersionsForGroup(“”),

VersionedResourcesStorageMap: map[string]map[string]rest.Storage{},

Scheme: legacyscheme.Scheme,

ParameterCodec: legacyscheme.ParameterCodec,

NegotiatedSerializer: legacyscheme.Codecs,

}

podStorage, err := podstore.NewStorage(

restOptionsGetter,

nodeStorage.KubeletConnectionInfo,

c.ProxyTransport,

podDisruptionClient,

)

restStorageMap := 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.LegacyBinding,

}

}

m.GenericAPIServer.InstallLegacyAPIGroup的第一个参数是apiPrefix,值是/api;第二个参数是上面创建好的,包含资源存储方式的apiGroupInfo

与InstallAPIGroup类似地,InstallLegacyAPIGroup需要经过两层调用才会到达InstallREST,调用链如下

m.GenericAPIServer.InstallLegacyAPIGroup

|–s.installAPIResources

|–apiGroupVersion.InstallREST

InstallREST的入参是restful.Container,他是golang http框架go-restful里面的一个重要对象,在InstallREST里面构造出installer,installer包含资源的存储方法和资源对应api的前缀,利用installer.Install()来创建出go-restful的webservice,webservice加入到传入得container,即完成api的注册。

代码位于/vendor/k8s.io/apiserver/pkg/endpoints/groupversion.go

func (g *APIGroupVersion) InstallREST(container *restful.Container) error {

prefix := path.Join(g.Root, g.GroupVersion.Group, g.GroupVersion.Version)

installer := &APIInstaller{

group: g,

prefix: prefix,

minRequestTimeout: g.MinRequestTimeout,

}

apiResources, ws, registrationErrors := installer.Install()

versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, staticLister{apiResources})

versionDiscoveryHandler.AddToWebService(ws)

container.Add(ws)

return utilerrors.NewAggregate(registrationErrors)

}

installer.Install()方法的边幅很长,它既然创建了webservice,api中各个URL的路由注册,handler的绑定也会在里面实现。由于这部分代码也涉及到apiserver如何响应处理一个http请求,本篇先不探讨

go-restful框架

不过上面提及到go-restful框架的几个概念,在这里进行一个简单的科普

  • container:在http的角度就是一个Server,里面就包含若干个webservice

  • webservice:webservice从结构来说是承上启下的一个角色,它包含了一组route,而且这组route都会有一个共同的basePath或者说他们的URL的prefix是相同的

  • route:route对应具体的一个URL,它需要指定具体的路径Path,请求方法Method和处理函数Handler,以及一些参数Parameter等等。

他们的层次结构如下

container

|–webservice

|–Route

AggregratorServer

用于处理聚合进来的api请求,实际是做七层转发,它的创建流程与APIExtensionServer的最为相似

  • 创建GeneriAPIServer

  • 实例化Aggregrator

  • 实例化APIGroupInfo

  • InstallAPIGroup

实际创建AggregratorServer的代码位于/vendor/k8s.io/kube-aggregrator/pkg/apiserver/apiserver.go

func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.DelegationTarget) (*APIAggregator, error) {

//创建GeneriAPIServer

genericServer, err := c.GenericConfig.New(“kube-aggregator”, delegationTarget)

//实例化Aggregrator

s := &APIAggregator{…}

//实例化APIGroupInfo

apiGroupInfo := apiservicerest.NewRESTStorage(c.GenericConfig.MergedResourceConfig, c.GenericConfig.RESTOptionsGetter)

//InstallAPIGroup

if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {

return nil, err

}

}

运行http server

api的路由绑定完毕,最后就是要把http server跑起来,prepared.Run调用的是由preparedGenericAPIServer实现的Run方法,经过多层调用最终把server跑起来,调用链如下

prepared.Run /vendor/k8s.io/kube-aggregrator/pkg/apiserver/apiserver.go

|–s.runnable.Run(stopCh)

|==preparedGenericAPIServer.Run /vendor/k8s.io/apiserver/pkg/server/genericapiserver.go

|–s.NonBlockingRun

|–s.SecureServingInfo.Serve /vendor/k8s.io/kube-aggregrator/pkg/server/secure_serving.go

|–&http.Server{}

|–RunServer

http server的对象是在SecureServingInfo.Serve创建的,即调用链的s.SecureServingInfo.Serve,最终让server开始监听是在RunServer处。它接收了http.Server作为参数。至此apiserver运行起来,接收来自各个组件或客户端的请求。

小结

本篇讲述了k8s-apiserver的启动流程,介绍了apiserver包含了3个server组件,apiserver的服务实际上由这三个组件提供,讲述了他们创建流程,实例化底层的GenericServer,实例化各自的Server类,实例化ApiGroupInfo来建立资源与存储操作间的映射关系,最后InstallAPI。还专门挑了k8s核心资源类型的ApiGroup注册过程介绍。整个启动过程的调用链如下

Run /cmd/kube-apiserver/app/server.go

|–CreateServerChain

| |–CreateKubeAPIServerConfig

| | |–buildGenericConfig

| | |–genericapiserver.NewConfig

| | |–s.Authentication.ApplyTo

| | |–BuildAuthorizer

| | |–s.Admission.ApplyTo

| |–createAPIExtensionsConfig

| |–createAPIExtensionsServer

| | |–apiextensionsConfig.Complete().New /vendor/k8s.io/apiextensions-apiserver/apiserver.go

| | |–c.GenericConfig.New

| | |–&CustomResourceDefinitions{}

| | |–genericapiserver.NewDefaultAPIGroupInfo

| | |–s.GenericAPIServer.InstallAPIGroup

| |–CreateKubeAPIServer

| | |–kubeAPIServerConfig.Complete().New /pkg/controlplane/instance.go

| | | |–c.GenericConfig.New

| | | |–&Instance{}

| | | |–m.InstallLegacyAPI /pkg/controlplane/instance.go

| | | | |–legacyRESTStorageProvider.NewLegacyRESTStorage /pkg/registry/core/rest/storage_core.go

| | | | |–m.GenericAPIServer.InstallLegacyAPIGroup ##相当于新版本的InstallAPIGroup

| | | | | |–s.installAPIResources
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
在这里插入图片描述

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-vb921uul-1712092392380)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值