kubectl 源码分析

Cobra库

k8s各组件的cli部分都使用Cobra库实现,Cobra 中文文档 - 掘金 (juejin.cn),获取方式如下:

go get -u github.com/spf13/cobra@latest

cobra库中的Command结构体的字段,用于定义命令行工具的行为和选项。它们的作用如下:

Use: 命令名称。
Aliases: 命令的别名。
SuggestFor: 命令建议使用的单词列表。
Short: 命令简短描述。
GroupID: 命令所属的命令组。
Long: 命令详细描述。
Example: 命令的使用示例。
ValidArgs: 命令接受的参数列表。
ValidArgsFunction: 命令用于提供动态参数补全的函数。
Args: 命令的位置参数列表。
ArgAliases: 位置参数的别名。
BashCompletionFunction: 生成Bash补全的函数。
Deprecated: 命令是否已经过时的标志。
Annotations: 命令的附加注释信息。
Version: 命令版本号。
PersistentPreRun: 每次执行该命令之前都会执行的函数。
PersistentPreRunE: 每次执行该命令之前都会执行的返回错误的函数。
PreRun: 每次执行该命令之前都会执行的函数。
PreRunE: 每次执行该命令之前都会执行的返回错误的函数。
Run: 执行命令的函数。
RunE: 执行命令的返回错误的函数,RunE与Run的差别是,RunE执行有错误会直接return,Run无论是否有错误,都会继续执行后面PostRun和PersistentPostRun等逻辑。
PostRun: 每次执行该命令之后都会执行的函数。
PostRunE: 每次执行该命令之后都会执行的返回错误的函数。
PersistentPostRun: 每次执行该命令之后都会执行的函数。
PersistentPostRunE: 每次执行该命令之后都会执行的返回错误的函数。
FParseErrWhitelist : 忽略特定的解析错误
CompletionOptions :控制 shell 自动完成的选项
TraverseChildren: 解析父命令的标志后再执行子命令
Hidden : 隐藏命令,不在可用命令列表中显示
SilenceErrors : 静默下游错误
SilenceUsage : 静默错误时不显示用法
DisableFlagParsing : 禁用标志解析
DisableAutoGenTag : 禁用自动生成的标记
DisableFlagsInUseLine : 在打印帮助或生成文档时禁用“[flags]”在用法行中的添加
DisableSuggestions : 禁用基于Levenshtein距离的建议
SuggestionsMinimumDistance : 显示建议的最小Levenshtein距离

kubectl执行流程

创建cobra.Command对象

    主要流程在cmd.NewDefaultKubectlCommand()中,构建KubectlOptions对象(Kubectl Command的配置对象),指定插件、命令行参数、通用配置和输入输出流,然后调用NewDefaultKubectlCommandWithArgs函数创建Command对象,NewDefaultKubectlCommandWithArgs中调用NewKubectlCommand构建Command对象。

  • 创建&cobra.Command{实例,指定Run函数(执行cmd.help)。指定PersistentPreRunE函数,在Run前进行初始化。指定PersistentPostRunE函数,在Run后执行,将配置写入到磁盘。
  • 为所有的子命令和flag设置规范化函数cliflag.WarnWordSepNormalizeFunc,当参数中包含 "_" 时,会将参数中的 "_" 替换为 "-",同时提示警告信息。
  • addProfilingFlags(flags):增加性能调优的参数开关,统计CPU,内存等相关信息,用于性能优化
  • 添加bool类型全局标志warnings-as-errors,默认值为false
  • 创建ConfigFlags对象,设置命令参数,将参数解析值绑定到kubeConfigFlags
  • 添加一个是否匹配client与server版本的参数match-server-version
  • addCmdHeaderHooks(cmds, kubeConfigFlags):为为rest client 增加HTTP Header,依照SIG CLI KEP 859标准
  • 将kubeconfig对象包装成一个Factory类型,Factory是一个通用对象,它提供了与kube-apiserver的交互方式,以及验证资源对象等方法。 Factory接口封装了 DynamicClient、KubernetesClientSet(简称ClientSet)及RESTClient 3种client-go客户端与kube-apiserver交互的方式。
  • 添加所有的子命令,将所有命令存放在不同的group数组中,然后groups.Add(cmds)将所有的子命令添加,groups.Add函数中会调用cobra库中的AddCommand方法添加子命令。
  • 添加其他子命令。
  • 返回command对象

Command对象的执行

  创建了cobra.Command对象后,调用Kubectl封装的RunNoErrOutput方法,进入Command对象的执行。

  • 设置全局规范化参数cliflag.WordSepNormalizeFunc,将参数中的 "_" 替换为 "-"。
  • flag解析错误打印设置,如果有错误不打印使用方法
  • 日志相关设置
  • 调用 cmd.Execute() 函数执行command

  每个子命令的主要处理逻辑(cobra.Command.Run函数CompleteValidateRun三个函数,其中 complete() 函数中会将命令行参数整理对命令行options进行初始化,设置一些默认值;Validate() 函数会对options中的选项进行检查,打印相应的错误提示信息;Run()函数中执行各子命令的主要处理流程。

创建资源对象的过程(kubectl create -f FILENAME)

    创建资源对象的流程分为: 实例化Factory接口 、通过Builder和Visitor将资源对象描述文件(deployment.yaml)文本格式转换成资源对象。将资源对象以HTTP请求的方式发送给kube-apiserver,并得到响应结果。最终根据Visitor匿名函数集的errors判断是否成功创建了资源对象。

  • Factory是一个通用对象,它提供了与kube-apiserver的交互方式,以及验证资源对象等方法。 Factory接口封装了 DynamicClient、KubernetesClientSet(简称ClientSet)及RESTClient 3种client-go客户端与kube-apiserver交互的方式。
  • Builder用于将命令行获取的参数转换成资源对象(Resource Object)。它实现了一种通用的资源对象转换功能。
  • Kubernetes Visitor中存在多种实现方法, 不同实现方法的作用不同,如下:

RunCreate()函数流程

raw参数处理。

首先通过f.NewBuilder()实例化Builder对象, 通过函数Unstructured()、 Schema()、 ContinueOnError()、NamespaceParam()、 FilenameParam()、LabelSelectorParam()、 Flatten()对参数赋值和初始化, 将参数保存到Builder对象中。 最后通过Do()函数生成最终的rusult对象,设置rusult.visitor。

   // 实例化builder对象
r := f.NewBuilder().// 以map的方式传输数据对象,对响应内容中的数据做一层封装,这样就可以保留所有字段而不需要首先解析成一个structUnstructured().//Schema(schema).// 配置result对象在出现错误的行为,意思很明显,在出错后继续ContinueOnError().// 基于命令行参数设置查询的namespaceNamespaceParam(cmdNamespace).DefaultNamespace().// 解析文件名参数 参数 -f,文件名被存放在 b.paths 中FilenameParam(enforceNamespace,&o.FilenameOptions).// 解析标签选择器 参数 -lLabelSelectorParam(o.Selector). // 将对象展开,比如对象是[a, b], 如果没有flatten就是完成访问[a,b]作为一个整体,反之, 让外层函数分别访问a,bFlatten().// 基于之前的配置,生成最终的result对象Do()

Do函数中设置rusult.visitor多层匿名函数嵌套关系如下:

result.Visitor = DecoratedVisitor {    // 在函数Do函数中通过NewDecoratedVisitor函数执设置,并且注册了SetNamespace、RequireNamespace、FilterNamespace、RetrieveLazy等修饰函数。visitor: ContinueOnErrorVisitor {    // 在函数Do函数中,如果b.continueOnError为真设置,b.continueOnError在函数ContinueOnError()设置。visitor: FlattenListVisitor {    // 在函数Do函数中设置,这个感觉有点多余,在后面的流程中还会设置一个FlattenListVisitor。visitor: FilteredVisitor {    // 在函数visitByPaths中,含有Selector时设置,对每个对象对应的info对象进行检查,检查函数为FilterByLabelSelector(selector)。visitor: FlattenListVisitor {    // 在函数visitByPaths中,b.flatten为真时设置,b.flatten在上面的Flatten()函数中设为true。Visitor: EagerVisitorList {    // 在函数visitByPaths中将b.paths强转成EagerVisitorList,调用关系:Do() -> b.visitorResult() -> b.visitByPaths()。[]b.paths FileVisitor {    // 每个文件对应一个FileVisitor,所有的FileVisitor被append到 b.paths 数组中。StreamVisitor: StreamVisitor {Reader: r,mapper: mapper,Source: source,    Schema: b.schema,},},},},},},},
} 

执行Result.Visit(),该函数中会按照上面多层嵌套关系执行每一个Visit函数,按顺序 处理逻辑如下:

  • 从 DecoratedVisitor.Visit 一直到 EagerVisitorList.Visit都是在函数开始就直接执行对象的成员visitor的Visit函数,直到FileVisitor.Visit中才是先执行本身的流程,然后再执行对象的成员visitor的Visit函数。
  • FileVisitor:打开xml文件,读取里面的数据到一个io.Reader中,然后执行StreamVisitor.Visit。
  • StreamVisitor:对xml文件中的数据进行解码,然后执行 infoForData 函数将解码后的数据转换成info对象,然后执行 EagerVisitorList定义的VisitorFunc(通过 FileVisitor 转传入)。
  • EagerVisitorList:将所有的err信息收集到一个集合中返回,如果StreamVisitor出现错误直接 return,如果没有错误执行FlattenListVisitor定义的VisitorFunc
  • FlattenListVisitor:如果yaml文件中包含多个资源对象,将runtime.ObjectTyper解析成多个runtime.Object,再转换为多个Info,逐个调用VisitorFunc,即执行FilteredVisitor定义的VisitFunc函数。
  • FilteredVisitor:对Info进行检验, 进行Selector检查。如果不满足条件,则返回error信息,如果满足条件则执行VisitorFunc,即FlattenListVisitor定义的VisitFunc函数
  • FlattenListVisitor:因为上面已经执行过一次FlattenListVisitor了,这里会直接执行ContinueOnErrorVisitor定义的VisitorFunc
  • ContinueOnErrorVisitor:将Visitor调用过程中产生的错误保留在[]error中,然后执行DecoratedVisitor定义的VisitorFunc
  • DecoratedVisitor:执行注册过的VisitorFunc,然后执行result指定的VisitorFunc。
  • Result指定的VisitFunc:通过Helper.Create向kube-apiserver发送创建资源的请求,然后将与kube-apiserver交互后得到的结果通过info.Refresh函数更新到info.Object中。Helper.Create最终会进入createResource函数
func (m *Helper) createResource(c RESTClient, resource, namespace string, obj runtime.Object, options *metav1.CreateOptions) (runtime.Object, error) {// RESTFUL接口风格中,POST请求对应的就时CREATE方法return c.Post(). NamespaceIfScoped(namespace,m.NamespaceScoped).Resource(resource).VersionedParams(options,metav1.ParameterCodec).Body(obj).// 发送请求Do(context.TODO()).// 将请求结果转换成runtime.ObjectGet()
}

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

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

相关文章

56K star!一键拥有跨平台 ChatGPT 应用:ChatGPT-Next-Web

前言 现在围绕 openai 的客户端层出不穷,各路开发大神可以说是各出绝招,我也试用过几个国内外的不同客户端。 今天我们推荐的开源项目是目前我用过最好的ChatGPT应用,在GitHub超过56K Star的开源项目:ChatGPT-Next-Web。 ChatGP…

一创聚宽停止服务,散户可以选择它!

第一创业和聚宽停止合作!还有什么量化平台可选? 先了解背景: 从2023年9月25日起,一创聚宽的量化交易平台暂停开通交易权限,到2023年12月29日,一创聚宽量化交易平台将停止提供所有服务。这一消息对于之前使…

Python基础入门第七课笔记(自定义函数 define)

函数 函数必须先定义再调用 函数必须先定义再调用 函数必须先定义再调用 定义函数: def 函数名(形参): 代码1 代码2 ………. 调用函数: 函数名(实参) 形参&…

Spring MVC响应结合RESTful风格开发,打造具有强大功能和良好体验的Web应用!

响应与Rest风格 1.11.1.1 环境准备步骤1:设置返回页面步骤2:启动程序测试 1.1.2 返回文本数据步骤1:设置返回文本内容步骤2:启动程序测试 1.1.3 响应JSON数据响应POJO对象响应POJO集合对象 知识点1:ResponseBody 2,Rest风格2.1 REST简介2.2 RESTful入门案…

技术概述:ARMv8体系结构

John Goodacre, Director Program Management ARM Processor Division, November 2011 背景:ARM体系结构 从ARM精简指令集体系结构提出到现在已经有20多年了;ARMv7系列处理器是在ARMv4基础上设计的,随着ARMv7系列处理器大量应用&#xff0…

争做智驾“第一阵营”,锚定“全球前五”,小米汽车底气何在?

“官宣”造车超1000天后,低调行事的小米终于进行了首次“军火展示”。 2023年12月28日,小米集团(HK:01810,下称“小米”)在北京举办小米汽车技术发布会,公布了小米汽车核心技术及首款产品小米SU7。按照规划…

对话新七天创始人&CEO左英杰:品牌直播电商出圈“五步法”

整理 | 飞族 编辑 | 渔舟 出品|极新&北京电子商务协会 AI、AIGC、VR等数智化新技术发展日新月异,在直播电商领域的应用和探索逐渐深入,从内容生成、创意优化、购物体验、智能客服、精准营销等方面提供全方位全链路的赋能&#…

用C语言采集游戏平台数据并做行业分析

目录 一、数据采集方法 日志采集 API采集 二、数据采集流程 确定采集目标 选择采集方法 编写采集程序 数据清洗和整理 三、行业分析方法 对比分析 趋势分析 分类分析 四、案例分析:基于C语言的实时游戏平台数据采集与行业分析系统实现 五、结论 随着游…

windows 10 安装wsl ubuntu

1.首先管理员模式打卡powershell,执行 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart 2.执行 wsl --update wsl --…

python 基础语法函数

函数定义 def 函数名(形参列表用逗号隔开): 函数体 return 返回值 # 有参数 无返回值 def my_length(data):count 0for i in data:count 1print(f"data count{count}")my_length(str1) my_length(str2)#无参数无返回值 def say_hello():print("h…

全网唯一值得推荐的C/C++框架和库

全网唯一值得推荐的C/C框架和库 C程序员开发指南 ​ 关注我,天天分享C/C开发技术干货! ​关注他 30 人赞同了该文章 ​ 目录 收起 标准库 C通用框架和库 人工智能 异步事件循环 音频 生态学 压缩 并发性 容器 数据库 调试 游戏引擎 图…

西门子消防主机控制面板显示盘维修B3Q565

作为图形监控主机,负责接收并储存各消防设备主要运行状态,接收火灾报警并显示报警部位,包括火灾报警、状态监视、设备故障报警、网络故障报警﹐指挥抢险救援的活动,进行火灾信息的处理与传送,同时具备提示操作人员的功能&#xff…

TS:类型断言

类型断言好比其他语言中的类型转换,但是不是真正的类型转换方式,之所以不被称为类型转换,是因为转换通常意味着某种运行时的支持。但是,类型断言纯粹是一个编译时语法,同时,它也是一种为编译器提供关于如何…

使用代理IP实现爬虫的匿名性

目录 前言 一、什么是代理IP? 二、使用Python实现代理IP爬虫 1. 安装所需模块 2. 获取代理IP列表 3. 使用代理IP进行爬取 4. 使用代理IP进行数据抓取 三、总结 前言 随着互联网的快速发展,网络爬虫已经成为了获取互联网数据的一种重要方式。然而…

原生JS实现抽奖

1、效果展示 0. 制作一个MiniSize使用提供的素材实现一个转盘活动的布局(如下图所示); 进入界面后2秒钟后开始旋转,5秒钟后停止旋转;并且3秒后进入一个表单界面(如下图2所示);界面…

vins 实机测试 rs_d435 + imu

vins 实机测试 文章目录 1. imu标定2. camera内参标定3. imu-cam 外参标定4. vins 实际运行5. realsense 1. imu标定 git clone https://github.com/gaowenliang/code_utils.git git clone https://github.com/gaowenliang/imu_utils.git编译运行, roslaunch imu_…

Unity 圆角 线段 绘制 LineRender

需求 绘制圆角 核心函数 /// <summary>/// 点ABC 形成的角度必须为90 点c为中间的点/// </summary>/// <param name"a"></param>/// <param name"b"></param>/// <param name"c"></param>/// &…

CH08_管理状态

Observer 模式 观察者模式&#xff08;Observer&#xff09;&#xff0c;又叫发布订阅模式&#xff08;Publish/Sunscribe&#xff09;模式&#xff0c;定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时&#xf…

2个nodejs进程利用redis 实现订阅发布

1.新建文件 redis_db.js use strict;const redis require(redis); const options {host: "127.0.0.1",port: 6379,password: "123456", // CONFIG SET requirepass "123456" }var array [] for(var i0; i<3; i){const client redis.crea…

MySQL数据库的CURD、常见函数及UNION和UNION ALL

一、概述 MySQL是一种流行的关系型数据库管理系统&#xff0c;广泛应用于各种应用场景。在MySQL中&#xff0c;CURD操作是指创建&#xff08;Create&#xff09;、读取&#xff08;Read&#xff09;、更新&#xff08;Update&#xff09;和删除&#xff08;Delete&#xff09;…