sig-kubernetes
sig-kubernetes copied to clipboard
【提问】apiserver 中 CRD 的 api group 是在哪里创建的呢?
问题描述
在 apiserver 启动过程中,会为不同的资源注册不同的 api。如:kubeApiServer负责内置资源的 api 创建,extensionServer 负责 crd 这种外部资源的 api 创建(只负责 apiextensions.k8s.io/v1 这个组的资源的 api 创建),aggregatorServer 负责 apiregistration 的api创建(只负责 apiextensions.k8s.io 这个组的资源的 api 创建)。
但在我们写 CRD 时,会自定义 CR 的 api 。比如 podlog 是我写的 CRD。执行 kubectl get podlog 命令的时候,会去调 apiServer对应的 api 去获取cr的相关信息:

图中 log.pod.log.io/v1 是我自定义的 api group,那么这个 group 是什么时候创建的呢?它的创建逻辑在哪呢?
apiextension apiserver创建时, 会初始化crdHandler
func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*CustomResourceDefinitions, error) {
...
crdHandler, err := NewCustomResourceDefinitionHandler(
versionDiscoveryHandler,
groupDiscoveryHandler,
s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(),
delegateHandler,
c.ExtraConfig.CRDRESTOptionsGetter,
c.GenericConfig.AdmissionControl,
establishingController,
c.ExtraConfig.ServiceResolver,
c.ExtraConfig.AuthResolverWrapper,
c.ExtraConfig.MasterCount,
s.GenericAPIServer.Authorizer,
c.GenericConfig.RequestTimeout,
c.GenericConfig.MaxRequestBodyBytes,
)
...
}
看一下crdHandler的serveHTTP方法
func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
requestInfo, ok := apirequest.RequestInfoFrom(ctx)
if !ok {
responsewriters.InternalError(w, req, fmt.Errorf("no RequestInfo found in the context"))
return
}
if !requestInfo.IsResourceRequest {
pathParts := splitPath(requestInfo.Path)
// only match /apis/<group>/<version>
// only registered under /apis
if len(pathParts) == 3 {
r.versionDiscoveryHandler.ServeHTTP(w, req)
return
}
// only match /apis/<group>
if len(pathParts) == 2 {
r.groupDiscoveryHandler.ServeHTTP(w, req)
return
}
r.delegate.ServeHTTP(w, req)
return
}
...
}
我们使用crd资源时, 需要先创建crd, 创建crd后, 会有消费者调用sync方法, 这时给groupDiscoveryHandler和versionDiscoveryHandler设置值
# vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go:76
func (c *DiscoveryController) sync(version schema.GroupVersion) error {
...
c.groupHandler.setDiscovery(version.Group, discovery.NewAPIGroupHandler(Codecs, apiGroup))
if !foundVersion {
c.versionHandler.unsetDiscovery(version)
return nil
}
c.versionHandler.setDiscovery(version, discovery.NewAPIVersionHandler(Codecs, version, discovery.APIResourceListerFunc(func() []metav1.APIResource {
return apiResourcesForDiscovery
})))
return nil
}
具体代码, 自己在找代码看看吧, 大概就在这一块~
customresource_discovery_controller
太感谢了!!之前一直没找到这段逻辑,一直在翻 apiserver 启动流程的代码,忽略了 crd 创建的时候会去动态创建 apisever 的路由。大佬你读源码的能力太强了!!!