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

相关文章

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

MySQL JSON 查询中的对象与数组技巧及查询示例

《MySQLJSON查询中的对象与数组技巧及查询示例》MySQL中JSON对象和JSON数组查询的详细介绍及带有WHERE条件的查询示例,本文给大家介绍的非常详细,mysqljson查询示例相关知... 目录jsON 对象查询1. JSON_CONTAINS2. JSON_EXTRACT3. JSON_TA

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

Spring中管理bean对象的方式(专业级说明)

《Spring中管理bean对象的方式(专业级说明)》在Spring框架中,Bean的管理是核心功能,主要通过IoC(控制反转)容器实现,下面给大家介绍Spring中管理bean对象的方式,感兴趣的朋... 目录1.Bean的声明与注册1.1 基于XML配置1.2 基于注解(主流方式)1.3 基于Java

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一

golang 对象池sync.Pool的实现

《golang对象池sync.Pool的实现》:本文主要介绍golang对象池sync.Pool的实现,用于缓存和复用临时对象,以减少内存分配和垃圾回收的压力,下面就来介绍一下,感兴趣的可以了解... 目录sync.Pool的用法原理sync.Pool 的使用示例sync.Pool 的使用场景注意sync.