K8S中为什么需要Unstructured对象

2024-08-23 20:58

本文主要是介绍K8S中为什么需要Unstructured对象,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

熟悉client-go的同学都知道,不止有DeploymentPod这些结构化对象,也提供了unstructured.Unstructured对象,那么为什么需要非结构对象?

Structured vs Unstructured

结构化对象是指可以用Go Struct表示的对象,比如Deployment在k8s.io/api/apps/v1定义

type Deployment struct {metav1.TypeMeta `json:",inline"`// Standard object's metadata.// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata// +optionalmetav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`...
}

我们可以直接通过appsv1.Deployment来安全地定义Deployment的各个字段,通常创建过程如下:

clientset, err := kubernetes.NewForConfig(config)deployment := &appsv1.Deployment{}
deployment.Name = "example"
deployment.Spec = appsv1.DeploymentSpec{...
}clientset.AppsV1().Deployments(apiv1.NamespaceDefault).Create(deployment)

而对于Unstructured定义在k8s.io/apimachinery/pkg/apis/meta/v1/unstructured

type Unstructured struct {// Object is a JSON compatible map with string, float, int, bool, []interface{}, or// map[string]interface{}// children.Object map[string]interface{}
}

通过定义map[string]interface{}可以来表示任意的JSON/YAML对象,而不需要引用Go Struct。可以通过Dynamic client来创建非结构化对象,以下是使用Unstructured创建Deployment的样例。

client, _ := dynamic.NewForConfig(config)
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": "demo-deployment",},"spec": map[string]interface{}{"replicas": 2,...}}
}client.Resource(deploymentRes).Namespace(namespace).Create(context.TODO(), deployment, metav1.CreateOptions{})

Why

那么什么情况下需要使用到Unstructured对象呢,结构化对象有着安全地类型校验,通过clientset可以方便地增删改查。而非结构化对象只能手动设置GVR、通过map[string]interface{}设置各个字段。

假想你作为一个Paas平台的开发者,需要为每个用户传入的YAML/JSON资源添加label,比如添加user信息creator=xxx。如果用户只能创建Deployment,那么我们可以将资源解析成appsv1.Deployment{}对象,再添加label。但是通常会传入多种资源,不仅有内置的DeploymentService等,也可能会包含自定义资源。由于不确定资源类型,我们只能通过Unstructured对象来解析。

const manifest = `
apiVersion: apps/v1
kind: Deployment
metadata:name: example
spec:...
`
// convert yaml to unstructured
obj := &unstructured.Unstructured{}
dec := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
dec.Decode([]byte(manifest), nil, obj)// add label
labels := obj.GetLabels()
labels["creator"]="userxxx"// set label
obj.SetLabels(labels)dynamicClient.Resource().Namespace(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})

当实现对多种资源的通用处理(上面的示例),或者运行时才能确定的对象(例如根据配置监听不同对象),又或者不愿引入额外的依赖(处理大量的CRD),可以使用Unstructured对象来处理以上情况。

How

不管是结构化对象还是非结构化,最终会调用k8s的Rest API,例如Create Deployment

POST /apis/apps/v1/namespaces/{namespace}/deployments/{name}

K8s中GVR(GroupVersionResource)可以唯一表征资源对象,用来组成Rest API, 如上Group为apps、Version为v1、Resource是deploymentsGVK(GroupVersionKind)可以来标识类型(如Deployment)。Resource与Kind的对应关系可以通过kubectl api-resources查看。

~ kubectl api-resources --api-group apps
NAME                  SHORTNAMES   APIVERSION   NAMESPACED   KIND
controllerrevisions                apps/v1      true         ControllerRevision
daemonsets            ds           apps/v1      true         DaemonSet
deployments           deploy       apps/v1      true         Deployment
replicasets           rs           apps/v1      true         ReplicaSet
statefulsets          sts          apps/v1      true         StatefulSet

对于结构化对象,使用clientset可以获取到GVR,最后调用restClient组成到Rest API

clientset.AppsV1().Deployments(namespace).Create(deployment)// Create takes the representation of a deployment and creates it.  Returns the server's representation of the deployment, and an error, if there is any.
func (c *deployments) Create(ctx context.Context, deployment *v1.Deployment, opts metav1.CreateOptions) (result *v1.Deployment, err error) {result = &v1.Deployment{}err = c.client.Post().Namespace(c.ns).Resource("deployments"). // Resource设置VersionedParams(&opts, scheme.ParameterCodec).Body(deployment).Do(ctx).Into(result)return
}

对于非结构化对象,需要用户手动填充GVR,如果只知道GVK可以通过restMapping获取

deploymentRes := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}dynamicClient.Resource().Namespace(namespace).Create()// Create具体实现
func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)name := ""if len(subresources) > 0 {accessor, err := meta.Accessor(obj)name = accessor.GetName()}// 调用restClientresult := c.client.client.Post().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(outBytes).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do(ctx)// ...
}

总结

本文描述Unstructured对象在K8s中的使用场景、使用方式,与Structured对象的对比,以及相关代码解析。

引用

  • https://kubernetes.io/zh/docs/reference/using-api/api-concepts/

这篇关于K8S中为什么需要Unstructured对象的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1100476

相关文章

sqlserver、mysql、oracle、pgsql、sqlite五大关系数据库的对象名称和转义字符

《sqlserver、mysql、oracle、pgsql、sqlite五大关系数据库的对象名称和转义字符》:本文主要介绍sqlserver、mysql、oracle、pgsql、sqlite五大... 目录一、转义符1.1 oracle1.2 sqlserver1.3 PostgreSQL1.4 SQLi

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

JavaScript对象转数组的三种方法实现

《JavaScript对象转数组的三种方法实现》本文介绍了在JavaScript中将对象转换为数组的三种实用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录方法1:使用Object.keys()和Array.map()方法2:使用Object.entr

k8s中实现mysql主备过程详解

《k8s中实现mysql主备过程详解》文章讲解了在K8s中使用StatefulSet部署MySQL主备架构,包含NFS安装、storageClass配置、MySQL部署及同步检查步骤,确保主备数据一致... 目录一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.

k8s admin用户生成token方式

《k8sadmin用户生成token方式》用户使用Kubernetes1.28创建admin命名空间并部署,通过ClusterRoleBinding为jenkins用户授权集群级权限,生成并获取其t... 目录k8s admin用户生成token创建一个admin的命名空间查看k8s namespace 的

使用MapStruct实现Java对象映射的示例代码

《使用MapStruct实现Java对象映射的示例代码》本文主要介绍了使用MapStruct实现Java对象映射的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、什么是 MapStruct?二、实战演练:三步集成 MapStruct第一步:添加 Mave

k8s搭建nfs共享存储实践

《k8s搭建nfs共享存储实践》本文介绍NFS服务端搭建与客户端配置,涵盖安装工具、目录设置及服务启动,随后讲解K8S中NFS动态存储部署,包括创建命名空间、ServiceAccount、RBAC权限... 目录1. NFS搭建1.1 部署NFS服务端1.1.1 下载nfs-utils和rpcbind1.1

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

k8s容器放开锁内存限制问题

《k8s容器放开锁内存限制问题》nccl-test容器运行mpirun时因NCCL_BUFFSIZE过大导致OOM,需通过修改docker服务配置文件,将LimitMEMLOCK设为infinity并... 目录问题问题确认放开容器max locked memory限制总结参考:https://Access

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定