The word schema originates from the Greek word form or figure, but exactly how schema should be defined depends on the context of the application environment. There are different types of schema and their meanings are closely related to the fields of data science, education, marketing and SEO, and psychology.

But schema in computing is actually very close to this interpretation, and the term schema can be found in many places, such as database, openldap, programming language, etc. Here we can simply interpret _schema_ as a metadata component, which mainly contains declarations of elements and attributes, and other data structures.

Schema in a database

In a database, schema is like a skeleton structure that represents a logical view of the entire database. It designs all the constraints that are applied to the data in a particular database. A schema is created when data is modeled. schema is often used when talking about relational databases] and object-oriented databases. sometimes it also refers to a description of the structure or text.

A schema in a database describes the shape of the data and its relationship to other models, tables, and libraries. In this case, the database entry is an instance of the schema and contains all the attributes described in the schema.

Database schema is usually divided into two categories: physical database schema which defines how data files are actually stored, and logical database schema which describes all the logical constraints applied to stored data, including integrity, tables and views. Common ones include

  • star schema
  • snowflake schema
  • fact constellation schema (fact constellation schema or galaxy schema)

The star schema is similar to a simple data warehouse diagram that includes a one-to-many fact table and dimension table. It uses non-normalized data.

star schema

Snowflake schema is a more complex and popular database schema in which dimension tables are normalized to save storage space and minimize data redundancy.

The fact constellation schema is far more complex than the star and snowflake schemas. It has multiple fact tables that share multiple dimension tables.

snowflake schema

Schema in Kubernetes

The above explanation gives you an idea of what schema is. In Kubernetes, there is also the concept of schema, which is the metadata of k8s resource objects by defining the specification of resources (GVK) in kubernetes and mapping the relationships between them.

The resource objects in kubernetes are Group Version Kind, which are defined in staging/src/k8s.io/api/type.go. This is the yaml file that we normally work with.

For example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment  
metadata:
  name:  ngx
  namespace: default
spec:
  selector:  
    matchLabels:
      app: ngx
  template:  
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: ngx-schema
        image: nginx
        ports:
        - containerPort: 80

k8s

The corresponding ones are TypeMeta, ObjectMeta and DeploymentSpec, TypeMeta for kind and apiserver, ObjectMeta for Name, Namespace, CreationTimestamp and so on. .

The DeploymentSpec corresponds to the spec in yaml.

The whole yaml is a k8s resource object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
type Deployment struct {
    metav1.TypeMeta `json:",inline"`
    // Standard object metadata.
    // +optional
    metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`

    // Specification of the desired behavior of the Deployment.
    // +optional
    Spec DeploymentSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`

    // Most recently observed status of the Deployment.
    // +optional
    Status DeploymentStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}

register.go is the class that registers the corresponding resource type into the schema.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var (
    // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
    // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
    SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes)
    localSchemeBuilder = &SchemeBuilder
    AddToScheme        = localSchemeBuilder.AddToScheme
)

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
    scheme.AddKnownTypes(SchemeGroupVersion,
        &Deployment{},
        &DeploymentList{},
        &StatefulSet{},
        &StatefulSetList{},
        &DaemonSet{},
        &DaemonSetList{},
        &ReplicaSet{},
        &ReplicaSetList{},
        &ControllerRevision{},
        &ControllerRevisionList{},
    )
    metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
    return nil
}

The apimachinery package is an implementation of schema, and by looking at its contents you can see that schema in kubernetes is a mapping between GVK attribute constraints and GVR.

Understanding schema through examples

For example, in the apps/v1/deployment resource, which is represented in the code as k8s.io/api/apps/v1/types.go, what do you need to do if you need to extend the resource? For example, create a StateDeplyment resource.

1
2
3
4
5
6
type Deployment struct {
    metav1.TypeMeta `json:",inline"`
    // Standard object metadata.
    // +optional
    metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
}

As shown in the above code, metav1.TypeMeta and metav1.ObjectMeta in Deployment.

Deployment

Then we copy a Deployment as StateDeployment, note that since the two properties of Deployment, metav1.TypeMeta and metav1.ObjectMeta implement different methods respectively, as shown in the figure.

copy a Deployment as StateDeployment

So when implementing the methods, you need to implement DeepCopyinfo, DeepCopy and the DeepCopyObject method of the inherited interface Object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StateDeployment) DeepCopyInto(out *StateDeployment) {
    *out = *in
    out.TypeMeta = in.TypeMeta
    in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
    in.Spec.DeepCopyInto(&out.Spec)
    in.Status.DeepCopyInto(&out.Status)
    return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StateDeployment.
func (in *StateDeployment) DeepCopy() *StateDeployment {
    if in == nil {
        return nil
    }
    out := new(StateDeployment)
    in.DeepCopyInto(out)
    return out
}

// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *StateDeployment) DeepCopyObject() runtime.Object {
    if c := in.DeepCopy(); c != nil {
        return c
    }
    return nil
}

Then the entire stream for extending a resource is.

  • Resource type in: k8s.io/api/{Group}/types.go
  • The implementation interface for the resource type k8s.io/apimachinery/pkg/runtime/interfaces.go.Object
  • which is based on the Deployment types, metav1.TypeMeta and metav1.ObjectMeta
  • metav1.TypeMeta implements GetObjectKind(); metav1.ObjectMeta implements DeepCopyinfo=(), DeepCopy() and also needs to implement DeepCopyObject()
  • Finally register the resource in schema k8s.io/api/apps/v1/register.go