kubectl使用及源码阅读

news2025/2/26 11:36:39

目录

  • 概述
  • 实践
    • 样例
      • yaml 中的必须字段
    • kubectl 代码原理
      • kubectl 命令行设置pprof 抓取火焰图
        • kubectl 中的 cobra
    • 七大分组命令
      • kubectl create
      • createCmd中的builder模式
      • createCmd中的visitor访问者模式
      • 外层VisitorFunc分析
  • 结束

概述

k8s 版本 v1.24.16

kubectl的职责

  • 1.主要的工作是处理用户提交的东西(包括,命令行参数,yaml文件等)
  • 2.将用户提交的这些东西组织成一个数据结构体
  • 3.再将其发送给 api server

实践

文章名链接
linux k8s 源码编译及单集群测试地址
k8s源码debug地址

样例

cat test/fixtures/doc-yaml/user-guide/pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
字段名含义
kindPod
metadata.name
spec.containers.name
spec.containers.imageimage名称:版本

对象规约(Spec) 与状态 (Status)

  • 几乎每个 Kubernetes 对象包含两个嵌套的对象字段,它们负责管理对象的配置:对象 spec (规约) 和对象 status (状态)
  • 对于具有 spec 的对象,必须在创建对象时设置具体内容,描述你希望对象所具有的特征:期望状态 (Desired State)

yaml 中的必须字段

  • 在想要创建的 Kubernetes 对象对应的 yaml 文件中,需要配置如下的字段:
    • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
    • kind - 想要创建的对象的类别
    • metadata - 帮助唯一标识对象的一些数据,包括一个 name 字符串、UID和可选的 namespace
[root@test kubernetes]# ./cluster/kubectl.sh get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          89s
字段名含义
NAMEnginx就是对应yaml中metadata.name
READY就绪个数
STATUS当前的状态,RUNNING表示运行中
RESTARTS重启的次数,代表没有重启过
AGE运行的时长

kubectl 代码原理

  • 1.从命令行和 yaml 文件中获取信息
  • 2.通过 Builder 模式并将其转成一系列的资源
  • 3.最后用 Visitor 模式来迭代处理这些 Resources

源码位置
在这里插入图片描述

kubectl 命令行设置pprof 抓取火焰图

kubectl 中的 cobra
  • 底层函数 NewKubectlCommand 解析
  • 在 PersistentPreRunE 设置 prrof 采集相关指令
  • 在 PersistentPostRunE 设置了 pprof 统计结果落盘
  • 执行采集 pprof cpu 的 kubelet 命令
kubectl.go --> command := cmd.NewDefaultKubectlCommand()
	cmd.go --> return NewDefaultKubectlCommandWithArgs(KubectlOptions{ -->cmd := NewKubectlCommand(o)
# cpu.pprof 文件在当前命令执行目录下
kubectl get node --profile=cpu --profile-output=cpu.pprof
# ll
# 使用 go 工具将 pprof 转换成 svg  火焰图
go tool pprof -svg cpu.pprof > kubectl_get_node_cpu.svg
# 下载下来,在浏览器打开

七大分组命令

kubectl.go --> command := cmd.NewDefaultKubectlCommand()
	cmd.go --> var defaultConfigFlags = genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0) --> f := cmdutil.NewFactory(matchVersionKubeConfigFlags) --> 	proxyCmd := proxy.NewCmdProxy(f, o.IOStreams)
	proxyCmd.PreRun = func(cmd *cobra.Command, args []string) {
		kubeConfigFlags.WrapConfigFn = nil
	}
groups := templates.CommandGroups{
	{
		Message: "Basic Commands (Beginner):",
		Commands: []*cobra.Command{
			create.NewCmdCreate(f, o.IOStreams),
			expose.NewCmdExposeService(f, o.IOStreams),
			run.NewCmdRun(f, o.IOStreams),
			set.NewCmdSet(f, o.IOStreams),
		},
	},
	{
		Message: "Basic Commands (Intermediate):",
		Commands: []*cobra.Command{
			explain.NewCmdExplain("kubectl", f, o.IOStreams),
			getCmd,
			edit.NewCmdEdit(f, o.IOStreams),
			delete.NewCmdDelete(f, o.IOStreams),
		},
	},
	{
		Message: "Deploy Commands:",
		Commands: []*cobra.Command{
			rollout.NewCmdRollout(f, o.IOStreams),
			scale.NewCmdScale(f, o.IOStreams),
			autoscale.NewCmdAutoscale(f, o.IOStreams),
		},
	},
	{
		Message: "Cluster Management Commands:",
		Commands: []*cobra.Command{
			certificates.NewCmdCertificate(f, o.IOStreams),
			clusterinfo.NewCmdClusterInfo(f, o.IOStreams),
			top.NewCmdTop(f, o.IOStreams),
			drain.NewCmdCordon(f, o.IOStreams),
			drain.NewCmdUncordon(f, o.IOStreams),
			drain.NewCmdDrain(f, o.IOStreams),
			taint.NewCmdTaint(f, o.IOStreams),
		},
	},
	{
		Message: "Troubleshooting and Debugging Commands:",
		Commands: []*cobra.Command{
			describe.NewCmdDescribe("kubectl", f, o.IOStreams),
			logs.NewCmdLogs(f, o.IOStreams),
			attach.NewCmdAttach(f, o.IOStreams),
			cmdexec.NewCmdExec(f, o.IOStreams),
			portforward.NewCmdPortForward(f, o.IOStreams),
			proxyCmd,
			cp.NewCmdCp(f, o.IOStreams),
			auth.NewCmdAuth(f, o.IOStreams),
			debug.NewCmdDebug(f, o.IOStreams),
		},
	},
	{
		Message: "Advanced Commands:",
		Commands: []*cobra.Command{
			diff.NewCmdDiff(f, o.IOStreams),
			apply.NewCmdApply("kubectl", f, o.IOStreams),
			patch.NewCmdPatch(f, o.IOStreams),
			replace.NewCmdReplace(f, o.IOStreams),
			wait.NewCmdWait(f, o.IOStreams),
			kustomize.NewCmdKustomize(o.IOStreams),
		},
	},
	{
		Message: "Settings Commands:",
		Commands: []*cobra.Command{
			label.NewCmdLabel(f, o.IOStreams),
			annotate.NewCmdAnnotate("kubectl", f, o.IOStreams),
			completion.NewCmdCompletion(o.IOStreams.Out, ""),
		},
	},
}

kubectl create

// 进入口
create.NewCmdCreate(f, o.IOStreams)

// 核心的cmd.Run函数
// 校验文件参数
if cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames, o.FilenameOptions.Kustomize) {
	ioStreams.ErrOut.Write([]byte("Error: must specify one of -f and -k\n\n"))
	defaultRunFunc := cmdutil.DefaultSubCommandRun(ioStreams.ErrOut)
	defaultRunFunc(cmd, args)
	return
}

// 完善并填充所需字段 
cmdutil.CheckErr(o.Complete(f, cmd))
// 校验参数
cmdutil.CheckErr(o.ValidateArgs(cmd, args))
// 核心的RunCreate
// 发送请求与 api server 通信
cmdutil.CheckErr(o.RunCreate(f, cmd))

createCmd中的builder模式

createCmd中的builder建造者设计模式

// 快速定位代码
cmdutil.CheckErr(o.RunCreate(f, cmd)) -->
r := f.NewBuilder().
		Unstructured().
		Schema(schema).
		ContinueOnError().
		NamespaceParam(cmdNamespace).DefaultNamespace().
		FilenameParam(enforceNamespace, &o.FilenameOptions).
		LabelSelectorParam(o.Selector).
		Flatten().
		Do()

在这里插入图片描述

createCmd中的visitor访问者模式

  • 访问都模式(Visitor Pattern) 是一种将数据结构与数据操作分离的设计模式
  • 指封装一些作用于某种数据结构中的各元素的操作
  • 可以在不改变数据结构的前提下定义作用于这些元素的新的操作
  • 属于行为型设计模式

使用场景:

  • 数据结构稳定,作用于数据结构的操作经常变化的场景
  • 需要数据结构与数据操作分享的场景
  • 需要对不同数据类型(元素)进行操作,而不使用分支判断具体类型的场景
// 快速定位代码
cmdutil.CheckErr(o.RunCreate(f, cmd)) --> err = r.Visit(func(info *resource.Info, err error) error {

// 注意 Visit 是由 Builder 中 FilenameParam 构建的
r := f.NewBuilder().
		...
		// 构建 Visit
		FilenameParam(enforceNamespace, &o.FilenameOptions).
		...
		// 创建 Visit
		Do()
// 定位
FilenameParam --> b.Path(recursive, matches...) --> visitors, err := ExpandPathsToFileVisitors(b.mapper, p, recursive, FileExtensions, b.schema) -->
		visitor := &FileVisitor{
			Path:          path,
			StreamVisitor: NewStreamVisitor(nil, mapper, path, schema),
		}

FilenameParam --> b.Path(recursive, matches…) 位置
在这里插入图片描述

// NewStreamVisitor is a helper function that is useful when we want to change the fields of the struct but keep calls the same.
func NewStreamVisitor(r io.Reader, mapper *mapper, source string, schema ContentValidator) *StreamVisitor {
	return &StreamVisitor{
		Reader: r,
		mapper: mapper,
		Source: source,
		Schema: schema,
	}
}

// 解析 yaml 或者 json 配置
// Visit implements Visitor over a stream. StreamVisitor is able to distinct multiple resources in one stream.
func (v *StreamVisitor) Visit(fn VisitorFunc) error {
	d := yaml.NewYAMLOrJSONDecoder(v.Reader, 4096)
	for {
		ext := runtime.RawExtension{}
		if err := d.Decode(&ext); err != nil {
			if err == io.EOF {
				return nil
			}
			return fmt.Errorf("error parsing %s: %v", v.Source, err)
		}
		// TODO: This needs to be able to handle object in other encodings and schemas.
		ext.Raw = bytes.TrimSpace(ext.Raw)
		if len(ext.Raw) == 0 || bytes.Equal(ext.Raw, []byte("null")) {
			continue
		}
		if err := ValidateSchema(ext.Raw, v.Schema); err != nil {
			return fmt.Errorf("error validating %q: %v", v.Source, err)
		}
		info, err := v.infoForData(ext.Raw, v.Source)
		if err != nil {
			if fnErr := fn(info, err); fnErr != nil {
				return fnErr
			}
			continue
		}
		if err := fn(info, nil); err != nil {
			return err
		}
	}
}
// 上面方法中,重点如下代码
info, err := v.infoForData(ext.Raw, v.Source)

// obj 代表 k8s的对象
// gvk 代表 Group/Version/Kind 的缩写
obj, gvk, err := m.decoder.Decode(data, nil, nil)

外层VisitorFunc分析

  • 如查出错即返回错误
  • DryRunStrategy 代表试运行策略
    • 默认为 None 代表不试运行
    • client 代表客户端试运行,不发送请求至 server
    • server 点服务端试运行,发送请求,但是如果会改变状态的话就不做
err = r.Visit(func(info *resource.Info, err error) error { --> if o.DryRunStrategy != cmdutil.DryRunClient {  --> Create(info.Namespace, true, info.Object)(最终创建资源)

结束

kubectl使用及进阶 至此结束。

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

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

相关文章

深入理解网络通信基本原理和tcp/ip协议

深入理解网络通信基本原理和tcp/ip协议 一、计算机网络体系1,计算机网络体系结构2,网络中数据传输2.1,浏览器中输入一个url的执行流程2.2,数据在网络中是的传输流程 3,三次握手和四次挥手3.1,三次握手3.1.1…

代理IP安全问题:在国外使用代理IP是否安全

目录 前言 一、国外使用代理IP的安全风险 1. 数据泄露 2. 恶意软件 3. 网络攻击 4. 法律风险 二、保护国外使用代理IP的安全方法 1. 选择可信的代理服务器 2. 使用加密协议 3. 定期更新系统和软件 4. 注意网络安全意识 三、案例分析 总结 前言 在互联网时代&…

xilinix 的硬件资源分布

从官方手册UG475中可以看出,下图中的V690T系列的i芯片,其具有的bank数量,已经上下半区的bufg对应的bank关系,实际在开发过程中,可能面临局部资源集中度过高,导致bufg的数量不够的情况,bufg的位置…

Docker数据集与自定义镜像:构建高效容器的关键要素

目录 博客前言 一.数据卷 1.数据卷介绍 2.实战 宿主机和容器共享目录 容器和容器之间共享目录 二.自定义镜像 1.自定义镜像介绍 2.实战 2.1自定义centos,具备vim及ifconfig作用 构建镜像 通过镜像运行一个容器进行测试 2.2自定义tomact(文件为…

人工智能_Centos7.9中CPU安装ChatGLM3-6B大模型_安装使用_010---人工智能工作笔记0105

从一个空的虚拟机开始安装: https://www.modelscope.cn/models/ZhipuAI/chatglm3-6b/files 可以看到这里有很多的数据文件,那么这里 这里点击模型文件就可以下载,这个就是chatglm3-6B的文件,需要点击每个文件,然后点击右边的下载,把文件都下载下来

Python3中真真假假True、False、None等含义详解

在Python中,不仅仅和类C一样的真假类似,比如1代表真,0代表假。Python中的真假有着更加广阔的含义范围,Python会把所有的空数据结构视为假,比如 [] (空列表)、 {} (空集合)、 (空字符…

初探2b blender

总结 按照youtube 教程 做了个雏形 心得 从正面, 侧面 视图整体上调整外轮廓流线型趋向, 比如正面看这个发型像个鸡蛋的外轮廓头发重要的是丝滑, 流畅 集束 层次 交错

Flutter开发进阶之Flutter Web加载速度优化

Flutter开发进阶之Flutter Web加载速度优化 通常使用Flutter开发的web加载速度会比较慢,原因是Flutter web需要加载的资源处于国外,以下是据此所做的相应优化。 一、FlutterWeb打包 flutter build web --web-renderer canvaskit使用新命令打包 flut…

面试经典150题——插入区间

"The future belongs to those who believe in the beauty of their dreams." - Eleanor Roosevelt 1. 题目描述 2. 题目分析与解析 2.1 思路一 解决这个问题的思路是基于区间排序和合并的经典算法。这个问题的关键在于如何处理新区间与现有区间的关系&#xff0c…

【C++入门】C++关键字 | 命名空间 | C++的输入输出

目录 0.C与C 1.C的关键字 2.命名空间 2.1域 2.2C中命名冲突问题 2.3命名空间定义 2.4命名空间使用 2.5命令空间的展开&头文件的展开 3.C的输入&输出 3.1cout&cin 3.1<<流插入运算符 3.2>>流提取运算符 0.C与C C是在C的基础之上&#xff…

九州金榜|家庭教育中孩子厌学的原因有哪些?

孩子的成长往往会受到家庭教育&#xff0c;社会环境&#xff0c;学校教育等因素影响&#xff0c;孩子厌学受家庭教育影响是一个重要因素&#xff0c;都是哪些因素会让孩子产生厌学情绪呢&#xff1f;下面九州金榜家庭教育分析一下因为家庭教育因素而让孩子产生厌学的原因&#…

Redis学习------实战篇----2024/02/28

1.集群的session共享问题 2.基于Redis实现共享session登录 //4.保存验证码到redisstringRedisTemplate.opsForValue().set(LOGIN_CODE_KEYphone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);RedisTemplate RedisTemplate使用的是JdkSerializationRedisSerializer存入数据&#xff…

不看后悔的2024年腾讯云服务器购买优惠活动汇总

腾讯云服务器多少钱一年&#xff1f;62元一年起&#xff0c;2核2G3M配置&#xff0c;腾讯云2核4G5M轻量应用服务器218元一年、756元3年&#xff0c;4核16G12M服务器32元1个月、312元一年&#xff0c;8核32G22M服务器115元1个月、345元3个月&#xff0c;腾讯云服务器网txyfwq.co…

二叉树(C/C++)

本篇将较为详细的介绍二叉树的相关知识&#xff0c;以及二叉树的实现。对于二叉树的相关知识&#xff0c;本篇介绍了其概念、特殊的二叉树、性质还有存储结构。 接着对于实现二叉树的每个函数都有其思路讲解&#xff0c;主要的函数分为&#xff1a;遍历&#xff1a;前中后序遍历…

redis-Redis主从,哨兵和集群模式

一&#xff0c;Redis的主从复制 ​ 主机数据更新后根据配置和策略&#xff0c; 自动同步到备机的master/slaver机制&#xff0c;Master以写为主&#xff0c;Slave以读为主。这样做的好处是读写分离&#xff0c;性能扩展&#xff0c;容灾快速恢复。 1.1 环境搭建 如果你的redi…

【HDFS】Decommision(退役) EC数据节点剩最后几个块卡住的问题

一、背景 近期操作退役EC集群的节点。在退役的过程中,遇到了一些问题。特此总结一下。 本文描述的问题现象是: 每一批次退役10个节点,完全退役成功后开始操作下一批。 但是,中间有一批次有2台节点的Under Replicated Blocks一直是1,不往下降。 处于Decommissioning状态卡…

iOS App冷启动优化:Before Main阶段

iOS应用冷启动时&#xff0c;在 UIApplicationMain(argc, argv, nil, appDelegateClassName)方法执行前&#xff0c;主要经历以下阶段&#xff1a; 1. 执行exec&#xff08;&#xff09;启动应用程序进程 2. 加载可执行文件&#xff0c;即将应用程序的Mach-O文件加载到内存…

跟着野火学FreeRTOS:第二段(堆存储管理)

F r e e R T O S FreeRTOS FreeRTOS从版本 V 9.0.0 V9.0.0 V9.0.0开始&#xff0c;内核对象所用的存储空间可以在编译时静态分配或在运行时动态分配&#xff0c;早期的版本不同时支持静态分配和动态分配&#xff0c;这里讲到的堆存储管理是和动态分配相关的。从版本 V 9.0.0 V9…

跨区域复制建筑UI输入框脚本迷你世界

--复制区域文件 --设置坐标起点&#xff0c;终点 --创建区域 --获取坐标id,data --星空露珠工作室制作 local pos1{x-16,y7,z28} local pos2{x28,y44,z-9} local block{num0} local str{} local str0{} local num0 local count0 local ui6 --几个输入框 local romath.random(…

【LeetCode:108. 将有序数组转换为二叉搜索树 + 二叉树+递归】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…