K8S 源码探秘 之 命令行解析工具 cobra

从k8s当中学习go cli脚手架开发利器-cobra 在Run()在设定了一系列的参数信息后,创建了cmd对象,并执行cmd对象的Execute(),这里的cmd对象就是一个cobra命令对象,而Execute是cobra提供执行命令的方法,cobra内部使用pflag库,通过设置 pflag 属性,可以对 cobra 的运行产生作用。cobra对象如何生成的,是我们需要关心的,**NewKubeadmCommand(os.Stdin, os.Stdout, os.Stderr)**的实现在cmd/kubeadm/app/cmd/cmd.go。 阅读详情

一、引言

        最近开始研读 Kubernetes 源码,希望能借此更加深入地理解其运行机理!

        由于 Kubernetes 代码量很庞大,我将分模块分组件地去分析和理解,并把自己的发现共享出来。

        第一篇博客,先从简单的命令行解析工具 cobra 开始。

二、源码解析

        Kubernetes 中的组件(如 kubeadm、kubectl 等)都是命令行方式运行的,命令解析是重要一步

        在 Kubernetes 系统中,cobra 被广泛应用,因为其实在是非常的简单易用

        关于 cobra 的更多资料,可以参考其 GitHub 官网:https://github.com/spf13/cobra

        下面以 kubeadm 为例,看一下 cobra 是怎么被使用的吧

        首先,找到 kubeadm 的入口,cmd/kubeadm/kubeadm.go

package main

import (
	"fmt"
	"os"

	"k8s.io/kubernetes/cmd/kubeadm/app"
)

func main() {
	if err := app.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}
	os.Exit(0)
}

        这里,直接调用了 app.Run() 方法,可见这只是个壳子,真正的逻辑在 k8s.io/kubernetes/cmd/kubeadm/app

        然后,我们跟踪到 cmd/kubeadm/app/kubeadm.go,找到其 Run 方法

package app

import (
	"flag"
	"os"

	_ "github.com/golang/glog"
	"github.com/spf13/pflag"

	utilflag "k8s.io/apiserver/pkg/util/flag"
	"k8s.io/kubernetes/cmd/kubeadm/app/cmd"
)

// Run creates and executes new kubeadm command
func Run() error {
	pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc)
	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)

	pflag.Set("logtostderr", "true")
	// We do not want these flags to show up in --help
	// These MarkHidden calls must be after the lines above
	pflag.CommandLine.MarkHidden("version")
	pflag.CommandLine.MarkHidden("google-json-key")
	pflag.CommandLine.MarkHidden("log-flush-frequency")
	pflag.CommandLine.MarkHidden("alsologtostderr")
	pflag.CommandLine.MarkHidden("log-backtrace-at")
	pflag.CommandLine.MarkHidden("log-dir")
	pflag.CommandLine.MarkHidden("logtostderr")
	pflag.CommandLine.MarkHidden("stderrthreshold")
	pflag.CommandLine.MarkHidden("vmodule")

	cmd := cmd.NewKubeadmCommand(os.Stdin, os.Stdout, os.Stderr)
	return cmd.Execute()
}

        可以看到,Run 方法在设定了一系列的参数属性信息后,创建了一个 cmd 对象,并执行了其 Execute 方法

        经过分析,这里的 cmd 对象就是一个 cobra 命令对象,而 Execute 正是 cobra 提供的执行命令的方法  

        cobra 内部使用了 pflag 库,这里通过设置 pflag 属性,可以对 cobra 的运行产生作用

        pflag 也兼容 golang flag 库,这里通过 AddGoFlagSet(flag.CommandLine) 实现了对 golang flag 的兼容

        紧接着,我们跟踪到 NewKubeadmCommand 的函数实现, cmd/kubeadm/app/cmd/cmd.go

// NewKubeadmCommand returns cobra.Command to run kubeadm command
func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command {
	var rootfsPath string

	cmds := &cobra.Command{
		Use:   "kubeadm",
		Short: "kubeadm: easily bootstrap a secure Kubernetes cluster",
		Long: dedent.Dedent(`
			kubeadm: easily bootstrap a secure Kubernetes cluster.

			    ┌──────────────────────────────────────────────────────────┐
			    │ KUBEADM IS CURRENTLY IN BETA                             │
			    │                                                          │
			    │ But please, try it out and give us feedback at:          │
			    │ https://github.com/kubernetes/kubeadm/issues             │
			    │ and at-mention @kubernetes/sig-cluster-lifecycle-bugs    │
			    │ or @kubernetes/sig-cluster-lifecycle-feature-requests    │
			    └──────────────────────────────────────────────────────────┘

			Example usage:

			    Create a two-machine cluster with one master (which controls the cluster),
			    and one node (where your workloads, like Pods and Deployments run).

			    ┌──────────────────────────────────────────────────────────┐
			    │ On the first machine:                                    │
			    ├──────────────────────────────────────────────────────────┤
			    │ master# kubeadm init                                     │
			    └──────────────────────────────────────────────────────────┘

			    ┌──────────────────────────────────────────────────────────┐
			    │ On the second machine:                                   │
			    ├──────────────────────────────────────────────────────────┤
			    │ node# kubeadm join <arguments-returned-from-init>        │
			    └──────────────────────────────────────────────────────────┘

			    You can then repeat the second step on as many other machines as you like.

		`),

		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			if rootfsPath != "" {
				if err := kubeadmutil.Chroot(rootfsPath); err != nil {
					return err
				}
			}
			return nil
		},
	}

	cmds.ResetFlags()

	cmds.AddCommand(NewCmdCompletion(out, ""))
	cmds.AddCommand(NewCmdConfig(out))
	cmds.AddCommand(NewCmdInit(out))
	cmds.AddCommand(NewCmdJoin(out))
	cmds.AddCommand(NewCmdReset(in, out))
	cmds.AddCommand(NewCmdVersion(out))
	cmds.AddCommand(NewCmdToken(out, err))
	cmds.AddCommand(upgrade.NewCmdUpgrade(out))

	// Wrap not yet fully supported commands in an alpha subcommand
	experimentalCmd := &cobra.Command{
		Use:   "alpha",
		Short: "Experimental sub-commands not yet fully functional.",
	}
	experimentalCmd.AddCommand(phases.NewCmdPhase(out))
	cmds.AddCommand(experimentalCmd)

	AddKubeadmOtherFlags(cmds.PersistentFlags(), &rootfsPath)

	return cmds
}

         该函数首先构造了 kubeadm 的根命令对象 cmds(也就是 kubeadm 命令)

         然后依次将 kubeadm 的子命令(如 init、join)等通过 cmds.AddCommand()方法添加到 cmds 对象

         可见,cmd/kubeadm/app/kubeadm.go 中末尾执行的 cmd.Execute() 正是执行的这个 cmds 的 Execute() 方法

         各个子命令的构造大同小异,为了简单起见,我们看一下 NewCmdVersion 是如何实现的吧

         跟踪到 cmd/kubeadm/app/cmd/version.go

// NewCmdVersion provides the version information of kubeadm.
func NewCmdVersion(out io.Writer) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "version",
		Short: "Print the version of kubeadm",
		Run: func(cmd *cobra.Command, args []string) {
			err := RunVersion(out, cmd)
			kubeadmutil.CheckErr(err)
		},
	}
	cmd.Flags().StringP("output", "o", "", "Output format; available options are 'yaml', 'json' and 'short'")
	return cmd
}

         我们看到,NewCmdVersion 函数同样返回了一个 cobra Command 对象,

         而与之前看到的根命令 kubeadm不同的是

         这里 version 子命令的定义中包含了运行实体 Run 函数的具体定义,

         这表明 version 命令不再是父级命令了,它能真正被执行

         至于 version 命令可以识别的参数,可以通过 cmd.Falgs() 设定

         这里把输入的参数直接绑定到 output 上了,使用的时候可以通过 cmd.Flags().GetString(“output”) 获取

三、源码分析总结

        整体而言,kubernetes 命令的执行是通过组合 cobra command 生成父子命令树,

       最终命令的执行是在树的叶节点上通过 Run: func(cmd *cobra.Command, args []string){...} 定义的     

       命令参数通过 cmd.Flags() 设置

       主函数 main 通过调起根命令的 Execute 激活整个命令解析和执行过程

  

  四、实验验证

          实验代码 GitHub 地址:https://github.com/SataQiu/k8s-learn/tree/master/cobra-example

package main

import (
	"fmt"
	"github.com/spf13/cobra"
)

func NewRootCommand() *cobra.Command {
	cmds := &cobra.Command{
		Use:   "cobra-example",
		Short: "cobra-example: my first cmd tool based on cobra.",
	}
	cmds.AddCommand(NewSubCommandOfHello())
	cmds.AddCommand(NewSubCommandOfBye())
	return cmds
}

func NewSubCommandOfHello() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "hello",
		Short: "Say hello.",
		Run: func(cmd *cobra.Command, args []string) {
			name, _ := cmd.Flags().GetString("name")
			fmt.Println("Welcome " + name)
		},
	}
	cmd.Flags().StringP("name", "n", "", "Name: input your name.")
	return cmd
}

func NewSubCommandOfBye() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "bye",
		Short: "Say bye.",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Bye!")
		},
	}
	return cmd
}
func main() {
	cmd := NewRootCommand()
	cmd.Execute()
}

          这里,我们首先定义一个根命令 cobra-example,然后添加两个子命令 hello 和 bye,其中 hello 可以接受 name 参数

          试验一下,执行编译后的二进制文件

           

           执行子命令

           

           

kubernetes源码分析-基础命令库cobra cobra 是go语言创建命令很好的一个工具, cobra 是由 spf13 写的 golang 库, 地址: https://github.com/spf13/cobra k8s cmd是基于cobra的 例如 cmd/kube-controller-manager/app/controllermanager.go NewControllerManagerCommand定义如下: cmd := &cobra.Command{ Use: "kube-controller-manager", 阅读详情

相关推荐

dedent:从多行字符串中删除所有常见的前导空格

凹痕 从多行字符串中删除常见的前导空格。 受Python中的启发。 用法/示例 想象以下打印多行字符串的代码段。 您希望缩进在代码和实际输出中都看起来不错。 package main import ( "fmt" "github.com/lithammer/dedent" ) func main () { s := ` Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur justo tellus, facilisis nec efficitur dictum, fermentum vitae ligula. Sed eu convallis sapien.` fmt . Println ( dedent . Dedent ( s )) fmt . Println ( "-----

k8s学习之cobra命令库学习

打开k8s代码的时候,我发现基本上那几个核心服务都是使用cobra库作为命令行处理的能力。因此,为了对代码之后的代码学习的有比较深入的理解,因此先基于这个库写个demo,加深对这个库的一些理解吧在这里了,Cobra是一个用Go语言实现的命令行工具。并且现在正在被很多项目使用,例如:Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速的创建命令行工具,特别适合写测试脚本,各种服务的Admin CLI等。

wintree的专栏 1607

WRF所需气象数据的下载方法

#数据下载是个大问题,巧妇难为无米之炊,没有数据就无法模拟啦,疫情期间国外服务器响应慢,打开网页慢都很正常啦~ WRF数据所需要的外部数据分为两种:静态地理数据,grib格式的气象数据(NAM、GFS、RUC、AGRMET等)。静态地理数据可以从WRF官网获得,比较简单,这里不做介绍。所以这篇日志重点介绍的是气象数据的获取。 提前说明,WRF官网不提供气象数据,但WRF官网提供各类气象数据的下载网址链接,所以我们下载一般还是从WRF官网开始。首先进入WRF官网,然后点击WRF ARW Uusres’ .

六出的博客 1万+

零基础入门Cobra---kubernetes源码学习必备

Cobra 是用 go 语言实现的用于创建 CLI 应用程序和命令文件的工具。许多 Go 的项目都是使用 Cobra 构建的,包括:kubernetesetcdhugodocker……本篇...

1721

STM32H7多通道ADC数据采集实战:CubeMX配置ADC1/2/3+DMA/BDMA+Cache避坑全记录

本文详细解析了STM32H7多通道ADC数据采集的实战配置,涵盖CubeMX中ADC1/2/3与DMA/BDMA的协同设置及Cache一致性处理。通过硬件架构分析、DMA优化技巧和Cache避坑指南,帮助开发者实现高精度数据采集,适用于电机控制、环境监测等嵌入式系统。

weixin_28744613的博客 292

深入剖析:功率放大电路设计精髓——从理论到实践

输入信号首先被调制(通常是PWM脉宽调制)成高频开关信号,驱动功率开关管(MOSFET),再通过LC低通滤波器滤除高频分量,还原出放大的音频信号。在靠近功放板电源引脚处放置足够容量的电解电容(如100uF - 1000uF)和高频瓷片电容(如0.1uF)并联进行电源去耦,抑制低频和高频干扰,防止低频振荡(Motorboating)和高频自激。,堪称电子世界里的“能量转换器”。当输入信号在零附近(即两个器件切换导通的区域)时,由于器件的开启电压(Vbe或Vgs)不为零,输出波形会出现明显的衔接不流畅的失真。

Zihan2558的博客 1698

golang工程组件之命令行框架cobra

而cobra则是一个非常受欢迎的Golang工程组件之一,它提供了简单易用的命令行框架,并且支持子命令、Flag解析、嵌套等高级特性。通过使用cobra,我们可以轻松地创建各种复杂的命令行工具,并实现Flag解析、子命令、嵌套等高级功能。同时,cobra还提供了丰富的自定义选项,使我们能够轻松地扩展和定制我们的命令行工具。在上面的例子中,我们创建了一个名为nestedCmd的嵌套命令,并将其添加到subCmd对象中。在上面的例子中,我们添加了一个名为subCmd的子命令,并将其添加到rootCmd对象中。

SMILY12138的博客 1449

LEF文件介绍及其生成

介绍LEF文件及其生成方法

weixin_43249158的博客 3万+

k8s源码分析 pdf_k8s源码分析之Cobra

一、Cobra简介cobra:既是一个用来创建强大的现代CLI命令行的golang库,也是一个生成程序应用和命令行文件的程序.官网地址: https://github.com/spf13/cobraCobra主要提供的功能* 简易的子命令行模式,如 app server, app fetch等等* 完全兼容posix命令行模式* 嵌套子命令subcommand* 支持全局,局部,串...

weixin_39963523的博客 367

万达电影 com.wandafilm.app headers check

万达电影 安卓逆向 抓包 逆向 check

weixin_43786514的博客 1438

打造你自己的小程序容器 —— 一套能装得下整个未来的跨端技术!

摘要: 本文介绍了一种基于Capacitor框架开发的轻量级“小程序容器”解决方案——LapDrop。通过模拟微信小程序的运行逻辑(动态加载、原生能力调用、沙盒环境),LapDrop允许开发者自主构建跨平台(iOS/Android/Web)的小程序生态。其核心利用Capacitor的插件桥接机制,实现JS与原生功能的无缝调用,并支持浏览器调试与原生环境一致化。优势包括插件化架构、状态隔离、热更新及开放权限控制,适用于企业级模块化应用或开发者工具。未来计划扩展生命周期管理、远程加载等功能,目标成为开源的小程序

CangYuChenAi的博客 976

Cobra:一种基于golang的命令行开发框架(一)

介绍cobra框架的用法,帮助快速上手命令行开发

weixin_38757398的博客 2246

IMU标定中的Allen方差

Allen方差 Allen方差是IMU标定任务中的常用工具。IMU标定可以分为确定性误差和随机误差,确定性误差包括:scale、bias、misalignment。随机误差则主要是高斯白噪声和bias随机游走。Allen方差主要用于标定随机误差。 Allen方差获取 Allen方差的计算方法如下: 保持IMU静止, 采集N个数据点。 将N个点定长分组,常用的交叠式Allen方差如下(n=3): 对于每个子集,计算均值后,计算相邻两组的方差,得到的时间-方差曲线即为Allen方差。 Alle

realjc的博客 5735

从kubectl源码学Cobra:打造专业级Go命令行工具的完整实践

深入实践:选项(Flags)和参数(Args) Flags:控制命令行为的开关 Cobra支持两种类型的选项: 1. Persistent Flags(持久选项) 全局有效,适用于当前命令及其所有子命令 常用于日志级别、配置文件路径等全局配置 示例:rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "显示详细输出") 2. Local Flags(局部选项) 仅当前命令有效 适用于特定命令的专有配置 示例:deployCm

java_cj的专栏 462

PyTorch深度学习实战(6)——神经网络性能优化技术

神经网络性能优化技术是指通过改进神经网络的结构、参数初始化、正则化和训练过程等方面来提高其性能和泛化能力的方法。优化技术的选择和调试需要根据具体问题进行,通过不断实验和调整,找到最适合网络的优化策略。本节首先训练了一个简单的全连接网络,然后在此基础上介绍了简单有效的神经网络性能提升技巧。

盼小辉丶的博客 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

FilamentPHP v3.3.8 表单构建器提速指南:加载时间减半是怎么做到的

FilamentPHP v3.3.8 已发布,这次更新的核心变化集中在表单构建器:复杂表单的平均加载时间从 500ms 压缩到 250ms 以内,整体性能提升约 50%。对于依赖 Filament 搭建 Laravel 后台管理系统的团队来说,这是一次直接改善日常体验的版本。 [![FilamentPHP表单界面示例](https://raw.gitcode.com/GitHub_Trendin

gitblog_00693的博客 939

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

kubernetes 1.24.2实战与源码(1)

kubectl的职责主要的工作是处理用户提交的东西(包括,命令行参数,yaml文件等)然后其会把用户提交的这些东西组织成一个数据结构体然后把其发送给API Serverkubectl的代码原理cobra从命令行和yaml文件中获取信息通过Builder模式并把其转成一系列的资源最后用Visitor模式来迭代处理这些Resources,实现各类资源对象的解析和校验用RESTClient将Object发送到kube-apiserverkubectl架构图create流程。

niwoxiangyu的博客 2280

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Kubernetes api-server源码阅读3(源码篇)正在更新中

本文是 Kubernetes api-server源码阅读 系列第三篇,主要学习 kubernetes api-server 的 源码,参考B站 Kubernetes源码开发之旅

a1369760658的博客 802

《kubernetes源码剖析》阅读笔记

概括了《kubernetes源码剖析》介绍的一些重要架构和算法以及概念,例如:client-go,informer, 限速算法和调度算法等

weixin_62437742的博客 924

Kubernetes apiserver 源码解析

要编译 Kubernetes 项目,需要先配置好 Golang 环境,本文以 v1.15.2 版本为例。Kubernetes 项目源代码可在 https://github.com/kubernetes/kubernetes 找到。

RayPick的博客 2449

kubernetes源码剖析读后感(四)

注:结合书中的大概内容以及笔者自身的k8s经验 总结学到的一些新知识每一篇篇幅不会很长 书很棒强烈推荐买一本读 本次读书来自于《kubernetes源码剖析》 作者郑东旭 总结中包含部分书中内容 包含部分笔者读书学习到的知识点以及根据笔者结合书的一些总结 第四章 kubectl命令行交互 1.kubectl命令行交互参数详解 详情请见kubernetes专栏 附链接kubectl命令行参数 2.cobra命令行参数解析 3.创建资源对象的过程 ...

屈帅波的技术博客 763

K8S 源码探秘 之 kubeadm init 执行流程分析_kubeadm init解析

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

ccc6553584的博客 858

iptv-checker 完整教程:3分钟批量检测 IPTV 播放源可用性并导出可用频道列表

iptv-checker 是一款免费开源的 IPTV 播放源检测工具,批量检查 M3U/M3U8/TXT 播放列表中的频道是否可用,支持 Docker 部署与定时检测,并可一键导出可用频道列表。 ## 🔍 iptv-checker 解决什么问题:告别逐个试播 面对几百个频道,手动逐个点开看能否播放并不现实。iptv-checker 把这件重复劳动接管下来:批量验证每个播放源的连通性,标记失效

gitblog_00743的博客 466

K8s源码分析(一)-K8s调度框架及调度器初始化介绍

对K8s调度框架进行了介绍,还介绍了Cobra,并分析了K8s调度器的初始化代码

slipegg的博客 1838

从 getopt 到 argparse/commander/cobra:命令行参数解析的友好化演进

命令行参数解析是开发 CLI 工具的基础环节,几乎所有程序员都接触过经典的 getopt 函数。它能处理简单的短选项,却难以满足现代工具对帮助信息、类型校验、子命令等复杂需求。为解决这一痛点,各语言生态涌现出更友好的参数解析方案,如 Python 的 argparse、Node.js 的 commander、Go 的 cobra。这类库采用声明式配置,将解析逻辑与业务逻辑分离,自动生成帮助文本、完成类型转换和错误提示,让开发者专注于工具的核心功能。从系统脚本到云原生 CLI,参数解析的友好化直接影响开发效率

weixin_33937778的博客 371

k3sup源码深度解析:Go语言实现的轻量级Kubernetes部署利器

k3sup是一个用Go语言编写的轻量级工具,专门用于在60秒内通过SSH快速部署Kubernetes集群。这个强大的工具让Kubernetes集群的搭建变得前所未有的简单和高效。 ## 🚀 k3sup核心功能概述 k3sup的核心功能主要包括集群安装、节点加入、配置管理等模块。通过分析[main.go](https://link.gitcode.com/i/00b425fe4291c0d22

gitblog_07690的博客 624
上一篇: VSphere系列教程(二):ESXI 主机启用 Shell 及 SSH 服务
下一篇: Kubernetes 源码部分编译(快速编译其中一个模块) 单独编译 k8s 某个模块
shida_csdn
博客等级 码龄11年 429粉丝 320原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值