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

欢迎访问我的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 Resulterr := 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 codeckind.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://xiahunao.cn/news/1618359.html

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

相关文章

WindowBuilder的安装

偶然间发现利用Eclipse原来也可以通过Java Swing像VB一样以拖拽的形式布局控件。 那就是在Eclipse中安装Window Builder插件。 1、在Eclipse中Help——Install New Software——在Work with中输入WindowBuilder的链接 WindowBuilder的链接:WindowBuilder | Downlo…

android获取当前windows,Android 中的 Window

一台 Android 手机屏幕上显示的内容就是由一个个 Window 组合而成的。顶部的状态栏是一个 Window,底部的导航栏也是一个 Window,中间自己的应用显示区域也是一块大 Window,Toast、Dialog 也都对应一个自己的 Window。而 Android 中对这些 Window 的管理是通过 一个框架的服务…

Flink Window机制详解

Flink 认为 Batch 是 Streaming 的一个特例,所以 Flink 底层引擎是一个流式引擎,在上面实现了流处理和批处理。而窗口(window)就是从 Streaming 到 Batch 的一个桥梁。Flink 提供了非常完善的窗口机制,这是我认为的 Fl…

window7下利用DockerToolbox安装Docker

这几天终于放假,有空在家深造下后端的知识。在通过某位大神的博客中深入学习redis时,知道了redis在window中的版本其实是阉割版(既非官方版)的,也就意味着很多功能没有,这对于以后的开发中可能造成隐患。当…

Window.innerHeight

Window.innerHeight 接口的只读innerHeight属性 Window返回窗口的内部高度(以像素为单位),包括水平滚动条的高度(如果存在)。值innerHeight取自窗口 布局视口的高度。可以使用该 innerWidth属性获得宽度。一个整数值&a…

window7 正式中文零售版(10.22版) 32位已提供下载,64位待更新

window7ULTIMATE 正式中文零售版(10.22版) 32(上传时间:2009-10-21 04:18:54) fs2you://Y2FjaGVmaWxlMzQucmF5ZmlsZS5jb20vemgtY24vZG93bmxvYWQvM2JlNzVkZjUzZTBjZmIzOTA1YWYwYjRmNDQ3MWM5ZjMvY25fd2luZG93c183X3VsdGl…

计算机Windows7③

一、操作系统 1.1操作系统的概念 操作系统可以控制和管理计算机的硬件和软件资源、控制程序执行、改善人机界面、合理组织计算机工作流程并为用户提供计算机运行环境的系统软件。 操作系统是人机接口,如果没有操作系统,则不能使用计算机,是裸…

STM32 Cubemx 同名外设中断及回调

文章目录 前言示例工程个人理解 前言 最近在学习STM32,采用HAL库开发方式。记录一下同名外设中断及回调。 这里提及的同名外设指USART1/2之类的相同外设,但不是同一个instance。 示例工程 以使用cubemx配置两个同名外设EXTI0/EXT4为例。 在NVIC配置…

Java语言程序设计 例题5.4(英里和公里的转化)

5.4 (Conversion from miles to kilometers) Write a program that displays the following table (note that 1 mile is 1.609 kilometers): Miles Kilometers 1 1.609 2 3.218 ... 9 14.481 10 16.090 5.4(英里和公里的转化)写一个程序显示下表&#x…

图片换脸-->>视频换脸-->>直播换脸

资源网站:https://tianfeng.space/ 个人娱乐,切勿作恶 下载 ​ 网盘:链接:https://pan.baidu.com/s/1DHMY1mCXpT0OtpmlvIoMKA 提取码:nf57 使用 下载解压后,打开 第一个就是你要替换的人脸,…

跟我学Springboot开发后端管理系统1:概述

前言 Matrxi-Web是一个前后端分离的管理系统,前端采用vue开发框架,后端使用springboot开发框架,具体快速开发、简单可复用的特点。只要把整体框架搭建起来了,后面就只用写CRUD了。 Matrxi-Web具备基本的管理系统的基本功能&…

跟我学SpringBoot之配置常见用法

只需低头努力,剩下的交给时光,时间会公平地帮你处理一切 配置基本用法 application.yml book:name: "Java"Value注解可以直接取配置的值 RestController EnableAutoConfiguration public class ConfigurationDemo {Value("${book.name…

《图解HTTP》——上野 宣

图解HTTP 看完这本书并在此博客下摘录书中的部分知识以便回顾。 第一章 了解Web及网络基础 1.1 使用HTTP协议访问Web Web使用一种名为HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成从客户端到服务器端等一系列运作流程。而协…

山西电力市场日前价格预测【2023-08-28】

日前价格预测 预测明日(2023-08-28)山西电力市场全天平均日前电价为319.70元/MWh。其中,最高日前电价为371.80元/MWh,预计出现在19: 15。最低日前电价为278.59元/MWh,预计出现在13: 00。 价差方向预测 1: …

2023.8 - java - 多态

多态是同一个行为具有多个不同表现形式或形态的能力。 多态就是同一个接口,使用不同的实例而执行不同操作, 多态的优点 1. 可替换性2 可扩充性3. 接口性、灵活性、简化性4. 消除类型之间的耦合关系 多态存在的三个必要条件 继承重写父类引用指向子类…

web系统添加盲水印

前言 为增加系统安全性,避免重要敏感信息通过截图方式泄露,对web页面增加盲水印标识,标注系统名称,登陆人,当前时间等信息,这里的盲水印指肉眼不可见的html水印 增加水印 引入watermark.js调用 watermar…

数字水印综述

目录 1.1 数字水印技术发展历史1.2水印检测1.3数据恢复阶段1.4 性能影响1.4.1水印嵌入算法性能1.4.2水印检测计算性能1.4.3数据恢复算法的计算性能1.4.4 水印隐藏率1.4.5 水印容量性能1.4.6 小结 2.1关系数据可逆水印参生的问题以及解决办法2.1.1 小结 3 总结4 数据溯源参考论文…

在图片上添加水印的四个方法

如何在图片上添加水印?在当今开放的互联网环境中,平时对于图片的使用已经变成非常广泛,越来越多的人开始关注图片的版权问题。如今,人们越来越注重防盗意识,这是因为我们在网上发布的图片很容易被别有用心之人盗用&…

水印怎么加在图片上,这些方法靠谱

水印怎么加在图片上?水印怎么弄在图片上,这里的意思就是给图片加上水印。在图片上添加水印通常是为了防止该图片被未经授权的复制或使用。水印可以是文字、图像或者其他标识符。添加水印的方法因软件而异,一般情况下,你可以使用专…

录音转文字下载哪个软件好?分享三个录音转文字神器

在一个小型创业公司里,有一位名叫艾米的创始人。她经常需要参加各种会议和讨论,以便与团队成员分享想法和制定发展策略。然而,她发现在每次会议结束后,整理会议记录非常耗时且容易遗漏重要信息。有时候,她还需要回顾之…