Kubernetes 的 Schema

1、schema的定义

而 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,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 之间的映射

2、通过示例了解 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.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
}

那么扩展一个资源的整个流为:

  • 资源类型在:k8s.io/api/{Group}/types.go
  • 资料类型的实现接口 k8s.io/apimachinery/pkg/runtime/interfaces.go.Object
  • 其中是基于 Deployment 的类型,metav1.TypeMeta 和 metav1.ObjectMeta
  • metav1.TypeMeta 实现了 GetObjectKind() ;metav1.ObjectMeta 实现了 DeepCopyinfo=()DeepCopy() ,还需要实现 DeepCopyObject()
  • 最后注册资源到 schema 中 k8s.io/api/apps/v1/register.go

3、schema的使用案例

1、创建deployment使用

deploymentRes := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}
	//定义结构化数据结构
	deployment := &unstructured.Unstructured{
		Object: map[string]interface{}{
			"apiVersion": "apps/v1",
			"kind":       "Deployment",
			"metadata": map[string]interface{}{
				"name": deployname,
			},
			"spec": map[string]interface{}{
				"replicas": replicas,
				"selector": map[string]interface{}{
					"matchLabels": map[string]interface{}{
						"app": "demo",
					},
				},
				"template": map[string]interface{}{
					"metadata": map[string]interface{}{
						"labels": map[string]interface{}{
							"app": "demo",
						},
					},

					"spec": map[string]interface{}{
						"containers": []map[string]interface{}{
							{
								"name":  "web",
								"image": image,
								"ports": []map[string]interface{}{
									{
										"name":          "http",
										"protocol":      "TCP",
										"containerPort": 80,
									},
								},
							},
						},
					},
				},
			},
		},
	}

	// 创建 Deployment
fmt.Println("创建 deployment...")
result, err := client.Resource(deploymentRes).Namespace(namespace).Create(context.TODO(), deployment, metav1.CreateOptions{})
if err != nil {
	panic(err)
}

2、使用内置方法转成数据结构

// ParseGroupVersion方法将字符串转成数据结构
gv, err := schema.ParseGroupVersion(groupVerionStr)

  

posted @ 2022-05-31 21:31  南昌拌粉的成长  阅读(208)  评论(0编辑  收藏  举报