Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

【提问】apiserver 中 CRD 的 api group 是在哪里创建的呢? #30

Open
lianghao208 opened this issue Aug 15, 2020 · 2 comments
Open

Comments

@lianghao208
Copy link
Member

问题描述

在 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的相关信息:
pod-log crd

图中 log.pod.log.io/v1 是我自定义的 api group,那么这个 group 是什么时候创建的呢?它的创建逻辑在哪呢?

@sundongmin
Copy link

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
}

具体代码, 自己在找代码看看吧, 大概就在这一块~

@lianghao208
Copy link
Member Author

customresource_discovery_controller

太感谢了!!之前一直没找到这段逻辑,一直在翻 apiserver 启动流程的代码,忽略了 crd 创建的时候会去动态创建 apisever 的路由。大佬你读源码的能力太强了!!!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants