2.2.4 Discovery 原理
在分析 Discovery 原理之前,首先介绍一下 Kubernetes 的资源模型,图 2-7 是获取所有 Deployements 资源的 RESTful API,URL 中各字段含义如下。
(1) apps 是 Group 资源组,包含一组资源操作的集合。
(2) v1 是 Version 资源版本,用于区分不同 API 的稳定程度及兼容性。
(3) Deployments 是 Resource 资源信息,用于区分不同的资源 API。
图 2-7 Deployments 资源 URL
由于历史原因,Kubernetes 中有两种资源组:有组名资源组和无组名资源组(也叫核心资源组,Core Groups)。上面介绍的就是有组名资源组,而 Pods、Services 等资源属于无组名资源组,图 2-8 是获取 Pods 资源的 RESTful API,其中未包含 Group 信息,但拥有 Version 和 Resource 信息。
图 2-8 Pods 资源 URL
常用的 Kubectl 命令,当执行 kubectl api-versions 和 kubectl api-resources 命令时,返回的就是 GVR(Group,Version,Resource)信息(见代码清单 2-29)。
代码清单 2-29
$ kubectl api-versions admissionregistration.k8s.io/v1 admissionregistration.k8s.io/v1beta1 apiextensions.k8s.io/v1 apiextensions.k8s.io/v1beta1 apiregistration.k8s.io/v1 apiregistration.k8s.io/v1beta1 apps/v1 ... $ kubectl api-resources NAME SHORTNAMES APIGROUP NAMESPACED KIND bindings true Binding componentstatuses cs false ComponentStatus configmaps cm true ConfigMap endpoints ep true Endpoints events ev true Event ...
前面我们介绍的是标准的 DiscoveryClient ,由于 GVR 信息变动很少,因此,可以将 Kubernetes APIServer 返回的 GVR 信息缓存在本地,以此减轻 Kubernetes APIServer 的压力,这里可以使用 Discover/Cached 目录下的两个客户端:CachedDiscoveryClient 和 memCacheClient,分别将 GVR 信息缓存到本地文件(~ /.kube/cache 和 ~ /.kube/http-cache)和内存中。
Kubectl 的 apiVersions 命令就是利用 CachedDiscoveryClient 来实现的,如 APIVersionsOptions 结构体中 discoveryClient 变量是 CachedDiscoveryInterface 类型,而 CachedDiscoveryClient 结构体实现了该接口,且在 APIVersionsOptions 的 Complete 方法中会将 CachedDiscoveryClient 客户端赋值到 discoveryClient 变量(见代码清单2-30)。
代码清单 2-30
// APIVersionsOptions have the data required for API versions type APIVersionsOptions struct { discoveryClient discovery.CachedDiscoveryInterface genericclioptions.IOStreams }
CachedDiscoveryClient 获取 Group、Version 和 Resource 的流程与 DiscoveryClient 类似,只是在 ServerResourcesForGroupVersion 方法的实现上存在差异。
(1) CachedDiscoveryClient 首先通过 getCachedFile 方法查找本地缓存。
(2)如果信息不存在(未命中)或超时时才会通过 CachedDiscoveryClient 结构体成员 delegate 的 ServerResourcesForGroupVersion 方法访问 Kubernetes APIServer,此时相当于通过 DiscoveryClient 访问(见代码清代 2-31)。
代码清单 2-31
type CachedDiscoveryClient struct { delegate discovery.DiscoveryInterface //... }
(3)最后通过 writeCachedFile 方法将 Kubernetes APIServer 返回的数据存储在本地硬盘。
具体代码分析见代码清单 2-32。
代码清单 2-32
func (d *CachedDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { // 查找本地缓存 filename := filepath.Join(d.cacheDirectory, groupVersion, "serverresources. json") cachedBytes, err := d.getCachedFile(filename) //... // 利用 DiscoveryClient 中的 RESTClient 访问 Kubernetes APIServer liveResources, err := d.delegate.ServerResourcesForGroupVersion(groupVersion) //... // 将 Kubernetes APIServer 响应的数据缓存到本地硬盘 if err := d.writeCachedFile(filename, liveResources); err != nil { //... }
另一种实现方法 memCacheClient 与之类似,只是将数据缓存在 map[string]*cacheEntry 类型中。