Kubernetes operator(五)api 和 apimachinery 篇【更新中】

news2024/11/13 14:29:41

云原生学习路线导航页(持续更新中)

  • 本文是 Kubernetes operator学习 系列第五篇,主要对 k8s.io/api 和 k8s.io/apimachinery 两个项目 进行学习
  • Kubernetes operator学习系列 快捷链接
    • Kubernetes operator(一)client-go篇
    • Kubernetes operator(二)CRD篇
    • Kubernetes operator(三)code-generator 篇
    • Kubernetes operator(四)controller-tools 篇
    • Kubernetes operator(五)api 和 apimachinery 篇

1.k8s.io/api 项目

1.1.k8s.io/api 项目是什么

  • 一开始,kubernetes的 内建资源 还不太多,内建资源的 结构定义,都是放在项目里维护的。
  • 后来为了方便资源的管理和扩展,将 所有内建资源 的结构定义文件、scheme注册文件、deepcopy等文件,放入了 staging/src 目录下,作为一个单独的项目维护。该项目的名称就是 k8s.io/api
  • 因此,简单来说,k8s.io/api 项目,维护着 Kubernetes 所有内建资源 的 struct定义。

1.2.k8s.io/api 的源码分析

  • 下图中的每一个目录,都代表一个group
    在这里插入图片描述
  • 一个 Group 下,可能会存在多个 Version
    在这里插入图片描述
  • 每个version下,都会包含三个文件:doc.go、register.go、types.go
    • doc.go:声明了按照 package 维度,为所有 structs 提供生成的声明
    • types.go:编写资源的详细结构,一般包括:资源、资源List、资源Spec、资源Status 的详细定义
    • register.go:提供注册到 runtime.Scheme 的函数
      在这里插入图片描述
  • apps/v1/types.go 为例,查看其内容,发现包含 GroupVersion=apps/v1 下的所有Resource结构定义。
    • 下图只截出了一部分,没有截出全部。
      在这里插入图片描述
  • 因此,我们操作内建资源的时候,所有 GVK 内建资源的结构,都是由 k8s.io/api 这个项目提供的。

2.k8s.io/apimachinery 项目

2.1.k8s.io/apimachinery 项目是什么

  • k8s.io/apimachinery 项目是一个关于Kubernetes API资源的工具集,为 k8s.io/api 项目所有的资源,提供下列能力。
    • ObjectMeta与TypeMeta
    • Scheme
    • RESTMapper
    • 编码与解码
    • 版本转换
  • 有了 k8s.io/apimachinery,就可以很方便的操作 kubernetes API。

2.2.k8s.io/apimachinery 提供 TypeMeta 与 ObjectMeta

  • TypeMeta 与 ObjectMeta 是特别常用的两个数据结构。kubernetes 的每一个资源,都会包含一个 TypeMeta、一个ObjectMeta。
    • TypeMeta是内嵌的,转json的时候不会有嵌套结构
    • ObjectMeta,json标签就是 metadata
    type Pod struct {
    	metav1.TypeMeta `json:",inline"`
    	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
    	Spec PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
    	Status PodStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
    }
    
  • TypeMeta:位于 apimachinery/pkg/runtime/types.go
    type TypeMeta struct {
    	// +optional
    	APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty" protobuf:"bytes,1,opt,name=apiVersion"`
    	// +optional
    	Kind string `json:"kind,omitempty" yaml:"kind,omitempty" protobuf:"bytes,2,opt,name=kind"`
    }
    
  • ObjectMeta:位于 apimachinery/pkg/apis/meta/v1/types.go
    type ObjectMeta struct {
    	Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
    	GenerateName string `json:"generateName,omitempty" protobuf:"bytes,2,opt,name=generateName"`
    	Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`
    	SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,4,opt,name=selfLink"`
    	UID types.UID `json:"uid,omitempty" protobuf:"bytes,5,opt,name=uid,casttype=k8s.io/kubernetes/pkg/types.UID"`
    	ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,6,opt,name=resourceVersion"`
    	Generation int64 `json:"generation,omitempty" protobuf:"varint,7,opt,name=generation"`
    	CreationTimestamp Time `json:"creationTimestamp,omitempty" protobuf:"bytes,8,opt,name=creationTimestamp"`
    	DeletionTimestamp *Time `json:"deletionTimestamp,omitempty" protobuf:"bytes,9,opt,name=deletionTimestamp"`
    	DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty" protobuf:"varint,10,opt,name=deletionGracePeriodSeconds"`
    	Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"`
    	Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"`
    	OwnerReferences []OwnerReference `json:"ownerReferences,omitempty" patchStrategy:"merge" patchMergeKey:"uid" protobuf:"bytes,13,rep,name=ownerReferences"`
    	Finalizers []string `json:"finalizers,omitempty" patchStrategy:"merge" protobuf:"bytes,14,rep,name=finalizers"`
    	ZZZ_DeprecatedClusterName string `json:"clusterName,omitempty" protobuf:"bytes,15,opt,name=clusterName"`
    	ManagedFields []ManagedFieldsEntry `json:"managedFields,omitempty" protobuf:"bytes,17,rep,name=managedFields"`
    }
    

2.3.k8s.io/apimachinery 的rumetime/schema包提供 GVRK 各种数据结构

  • 在kubernetes中,为了方便描述资源,或描述REST 的URL,提出了5个概念:
    • GV:GroupVersion
    • GR:GroupResource
    • GVR:GroupVersionResource
    • GK:GroupKind
    • GVK:GroupVersionKind
  • 其中,GR、GVR都是用来描述 RESTFUL API 的,GK、GVK都是用来描述资源类型的
  • 5种数据结构的 struct 定义,都是写在 k8s.io/apimachinery/pkg/runtime/schema/group_version.go 文件中
  • 该文件中还提供了这5种数据结构相互转换的方法
    • 其中,APIVersion Kind,就是我们平时写yaml看到的apiVersion:Group/Version Kind

    • 各结构的转换方法如下:
      在这里插入图片描述

    • 源码如下:在这里插入图片描述
      在这里插入图片描述

2.4.k8s.io/apimachinery 提供 scheme 数据结构

2.4.1.资源的internal版本、external版本

  • kubernetes的资源,并非一下就确定好的,是有一个发展过程的,因此一个资源Kind,可能在多个 GroupVersion 下同时存在。比如 Deployment,在apps/v1下存在,在apps/v1beta1下也存在。
  • 那么,在kubernetes的开发者想要处理Deployment的时候,到底应该按照哪个版本写程序呢?
    • 按理说,每一种GVK都要有相应的处理方法。
    • 但是这样实在是太繁琐了,维护起来不方便,还会有大量重复代码
  • 因此,为每一种GK,维护了一个internal版本,作为中转节点
    • apps/v1/Deploymentapps/v1beta1/Deployment 的相互转换,均是先转成internal的Deployment,再转成 对外的版本
    • kubernetes的作者们,只需要对 internal版本 的资源编写逻辑,就可以处理所有version的资源
  • 这种设计方式,将GVK之间的 拓扑结构,变成了星型结构,非常巧妙。

2.4.2.scheme的作用

  • kubernetes的资源版本太多了,没有谁专门有时间去维护,还是让资源自己来注册比较方便。
  • scheme就是为资源注册信息设计的一个数据结构,每个GVK,将自己的信息封装成一个scheme对象,并将这个scheme对象交给APIServer统一管理,API Server就能够认识这种 GVK 了
  • 在k8s.io/api 项目中,每一个GV下都有一个register.go文件,里面就是将当前GV下的所有Kind,注册到 APIServer 的统一scheme中去。比如 staging/src/k8s.io/api/apps/v1/register.go 文件,
    package v1
    
    import (
    	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    	"k8s.io/apimachinery/pkg/runtime"
    	"k8s.io/apimachinery/pkg/runtime/schema"
    )
    
    // GroupName is the group name use in this package
    const GroupName = "apps"
    
    // SchemeGroupVersion is group version used to register these objects
    var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
    
    // Resource takes an unqualified resource and returns a Group qualified GroupResource
    func Resource(resource string) schema.GroupResource {
    	return SchemeGroupVersion.WithResource(resource).GroupResource()
    }
    
    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
    }
    

2.4.3.k8s.io/apimachinery 提供 scheme 数据结构

  • 根据前面的描述,我们知道scheme是一个数据结构,它的struct其实就是 k8s.io/apimachinery 提供的
  • staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go 文件中,有 Scheme 结构
    type Scheme struct {
        // map,记录 gvk-->type。其中type是通过反射的方式记录的
      	gvkToType map[schema.GroupVersionKind]reflect.Type
      
      	// map,记录 type-->gvk
      	typeToGVK map[reflect.Type][]schema.GroupVersionKind
      
      	// map,记录 type-->gvk。像pod这种,只有一个version的,就记录在这里。
      	unversionedTypes map[reflect.Type]schema.GroupVersionKind
      
      	// map,记录 gvk-->type。像pod这种,只有一个version的,就记录在这里。
      	unversionedKinds map[string]reflect.Type
      
      	// Map from version and resource to the corresponding func to convert
      	// resource field labels in that version to internal version.
      	fieldLabelConversionFuncs map[schema.GroupVersionKind]FieldLabelConversionFunc
      
      	// map,记录默认方法。为某一个具体的type,设置默认值
      	defaulterFuncs map[reflect.Type]func(interface{})
      
      	// 转换器
      	converter *conversion.Converter
      
      	// 记录version的优先级。当没有选择version的时候,优先使用谁
      	versionPriority map[string][]string
      
      	// observedVersions keeps track of the order we've seen versions during type registration
      	observedVersions []schema.GroupVersion
      
      	// schemeName is the name of this scheme.  If you don't specify a name, the stack of the NewScheme caller will be used.
      	// This is useful for error reporting to indicate the origin of the scheme.
      	schemeName string
    }
    
  • Scheme结构中,所有的字段首字母都是小写的,即非导出的,外界无法访问。为此,staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go 文件中还提供了一个方法 NewScheme(),用于初始化一个空的Scheme对象
    func NewScheme() *Scheme {
    	s := &Scheme{
    		gvkToType:                 map[schema.GroupVersionKind]reflect.Type{},
    		typeToGVK:                 map[reflect.Type][]schema.GroupVersionKind{},
    		unversionedTypes:          map[reflect.Type]schema.GroupVersionKind{},
    		unversionedKinds:          map[string]reflect.Type{},
    		fieldLabelConversionFuncs: map[schema.GroupVersionKind]FieldLabelConversionFunc{},
    		defaulterFuncs:            map[reflect.Type]func(interface{}){},
    		versionPriority:           map[string][]string{},
    		schemeName:                naming.GetNameFromCallsite(internalPackages...),
    	}
    	s.converter = conversion.NewConverter(nil)
    
    	// Enable couple default conversions by default.
    	utilruntime.Must(RegisterEmbeddedConversions(s))
    	utilruntime.Must(RegisterStringConversions(s))
    	return s
    }
    
  • 此外,staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go 文件还提供了很多方法,用于将GVK注册到Scheme对象中。用的比较多的是AddKnownTypes()方法
    func (s *Scheme) AddKnownTypes(gv schema.GroupVersion, types ...Object) {
    	s.addObservedVersion(gv)
    	for _, obj := range types {
    		t := reflect.TypeOf(obj)
    		if t.Kind() != reflect.Ptr {
    			panic("All types must be pointers to structs.")
    		}
    		t = t.Elem()
    		s.AddKnownTypeWithName(gv.WithKind(t.Name()), obj)
    	}
    }
    

3.参考博客

  • Kubernetes学习笔记[第5章]API Machinery

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1424301.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyCharm / DataSpell 导入WSL2 解析器,实现GPU加速

PyCharm / DataSpell 导入WSL2 解析器的实现 Windows的解析器不好么?设置WSL2和实现GPU加速为PyCharm / DataSpell 设置WSL解析器设置Interpreter Windows的解析器不好么? Windows上的解析器的确很方便,也省去了我们很多的麻烦。但是WSL2的解…

Ubuntu-22.04上ToDest设置开机不弹出图形界面

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、开始操作1.设置图形端 总结 前言 有时候远程成为开发必不可少的工具,目前国内有很多相关的软件,比较有名的是向日葵、ToDesk、Rust…

Docker基础(持续更新中)

# 第1步,去DockerHub查看nginx镜像仓库及相关信息# 第2步,拉取Nginx镜像 docker pull nginx# 第3步,查看镜像 docker images # 结果如下: REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 60…

黑马程序员前端web入门:新浪新闻

黑马程序员前端web入门:新浪新闻 几点学习到的: 设置li无圆点: list-style: none;设置a无下划线:text-decoration: none;a属于行内元素,高度hegiht不起作用,可以设置 display: block; 把它变成块元素。此时&#xff0c…

20240131在WIN10下配置whisper

20240131在WIN10下配置whisper 2024/1/31 18:25 首先你要有一张NVIDIA的显卡,比如我用的PDD拼多多的二手GTX1080显卡。【并且极其可能是矿卡!】800¥ 2、请正确安装好NVIDIA最新的545版本的驱动程序和CUDA。 2、安装Torch 3、配置whisper http…

【简便方法和积累】pytest 单元测试框架中便捷安装插件和执行问题

又来进步一点点~~~ 背景:之前写了两篇关于pytest单元测试框架的文章,本篇内容对之前的做一个补充 一、pytest插件: pytest 有非常多的插件,很方便,以下为插件举例: pytest,pytest-html&#x…

leetcode刷题(剑指offer) 19.删除链表的倒数第N个节点

19.删除链表的倒数第N个节点 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,3,4,5], n 2 输出:[1,2,3,5]示例 2: 输入:head [1], n 1 输出&am…

双异步系列完结撒花,如何解決异步事务问题?

目录 一、前情提要原始需求:读取一个10万行的Excel优化1:[**使用双异步后,从 191s 优化到 2s**](https://blog.csdn.net/guorui_java/article/details/135143234)优化2:[**使用双异步后,如何保证数据一致性&#xff1f…

ClickHouse为什么这么快(二)SSE指令优化

上一篇 ClickHouse为什么这么快(一)减少数据扫描范围 我们说到了ClickHouse中使用列存储,每个列都单独存储为一个文件,每个文件都是由一个或多个数据块组成,也就是说:每个文件由一个或多个数组组成&#xf…

Python限定符

在正则表达式中,限定符用于指定模式的匹配次数或匹配范围。在Python中,正则表达式模块re提供了多种不同的限定符,以实现更灵活和精确的匹配操作。熟悉并理解Python中的限定符对于处理文本和字符串数据非常重要。本文将详细介绍Python中常见的…

DNS配置文件讲解

1. 概述 BIND:Berkeley Internet Name Domain ,伯克利因特网域名解析服务是一种全球使用最广泛的、 最高效的、最安全的域名解析服务程序 2. 安装软件 [rootserver ~]# yum install bind -y 3. bind服务中三个关键文件 /etc/named.conf : 主配置文件…

Histone H3K27ac Antibody, SNAP-ChIP® Certified

EpiCypher是一家为表观遗传学和染色质生物学研究提供高质量试剂和工具的专业制造商。EpiCypher(国内代理商欣博盛生物)推出的ChIP级别的Histone H3K27ac Antibody符合EpiCypher的“SNAP-ChIP Certified”标准,用于ChIP实验中的特异性和有效靶…

Orion-14B-Chat-RAG本地部署的解决方案

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

刷存在感,Excel转Protobuf/Json通用配置文件

使用场景 最近工作流中有将Excel转Protobuf作为配置文件的技术方案。具体实现是先定一个proto文件,再在一个对应excel表中定义对应字段,由策划在excel进行更改。proto文件可以生成对应语言的脚本,然后将excel转成对应protobuf的binary。 我…

【Tomcat与网络9】提高Tomcat启动速度的八大措施

本文我们来看一下如何对Tomcat进行调优,我们对于Tomcat的调优主要集中在三个方面:提高启动速度、提高系统稳定性和提高并发能力,后两者很多时候是相辅相成的,我们放在一起看。 Tomcat现在一般都嵌入在SpringBoot里,因…

又涨又跌 近期现货黄金价格波动怎么看?

踏入2024年一月的下旬,现货黄金价格可以说没了之前火热的状态,盘面上是又涨又跌。面对这样的行情,很多投资者不知道如何看了。下面我们就来讨论一下怎么把握近期的行情。 先区分走势类型。在现货黄金市场中有两种主要的走势类型,一…

千兆电口模块和万兆电口模块:网络速度的演变

随着信息技术的迅猛发展,网络通信技术也在不断进步。在过去的几十年中,以太网的速度发生了巨大的变化,从最初的百兆以太网,到如今的千兆以太网和万兆以太网甚至40G、100G以太网满足了大数据、云计算、人工智能等新兴应用的需求。在…

Golang语言异常机制解析:错误策略与优雅处理

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie。 前言 作为开发者来说,我们没办法保证程序在运行过程中永远不会出现异常,对于异常…

前端JavaScript篇之实现一个将多维数组展示的方法有哪些,分别是?

目录 实现一个将多维数组展示的方法有哪些,分别是?方法一:递归展开成一维数组方法二:嵌套展示结构方法三:ES6新增的数组扩展方法 flat()方法四:apply() 结合 concat() 使用以展开成一维数组方法五&#xff…

2024 年 Sketch 替代品的最佳选择:Windows、Web 和 Mac 用户的详细比较

什么是Sketch Sketch是一个著名的、越来越受欢迎的矢量图形设计软件,它通过各种有用的UI设计和原型设计工具使这一过程更易于管理。 Sketch于2010年9月首次发布,后来在2012年获得苹果设计奖。对于Sketch来说,这正好停止了Adobe使用当时领先…