理解 Kubernetes 的 API 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,它描述了應用於存儲數據的所有邏輯約束,包括完整性、表和視圖。常見包括

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

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

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

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

而對應的的即爲 TypeMeta 、ObjectMeta 和 DeploymentSpecTypeMeta 爲 kind 與 apiserverObjectMeta 爲 Name 、Namespace 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,`

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

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

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,`

如上述代碼所示,Deployment 中的 metav1.TypeMeta 和 metav1.ObjectMeta

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

所以在實現方法時,需要實現 DeepCopyinfo , DeepCopy 和繼承接口 Object 的 DeepCopyObject 方法

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

那麼擴展一個資源的整個流爲:

原文:https://www.cnblogs.com/Cylon/p/16282407.html

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/_pXsz4HUwtC5OjvS5h5a0Q