Last In this article, we mainly introduce how different versions of resources in kubernetes are registered into schema objects, including internal version resources and all external version resources. As well as the registration of the model type of the resource, the registration of the initialization function (i.e. the default value function) of the resource, the registration of the label conversion function of the resource, and the registration of the conversion function between internal and external versions. In this article, we mainly introduce the data access layer of resources.
As we all know, all kubernetes resources are stored in etcd clsuter. It is a typical distributed kv database, which provides operations such as storage, query, update, watch to monitor object changes and so on. In the design of data access layer, it also adheres to the principle of interface and implementation, defines the interface function, and realizes the function by the relevant specific implementation class (etcd3 Implementation). The relevant diagrams and source codes are as follows:

// k8s.io/apiserver/pkg/storage/interfaces.go type Interface interface { Versioner() Versioner Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64) error Delete(ctx context.Context, key string, out runtime.Object, preconditions *Preconditions,validateDeletion ValidateObjectFunc, cachedExistingObject runtime.Object) error Watch(ctx context.Context, key string, opts ListOptions) (watch.Interface, error) WatchList(ctx context.Context, key string, opts ListOptions) (watch.Interface, error) Get(ctx context.Context, key string, opts GetOptions, objPtr runtime.Object) error GetToList(ctx context.Context, key string, opts ListOptions, listObj runtime.Object) error List(ctx context.Context, key string, opts ListOptions, listObj runtime.Object) error GuaranteedUpdate(ctx context.Context, key string, ptrToType runtime.Object, ignoreNotFound bool, precondtions *Preconditions, tryUpdate UpdateFunc, cachedExistingObject runtime.Object) error Count(key string) (int64, error) } // k8s.io/apiserver/pkg/storage/etcd3/store.go type store struct { client *clientv3.Client codec runtime.Codec versioner storage.Versioner transformer value.Transformer pathPrefix string watcher *watcher pagingEnabled bool leaseManager *leaseManager } func (s *store) Versioner() Versioner{...} func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64) error{...} func (s *store) Delete(ctx context.Context, key string, out runtime.Object, preconditions *Preconditions,validateDeletion ValidateObjectFunc, cachedExistingObject runtime.Object) error{...} func (s *store) Watch(ctx context.Context, key string, opts ListOptions) (watch.Interface, error){...} func (s *store) WatchList(ctx context.Context, key string, opts ListOptions) (watch.Interface, error){...} func (s *store) Get(ctx context.Context, key string, opts GetOptions, objPtr runtime.Object) error{...} func (s *store) GetToList(ctx context.Context, key string, opts ListOptions, listObj runtime.Object) error{...} func (s *store) List(ctx context.Context, key string, opts ListOptions, listObj runtime.Object) error{...} func (s *store) GuaranteedUpdate(ctx context.Context, key string, ptrToType runtime.Object, ignoreNotFound bool, precondtions *Preconditions, tryUpdate UpdateFunc, cachedExistingObject runtime.Object) error{...} func (s *store) Count(key string) (int64, error){...}
- k8s.io/apiserver/pkg/storage/interfaces.go defines the interface of resource data access layer, including adding, deleting, modifying and querying resources and watch ing.
- The etcd3.store structure implements the interface functions defined above. The implementation in this structure encapsulates the object clientv3.Client, which is used to access and operate the etcd3 cluster.
In addition, kubernetes also supports dry run operation, that is, running commands or executing API s, but does not affect resource storage. Therefore, based on the above interface functions, DryRunnableStorage structure is defined to realize this function. The relevant diagrams and source codes are as follows:

// k8s.io/apiserver/pkg/registry/generic/registry/dryrun.go type DryRunnableStorage struct { Storage storage.Interface Codec runtime.Codec } func (s *DryRunnableStorage) Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64, dryRun bool) error { if dryRun { if err := s.Storage.Get(ctx, key, storage.GetOptions{}, out); err == nil { return storage.NewKeyExistsError(key, 0) } return s.copyInto(obj, out) } return s.Storage.Create(ctx, key, obj, out, ttl) } func (s *DryRunnableStorage) copyInto(in, out runtime.Object) error { var data []byte data, err := runtime.Encode(s.Codec, in) if err != nil { return err } _, _, err = s.Codec.Decode(data, nil, out) if err != nil { return err } return nil } // ... other functions
- This structure contains the attributes of the data provider type described above to complete the basic data access operation.
- This structure contains the runtime.Codec attribute to complete the necessary serialization and deserialization operations.
- Take the dry run of the create operation as an example. The operation judges whether the resource exists, and then the internal copy object returns without the actual create operation.
The diagram and source code of the creation process of data access objects or DAO objects are as follows:

// k8s.io/apiserver/pkg/storage/storagebackend/factory/factory.go func Create(c storagebackend.Config, newFunc func() runtime.Object) (storage.Interface, DestroyFunc, error) { switch c.Type { case "etcd2": return nil, nil, fmt.Errorf("%v is no longer a supported storage backend", c.Type) case storagebackend.StorageTypeUnset, storagebackend.StorageTypeETCD3: return newETCD3Storage(c, newFunc) default: return nil, nil, fmt.Errorf("unknown storage type: %s", c.Type) } }
- The creation of data access objects is based on configuration and is determined by storagebackend.Config.
- For the current kubernetes version, only the data access layer of etcd3 is supported.
- The data access layer is not supported for etcd2 or other types of storage.
Now let's write here. In the next article, we will continue to introduce the data service layer of resources.