了解 k8s 的同窗都知道,kube-apiserver 对外提供 RESTful API 接口提供 查询,监听集群(资源)状态的服务,kube-apiserver 主要就作一件事,就是如何将 RESTful API (CREATE, DELETE, UPDATE, GET .etc)接口调用映射到对后端存储(好比 etcd)的(增删改查)访问,在设计的时候考虑到 k8s 是个快速迭代的开源项目,不少 API 接口(版本)可能在将来版本发生变化,所以如何设计一个扩展性强,耦合度低的架构应该是 Google 那帮货当初主要考虑的问题,因此才致使 kube-apiserver 原本相比 kube-scheduler 和 kube-controller-manager 应该简单的代码设计的巨复杂(我的观点)~node
从 kube-apiserver 收到 RESTful API 请求到从 后端存储中获取(更新 .etc)到数据大概须要通过一下几层(非官方命名),各层之间经过 《接口》 交互(解偶)segmentfault
RESTful API
||
<REST Operation Interface>
||
Storage
||
<Storage Backend Interface>
||
Sotrage Backend(etcd2,etcd3)后端
好比 Storage 和 Storage Backend 之间经过 Storage Backend Interface(参考k8s :kube-apiserver 访问 etcd 后端存储 )交互,Storage 和 RESTful API 之间经过 REST Operation Interface(增删改查 方法的封装)交互api
Storage is a generic interface for RESTful storage services.
Resources which are exported to the RESTful API of apiserver need to implement this interface(原文注释,下同)
It is expected that objects may implement any of the below interfaces
全部想经过 RESTful API 暴露出去的资源都必须实现 Storage 接口,Storage 接口是个最小接口(单一职责),资源类能够根据自身状况实现其它各类接口数据结构
// kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go type Storage interface { New() runtime.Object }
StandardStorage is an interface covering the common verbs. Provided for testing whether a resource satisfies the normal storage methods.
Use Storage when passing opaque storage objects
StandardStorage架构
type StandardStorage interface { Getter Lister GreaterUpdater GracefulDeleter CollectionDeleter Watcher }
StandardStorage 聚合了能够对 Storage 施加的操做(或者叫 Verb,动做),RESTful API根据该(子)接口测试 Storage 是否支持相关操做,而后注册相应的 API 接口,好比若是 Storage 支持 Delete 接口,就注册一个 HTTP method 为 DELETE 的方法到相应的资源路径ide
kubernetes/pkg/registry/core 目录下包含了各类 Storage 实现类,好比你们耳熟能详的 pod, service, endpoint, configmap, node 等等,各个资源的目录结构很类似,以 pod 为例测试
kubernetes/pkg/registry/core/pod rest storage storage.go <- Storage 实现 doc.go strategy.go strategy_test.go
咱们以 pod storage 为例来分析 storage 建立,首先是 pod storage 定义this
type PodStorage struct { Pod *REST Binding *BindingREST Eviction *EvictionREST Status *StatusREST Log *podrest.LogREST Proxy *podrest.ProxyREST Exec *podrest.ExecREST Attach *podrest.AttachREST PortForward *podrest.PortForwardREST }
这里又冒出一些新的类型 REST,BindingREST .etc,这些 XXXREST 才是"真正"的 Storage,对应具体的 RESTful endpoint设计
// REST implements a RESTStorage for pods type REST struct { *genericregistry.Store proxyTransport http.RoundTripper } // BindingREST implements the REST endpoint for binding pods to nodes when etcd is in use type BindingREST struct { store *genericregistry.Store }
XXXREST 类类包含一个 genericregistry.Store 类型的字段,咱们在k8s :kube-apiserver 访问 etcd 后端存储中分析过,它用于访问后端存储
PodStorage 经过 NewStorage 方法建立,各个 XXXREST 共享 Store
func NewStorage(optsGetter generic.RESTOptionsGetter, ...) { 建立 genericregistry.Store store := &genericregistry.Store { ... } ... return PodStorage { Pod: &REST{store, proxyTransport}, Binding: &BindingREST{store: store} ... } }
Storage 是如何"绑定"到 api 接口呢?这中间还涉及到一些数据结构(类),这里先列出绑定相关的代码:
// kubernetes/pkg/registry/core/rest/storage_core.go func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(...) { ... restStorageMap := map[string]rest.Storage { "pods": podStorage.Pod, "pods/attach": podStorage.Attach ... } }
后续再详细分析
本文介绍了 kube-apiserver 中 Storage 相关的一些概念,但愿对你们阅读 k8s 源代码有所帮助