Kubernetes对象深入学习之五:TypeMeta无效之谜
欢迎访问我的GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
- 本文是《Kubernetes对象深入学习之五》系列的第五篇,从前文的分析也能看出,代表对象类型的schema.ObjectKind,于对象而言是至关重要的,那是它的类型和身份,既然如此,与之有关的问题也不能放过,因此本篇就来看一个对象类型相关的问题,本文由以下内容组成:
- 复现问题:我的代码中获取的对象类型为空
- 问题原因
- 为什么会有这个问题?
- 这个问题有解吗?
复现问题
- 问题很容易复现,回顾《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无效之谜已经解开,如果您有更好的解法或者更多官方消息,欢迎留言,感谢您的帮助
你不孤单,欣宸原创一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 数据库+中间件系列
- DevOps系列
相关文章:

Kubernetes对象深入学习之五:TypeMeta无效之谜
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是《Kubernetes对象深入学习之五》系列的第五篇,从前文的分析也能看出,代表对象类型的schema.ObjectKind,于…...

Gitlab设置中文
1. 打开设置 2.选择首选项Preferences 3. 下滑选择本地化选项Localization,设置简体中文,然后保存更改save changes。刷新网页即可。...
【微服务部署】05-安全:强制HTTPS
文章目录 安全 : 强制HTTPS的两种方式1. Ingress配置重定向2. 应用程序配置3. Ingress配置4. 应用程序配置代码总结 安全 : 强制HTTPS的两种方式 互联网发展中,安全是非常重要的,由其是现在HTTPS非常普及的情况下,应用程序在公网上一般都会被…...

Config:服务端连接Git配置
创建子模块 Pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org…...
c++学习 之 类和对象 public , protected ,private
前言 在C中,访问控制修饰符(Access Control Modifiers)用于控制类的成员(成员变量和成员函数)的访问权限。这些修饰符分为三种:public、protected和private。它们定义了成员可以在何处访问,具体…...

ECharts图表动态修改series显示隐藏
文章目录 1、前言2、思路3、实现 1、前言 最近做的大数据平台,里面很多部分用到了ECharts,其中有个功能,要求将图表分组,根据用户选择的组,来确定ECharts要显示那些线条和柱子,也就是动态的显示option.seri…...

云服务器(Centos7系统)配置JAVA+mysql+tomcat 环境
文章主要内容来源云服务器(Centos7系统)部署javaweb项目(二)配置JAVAmysqltomcat 环境_man_zuo的博客-CSDN博客 模仿途中遇到的问题 连接无效 有时连接无法下载,可能是过期了,将其更换为官网给的下载连接即…...
【计算机视觉 | 目标检测】目标检测常用数据集及其介绍(四)
文章目录 一、JTA (Joint Track Auto)二、AVD (Active Vision Dataset)三、ExDark (Exclusively Dark Image Dataset)四、InteriorNet五、ScanRefer Dataset六、FlickrLogos-32七、SIXray八、Clear Weather (DENSE)九、DVQA (Data Visualizations via Question Answering)十、M…...

Dockerfile制作镜像与搭建LAMP环境
一.编写Dockerfile制作Web应用系统nginx镜像,生成镜像nginx:v1.1,并推送其到私有仓库。具体要求如下: (1)基于centos基础镜像; (2)指定作者信息; (3ÿ…...
Linux系统中查看端口的方法
一、使用netstat命令 netstat命令是一种非常实用的命令,可以用来显示网络连接、路由表、网络接口和网络统计信息等。它还可以用来显示系统中正在监听的端口。要查看端口,只需在终端中输入以下命令: netstat -tuln 这个命令的意思是列出所有…...
java mysql传入string数组返回string数组的简单写法
一、前言 最近有个需求,需要一个传入string数组返回string数组的sql逻辑。 懒得封装成javabean了,于是就写了一个简单的样例,总结下。 二、代码 1.mapper.java,可以这样写: public interface MyMapper {String[] …...

【PHP】PHP基本语法
1、PHP标记 当解析一个文件时,PHP 会寻找起始和结束标记,也就是 <?php 和 ?>,告诉 PHP 开始和停止解析二者之间的代码。此种解析方式使得 PHP 可以被嵌入到各种不同的文档中去,而任何起始和结束标记之外的部分都会被 PHP…...

SystemVerilog interface详细介绍
1. Interface概念 System Verilog中引入了接口定义,接口与module 等价的定义,是要在其他的接口、module中直接定义,不能写在块语句中,跟class是不同的。接口是将一组线捆绑起来,可以将接口传递给module。 2. 接口的优…...
计网第四章(网络层)(三)
IPV4地址的应用规划: 定长的子网掩码FLSM: 使用同一个子网掩码划分子网,每个子网所分配的IP地址数量相同,造成IP地址的浪费。 变长的子网掩码VLSM: 使用不同的子网掩码划分子网,每个子网所分配的IP地址…...

python学习1之安装
前言 目前,Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的。由于3.x版越来越普及,我们的教程将以最新的Python 3.9版本为基础。 1、下载 官网地址 https://www.python.org/downloads/ 2、安装 点击…...
Autofac在WebApi,Winform中应用
安装注意事项 使用AOP的时候需要安装Autofac.Extras.DynamicProxy,如果发现VS老是提示报错,需要把VS重启下才可以识别。 WebApi 注意事项:WebApi中多一个ApiController中构造注入功能。 注入和AOP拦截 var siteNameList ClassHelper.GetConstants(typeof(SiteName));//创建…...

uview ui 查看版号
版本查询2种方式 有两种方式可以查询到正在使用的uView的版本: // 通过console.log打印的形式 console.log(uni.$u.config.v);// 可以查阅uView的配置文件得知当前版本号,具体位置为: /uview-ui/libs/config/config.js...
Python 爬虫网页图片下载到本地
您可以使用Python的requests库来获取网页的源码,使用BeautifulSoup库来解析HTML,并使用urllib库来下载图片到本地。下面是一个示例代码: import requests from bs4 import BeautifulSoup import urllib # 获取网页源码 url https://examp…...

PyQt open3d 加载 显示点云
PyQt加载 显示点云,已经有三种方式,使用 open3d; 使用 vtk; 使用 pcl; 下面是使用 open3d: import sys import open3d as o3d import numpy as np import pyqtgraph.opengl as gl from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QFi…...

Linux搭建SSLVpn
安装http、ssl服务 编辑http配置文件 修改http的136行,276行以及990行 1、136行将监听端口注释 2、276行和990行修改为自己的域名和要访问的端口 修改http文档最后那部分 新添ssl配置信息,将端口修改为443(截图错了server.key应该放在/etc/…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...