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/…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
