Kubernetes对象深入学习之五:TypeMeta无效之谜

news2024/11/15 4:23:21

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本文是《Kubernetes对象深入学习之五》系列的第五篇,从前文的分析也能看出,代表对象类型的schema.ObjectKind,于对象而言是至关重要的,那是它的类型和身份,既然如此,与之有关的问题也不能放过,因此本篇就来看一个对象类型相关的问题,本文由以下内容组成:
  1. 复现问题:我的代码中获取的对象类型为空
  2. 问题原因
  3. 为什么会有这个问题?
  4. 这个问题有解吗?

复现问题

  • 问题很容易复现,回顾《Kubernetes对象深入学习之四:对象属性编码实战》的代码,controller.go有下面这么一段代码,作用是在controller监听到对象变化时,将对象的ObjectMeta内容在控制台打印出来,现在咱们在黄色箭头前面添加两端代码
    在这里插入图片描述
  • 新增的代码是下面这些,先用现成的方法做一次提取,得到Kind和APIVersion,再尝试直接转换成objectruntime.Object类型获取GVK
// 第一次尝试:通过公共方法转为Type接口
objType, err := meta.TypeAccessor(obj)
if err != nil {
	klog.Errorf("TypeAccessor [%s], failed with %v", key, err)
	return err
}

fmt.Printf("** 通过公共方法获取Kind, kind [%s], version [%s]\n", objType.GetKind(), objType.GetAPIVersion())

// 第二次尝试:亲自尝试强转
runtimeObj, _ := obj.(objectruntime.Object)
fmt.Printf("** 强转获取Kind: %v\n", runtimeObj.GetObjectKind().GroupVersionKind())
  • 修改后整体效果如下,黄框中是本次新增内容
    在这里插入图片描述
  • 程序启动后,打印日志如下,可见不论是哪种方式,kind和version的值都是空
I0827 01:15:58.890491 2945049 controller.go:144] Starting Pod controller
** 通过公共方法获取Kind, kind [], version []
** 强转获取Kind: /, Kind=
** 通过公共方法获取Kind, kind [], version []
** 强转获取Kind: /, Kind=
** 通过公共方法获取Kind, kind [], version []
** 强转获取Kind: /, Kind=
  • 好了,现在问题已复现:TypeMeta内容为空,接下来去寻找问题原因

问题原因

  • 咱们按照顺序捋一下代码,在main.go中调用了CreateAndStartController来创建controller,此时指定了类型是&v1.Pod{}
    在这里插入图片描述

  • 在CreateAndStartController方法内会调用NewListWatchFromClient来创建ListWatcher,指定了resource就是刚才传入的pods
    在这里插入图片描述

  • 继续展开,就看到了关键代码NewFilteredListWatchFromClient方法,这里指出了list操作的具体实现,该方法其余代码略去不看了:

func NewFilteredListWatchFromClient(c Getter, resource string, namespace string, optionsModifier func(options *metav1.ListOptions)) *ListWatch {
	listFunc := func(options metav1.ListOptions) (runtime.Object, error) {
		optionsModifier(&options)
		return c.Get().
			Namespace(namespace).
			Resource(resource).
			VersionedParams(&options, metav1.ParameterCodec).
			Do(context.TODO()).
			Get()
	}
	
	// 剩余的代码省略不看
	...
}
  • 注意,重点来了,先展开上面的Do方法,这里面发起了远程请求,获取资源列表,并且指定transformResponse方法用来处理收到的响应
func (r *Request) Do(ctx context.Context) Result {
	var result Result
	err := r.request(ctx, func(req *http.Request, resp *http.Response) {
		result = r.transformResponse(resp, req)
	})
	if err != nil {
		return Result{err: err}
	}
	return result
}
  • 这个transformResponse方法的代码太多,我们只关注重点,就是这个decoder对象,记住这个decoder
    在这里插入图片描述
  • 看完了Do方法,再来看Get方法,关键代码是黄色箭头指出的部分:使用decoder对响应的body进行处理
    在这里插入图片描述
  • 再来看这个Decode方法的内容(apimachinery@v0.22.8/pkg/runtime/helper.go),很明显,这里故意调用了SetGroupVersionKind方法,入参是个新的GroupVersionKind对象,如此一来,所有类型有关的信息就被清除了
// Decode does not do conversion. It removes the gvk during deserialization.
func (d WithoutVersionDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
	obj, gvk, err := d.Decoder.Decode(data, defaults, into)
	if obj != nil {
		kind := obj.GetObjectKind()
		// clearing the gvk is just a convention of a codec
		kind.SetGroupVersionKind(schema.GroupVersionKind{})
	}
	return obj, gvk, err
}
  • 至此,真相大白,kubernetes官方在处理api-server的响应内容时,刻意将TypeMeta清理掉了

为什么会有这个问题?

  • 对于这么做的原因,首先是个人猜测,回到main.go,如下图,作为使用方,既然已经明确了要监听的资源是pod,那么得到的结果自然就只能是v1.Pod了,所以无需再从结果中获取类型,
    在这里插入图片描述
  • 至于根本原因,由于欣宸英语水平太差,未能从一群老外的讨论中得到明确答案,下面是和这个问题相关的pr和issue,可见抱有相同疑惑的人着实不少,并且这个问题已经持续多年,并且一直没有解决
  • https://github.com/kubernetes/kubernetes/pull/59264#issuecomment-362579495
  • https://github.com/kubernetes/client-go/issues/541
  • https://github.com/kubernetes/client-go/issues/861
  • https://github.com/kubernetes/kubernetes/issues/80609

这个问题可以解决吗?

  • 老外有个建议,就是用DoRaw方法得到api-server响应的原始body,然后自己做反序列化,我这里试了下
    在这里插入图片描述
  • 日志打印出原始body内容如下,太长了只截取部分
raw : {"kind":"PodList","apiVersion":"v1","metadata":{"resourceVersion":"12435998"},"items":[{"metadata":{"name":"nginx-deployment-78f6b696d9-cr47w","generateName":"nginx-deployment-78f6b696d9-","namespace":"client-go-tutorials","uid":"645628af-0d20-4548-b15d-0faf9e03b733","resourceVersion":"12227486","creationTimestamp":"2023-08-13T11:15:59Z","labels":{"app":"nginx-app","business-service-type":"web","language":"c","pod-template-hash":"78f6b696d9","service-update-time":"20230813120623","type":"front-end"},"annotations":{"cni.projectcalico.org/containerID":"e94b7b0ebe60d1cada361f7a672b2c6df71f2d89c4b5c1ae4056f82dec6a78db","cni.projectcalico.org/podIP":"100.91.64.45/32","cni.projectcalico.org/podIPs":"100.91.64.45/32"},"ownerReferences":[{"apiVersion":"apps/v1","kind":"ReplicaSet","name":"nginx-deployment-78f6b696d9","uid":"642c39e7-814a-491f-9b4f-295f34e959a3","controller":true,"blockOwnerDeletion":true}],"managedFields":[{"manager":"kube-controller-manager","operation":"Update","apiVersion":"v1","time":"2023-08-13T11:15:59Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:generateName":{},"f:labels":{".":{},"f:app":{},"f:business-service-type":{},"f:language":{},"f:pod-template-hash":{},"f:type":{}},"f:ownerReferences":{".":{},"k:{\"uid\":\"642c39e7-814a-491f-9b4f-295f34e959a3\"}":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"nginx-container\"}":{".":{},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:resources":{".":{},"f:limits":{".":{},"f:cpu":{},"f:memory":{}},"f:requests":{".":{},"f:cpu":{},"f:memory":{}}},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:enableServiceLinks":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}},
...
..
.
  • 拿到这样的json内容后,去工具网站转为go的数据结构代码,这样就能在代码中完成反序列化,例如:https://zxjson.com/json2go/, 如下图,转为go的数据接口
    在这里插入图片描述
  • 如此一来,跌跌撞撞的拿到了完整的json对象,当然了,这并不是个好的办法
  • 至此ypeMeta无效之谜已经解开,如果您有更好的解法或者更多官方消息,欢迎留言,感谢您的帮助

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

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

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

相关文章

uview ui 1.x ActonSheet项太多,设置滚动

问题:ActionSheet滚动不了。 使用uview ui :u-action-sheet, 但是item太多,超出屏幕了, 查了一下文档,并没有设置滚动的地方。 官方文档:ActionSheet 操作菜单 | uView - 多平台快速开发的UI框架 - uni-a…

【C语言】程序环境预处理 -- 详解

一、程序的翻译环境和执行环境 在 ANSI C 的任何一种实现中,存在两个不同的环境。 翻译环境,在这个环境中源代码被转换为可执行的机器指令。执行环境,它用于实际执行代码。 1、翻译环境 组成一个程序的每个源文件通过编译过程分别转换成目标代…

如何让qt tableView每个item中个别字用不同颜色显示?

如何让qt tableView每个item中个别字用不同颜色显示? 从上面图片可以看到,Item为红色,数字5为黑色。 要实现在一个控件实现不同颜色,目前想到的只有QTextEdit 。有两种方法,第一种是代理,第二种是通过setI…

python+mysql+前后端分离国内职位数据分析(源码+文档+指导)

系统阐述的是使用国内python职位数据分析系统的设计与实现,对于Python、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计,描述,实现和分析与测试方面来表明开发的过程。开发中使用了 Flask框架和MySql数据库技术搭建系统的整体…

Linux(实操篇二)

Linux实操篇 Linux(实操篇二)1. 常用基本命令1.3 时间日期类1.3.1 date显示当前时间1.3.2 显示非当前时间1.3.3 date设置系统时间1.3.4 cal查看日历 1.4 用户管理命令1.4.1 useradd添加新用户1.4.2 passwd设置用户密码1.4.3 id查看用户是否存在1.4.4 cat /etc/passwd 查看创建了…

【python】python智能停车场数据分析(代码+数据集)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

TypeError: ‘set‘ object is not subscriptable

问题出现的背景:写了一个python脚本,在脚本里用到了 pyexcel_xlsx 这个包,这个包可以读取excel文件。在本地运行可以运行成功,在Linux服务器上面运行报这个错。两边python都是用到3.8版本的,pyexcel_xlsx 版本也相同…

2023-8-26 字符串哈希

题目链接&#xff1a;字符串哈希 #include <iostream>using namespace std;typedef unsigned long long ULL;const int N 100010, P 131;char str[N]; ULL h[N], p[N];ULL get(int l, int r) {return h[r] - h[l - 1] * p[r - l 1]; }int main() {int n, m;cin >…

3000-6000元优质全单吉他推荐,雅马哈LL16、卡马A1、VEAZEN费森S88和伊斯特曼E1D深度评测对比,哪一款会是你心目中的首选呢?

对于初学新手和进阶的朋友来说&#xff0c;可以入手一把性价比很不错的吉他当然是最理想的&#xff0c;对音质和手感有更高要求的&#xff0c;后期想要演出需求的&#xff0c;不妨考虑全单吉他。下面就给大家推荐四款市面上3000-6000元比较热门值得推荐的全单吉他系列品牌&…

分类预测 | MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测

分类预测 | MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测 目录 分类预测 | MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测…

从源码到原理剖析activity核心知识点

如何在onResume方法中获取到View的宽高&#xff1f; 有两种方式&#xff1a;post和addOnGlobalLayoutListener override fun onResume() {super.onResume()Log.e("onresume",tabBottom.width.toString()"--"tabBottom.height.toString())//view.post之所以…

Docker之私有仓库 RegistryHabor

目录 一、Docker私有仓库&#xff08;Registry&#xff09; 1.1 Registry的介绍 二、搭建本地私有仓库 2.1首先下载 registry 镜像 2.2在 daemon.json 文件中添加私有镜像仓库地址 2.3运行 registry 容器 2.4Docker容器的重启策略 2.5为镜像打标签 2.6上传到私有仓库 2…

SpringBoot+MyBatisPlus+MySql+vue2+elementUi的案例、java访问数据库服务、java提供接口服务

文章目录 前言后端关键代码前端关键代码完整代码 前言 1、项目不使用前后端分离。 2、在创建SpringBoot的时候要注意各个插件间的版本问题。 3、后端技术SpringBootMyBatisPlusMySql。 4、前端技术vue2elementUi。 后端关键代码 简单介绍 1、数据库名称ssm_db 2、表名称tbl_bo…

「MySQL-03」用户管理与给用户授权

目录 一、用户管理 1. 用户信息 2. 创建用户 3. 删除用户 4. 修改用户密码 二、给用户授权 0.MySQL数据库提供的权限列表 1. 给用户授权 2. 回收权限 一、用户管理 1. 用户信息 1.0 数据库mysql和user表 安装好 MySQL后&#xff0c;里面会有一个默认的数据库mysql里面有一个u…

保姆级 Keras 实现 Faster R-CNN 十

保姆级 Keras 实现 Faster R-CNN 十 一. 建议区域矩形二. 定义 ProposalLyaer1. __init__函数2. build 函数3. call 函数3.1 生成 anchor_box3.2 找出 anchor 处最大分数, 最大分数对应的 anchor_box 和修正参数3. 3 修正 anchor_box3.4 完成 call 函数 4. compute_output_shap…

高精度地图定位在高速公路自动驾驶系统中的应用

近年来随着汽车保有量不断增加&#xff0c;随之而来的是: ( 1) 严重的交通拥堵&#xff0c;通行效率低下&#xff0c;用在通行上的时间不断增加; ( 2) 交通事故频发&#xff0c;交通事故导致的伤亡人数和费用不断增加&#xff0c;而且绝大多数事故是由人为因素导致的; ( 3) 大气…

视频批量剪辑利器!轻松在固定的位置上添加str字幕,

在如今的数字时代&#xff0c;视频内容的制作和分享变得越来越普遍。如果你是一个视频创作者&#xff0c;或者经常需要编辑和分享视频内容&#xff0c;那么我们为你带来了一款视频批量剪辑工具&#xff0c;让你轻松在固定位置添加字幕&#xff0c;打造专业级剪辑效果&#xff0…

Markdown中的LaTeX公式详解

引言 LaTeX是一种用于排版科学和数学文档的排版系统&#xff0c;它能够以高质量的方式生成复杂的数学公式。在CSDN&#xff08;Cnblogs和CSDN&#xff09;这样的博客平台中&#xff0c;也支持使用LaTeX语法插入数学公式。本文将详细介绍在CSDN中使用LaTeX公式的方法和常用语法&…

开源代码扫描工具 Socket新增对 Go 生态系统的支持

导读继日前宣布完成 2000 万美元的 A 轮融资后&#xff0c;开源代码扫描工具 Socket 紧接着宣布新增了对 Go 语言的支持&#xff1b;此前其仅支持 JavaScript 和 Python 语言。 “在过去的几个月中&#xff0c;我们观察到针对 Golang 的供应链攻击有所增加。意识到这种迫在眉睫…

聚类分析 | MATLAB实现基于FCM模糊C均值聚类结果可视化

聚类分析 | MATLAB实现基于FCM模糊C均值聚类结果可视化 目录 聚类分析 | MATLAB实现基于FCM模糊C均值聚类结果可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 FCM模糊C均值聚类&#xff0c;聚类结果可视化&#xff0c;MATLAB程序。 FCM&#xff08;Fuzzy C-Means&a…