API Schema in kubernetes

Cylon發表於2022-05-17

什麼是schema

schema一詞起源於希臘語中的formfigure,但具體應該如何定義schema取決於應用環境的上下文。schema有不同的型別,其含義與資料科學、教育、營銷和SEO以及心理學等領域密切相關。

在維基百科中將schema解釋為,圖式,在心裡學中主要描述一種思維或行為型別,用來組織資訊的類別,以及資訊之間的關係。它也可以被描述為先入為主思想的心理結構,表示世界某些觀點的框架,或是用於組織和感知新資訊的系統。

但在計算機中的schema其實與這個解釋很接近了,從很多地方都可以看到 schema 這個名詞,例如 database,openldap,programing language等的。這裡可以簡單的吧schema 理解為 後設資料集合 (metadata component),主要包含元素及屬性的宣告,與其他資料結構組成。

資料庫中的schema

在資料庫中,schema 就像一個骨架結構,代表整個資料庫的邏輯檢視。它設計了應用於特定資料庫中資料的所有約束。當在資料建模時,就會產生一個schema。在談到關聯式資料庫]和麵向物件資料庫時經常使用schema。有時也指將結構或文字的描述。

資料庫中schema描述資料的形狀以及它與其他模型、表和庫之間的關係。在這種情況下,資料庫條目是schema的一個例項,包含schema中描述的所有屬性。

資料庫schema通常分為兩類:定義資料檔案實際儲存方式的**物理資料庫schema ;和邏輯資料庫schema **,它描述了應用於儲存資料的所有邏輯約束,包括完整性、表和檢視。常見包括

  • 星型模式(star schema)
  • 雪花模式(snowflake schema)
  • 事實星座模型(fact constellation schema 或 galaxy schema)

星型模式是類似於一個簡單的資料倉儲圖,包括一對多的事實表和維度表。它使用非規範化資料。

雪花模式是更為複雜的一種流行的資料庫模式,在該模式下,維度表是規範化的,可以節省儲存空間並最大限度地減少資料冗餘。

事實星座模式遠比星型模式和雪花模式複雜得多。它擁有多個共享多個維度表的事實表。

Kubernetes中的schema

通過上面的闡述,大概上可以明白 schema究竟是什麼東西了,在Kubernetes中也有schema的概念,通過對kubernetes中資源(GVK)的規範定義、相互關係間的對映等,schema即k8s資源物件後設資料。

而kubernetes中資源物件即 Group Version Kind 這些被定義在 staging/src/k8s.io/api/type.go中,即平時所操作的yaml檔案,例如

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

而對應的的即為TypeMetaObjectMetaDeploymentSpec,

TypeMetakindapiserver

ObjectMetaNameNamespace CreationTimestamp等段。

DeploymentSpec 則對應了 yaml 中的 spec。

而整個yaml組成了 一個 k8s的資源物件。

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 則是將對應的資源型別註冊到schema中的類

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
}

apimachinery 包則是 schema的實現,通過看其內容可以發下,kubernetes中 schema就是 GVK 的屬性約束 與 GVR 之間的對映。

通過示例瞭解schema

例如在 apps/v1/deployment 這個資源,在程式碼中表示 k8s.io/api/apps/v1/types.go ,如果需要對其資源進行擴充套件那麼需要怎麼做?如,建立一個 StateDeplyment 資源

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

如上述程式碼所示,Deployment 中的 metav1.TypeMetametav1.ObjectMeta

那麼我們複製一個 Deployment 為 StateDeployment,注意,因為 Deployment的兩個屬性, metav1.TypeMetametav1.ObjectMeta 分別實現了不同的方法,如圖所示

所以在實現方法時,需要實現 DeepCopyinfoDeepCopy 和繼承介面 ObjectDeepCopyObject 方法

// 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
}

那麼擴充套件一個資源的整個流為:

  • 資源型別在:k8s.io/api/{Group}/types.go
  • 資料型別的實現介面 k8s.io/apimachinery/pkg/runtime/interfaces.go.Object
  • 其中是基於 Deployment 的型別,metav1.TypeMetametav1.ObjectMeta
  • metav1.TypeMeta 實現了 GetObjectKind()metav1.ObjectMeta 實現了DeepCopyinfo=()DeepCopy() ,還需要實現 DeepCopyObject()
  • 最後註冊資源到schema中 k8s.io/api/apps/v1/register.go

相關文章