kubectl源码阅读—get命令

  

「技术干货」kubectl源码阅读—get命令

  作者/吴江法

  kubectl源码阅读—get命令

  问题:

  1.kubectl get命令输出的表头是如何动态变化的?

  2.kubectl get pod命令输出的pod的状态如:CrashLoopBackOff、Completed等是如何获取的?

  3.kubectl是如何转换别名的?如get po,get svc等。

  首先简单介绍cobra包的Command结构体,可以在该结构体的属性中找到关键的注释:

  该结构体中最重要的两个属性成员:

  1.子命令集合

  

「技术干货」kubectl源码阅读—get命令

  2.命令主要的执行逻辑

  

「技术干货」kubectl源码阅读—get命令

  kubectl是主命令,而get、describe、create等命令则是子命令。

  在构建kubectl命令时,会添加各子命令:

  

「技术干货」kubectl源码阅读—get命令

  执行主命令的入口:

  command.Execute() — >ExecuteC() 在该方法中获取命令行参数:

  

「技术干货」kubectl源码阅读—get命令

  再根据参数查询子命令:

  

「技术干货」kubectl源码阅读—get命令

  最终使用找到的子命令,执行子命令核心逻辑:

  

「技术干货」kubectl源码阅读—get命令

  在该核心逻辑中会执行Command的核心逻辑:

  

「技术干货」kubectl源码阅读—get命令

  抱着本次的问题,主要看子命令get的实现逻辑:

  在get命令的实现中,有一个很重要的结构体:

  

「技术干货」kubectl源码阅读—get命令

  该结构体负责接收和保存get子命令的参数。结合pflag包,将参数写入。

  

「技术干货」kubectl源码阅读—get命令

  

「技术干货」kubectl源码阅读—get命令

  子命令的核心逻辑:

  

「技术干货」kubectl源码阅读—get命令

  这里主要看o.Run方法:

  

「技术干货」kubectl源码阅读—get命令

  在该方法中,通过调试,可以发现,在执行下面这行代码时,kubectl调用接口拉取了数据:

  

「技术干货」kubectl源码阅读—get命令

  该方法代码如下:

  

「技术干货」kubectl源码阅读—get命令

  可以发现,这里使用了访问者模式。要明白它是如何调用接口的,得先弄清楚两个问题:

  1)r是如何构建出来的?

  2)r.visitor是什么?

  下面是r的构建代码,典型的构建者模式:

  

「技术干货」kubectl源码阅读—get命令

  回头看参数f,类型是cmdutil.Factory,是一个抽象工厂,是在cmd.go中构建传入的:

  

「技术干货」kubectl源码阅读—get命令

  实现类是:

  

「技术干货」kubectl源码阅读—get命令

  追踪找到NewBuilder():

  

「技术干货」kubectl源码阅读—get命令

  查看Do()方法:

  

「技术干货」kubectl源码阅读—get命令

  在该方法中,对r.visitor进行赋值,这里运用了装饰器模式,核心方法是b.visitorResult(),最终发现了一层层的装饰:

  底层是DecoratedVisitor—>ContinueOnErrorVisitor—>FlattenListVisitor—>EagerVisitorList—>Selector

  终于在Selector中找到了接口调用:

  

「技术干货」kubectl源码阅读—get命令

  调试拿到数据,找到了开篇时的问题1,2的答案:原来输出哪些表头是接口返回的,pod的状态也是接口返回的。

  表头:

  

「技术干货」kubectl源码阅读—get命令

  这里产生了疑问:莫非kubectl拉取数据时调用的不是普通的接口?

  继续调试,最终找到了答案:

  

「技术干货」kubectl源码阅读—get命令

  接口是一样的接口,但是加了特殊的header,as=Table。

  然后新的问题就是这个请求头是怎么加上去的?要回答这个问题,就得先追踪client的构建和传递:

  

「技术干货」kubectl源码阅读—get命令

  这个Client是哪来的?

  是调用了NewSelector方法获取的。

  

「技术干货」kubectl源码阅读—get命令

  接着找到调用者,以及client的源头:

  

「技术干货」kubectl源码阅读—get命令

  查看b.getClient方法:

  

「技术干货」kubectl源码阅读—get命令

  requestTransforms是不是很眼熟:

  

「技术干货」kubectl源码阅读—get命令

  最终找到:

  

「技术干货」kubectl源码阅读—get命令

  该方法会在发起http请求前被回调:

  

「技术干货」kubectl源码阅读—get命令

  以上,基本理顺了开篇的两个问题。

  通过调试,找到了解开第三个问题的入口:

  

「技术干货」kubectl源码阅读—get命令

  入口:b.resourceMappings(),查看该方法,找到方法的核心点:

  

「技术干货」kubectl源码阅读—get命令

  继续跟进:

  

「技术干货」kubectl源码阅读—get命令

  终于找到了抽象层,关键点在于restMapper是如何传入Builder对象中的。

  可以查看NewBuilder:

  

「技术干货」kubectl源码阅读—get命令

  关键点在于restClientGetter,该参数源头,继续回推:

  

「技术干货」kubectl源码阅读—get命令

  

「技术干货」kubectl源码阅读—get命令

  那么factoryImpl中的clientGetter是哪来的?

  

「技术干货」kubectl源码阅读—get命令

  

「技术干货」kubectl源码阅读—get命令

  可以发现最顶层的构建是:

  

「技术干货」kubectl源码阅读—get命令

  由于中间是一层层对clientGetter的代理,可以直接找到最底层的调用:

  

「技术干货」kubectl源码阅读—get命令

  找到对应的代理:

  

「技术干货」kubectl源码阅读—get命令

  对应的KindFor方法:

  

「技术干货」kubectl源码阅读—get命令

  以及最终的执行逻辑:

  

「技术干货」kubectl源码阅读—get命令

  

「技术干货」kubectl源码阅读—get命令

  最终调试:

  

「技术干货」kubectl源码阅读—get命令

  从数据中找到了答案:

  通过

  e.discoveryClient.ServerGroupsAndResources()能拉取到所有k8s资源的资源的别名。

  LStack产品简介

  面向行业应用开发商(ISV/SI)提供混合云/边缘云场景下云原生应用开发测试、交付、运维一站式服务,帮助企业采用云原生敏捷开发交付方法论,从而提高软件开发人员效率、减少运维成本,加快数字化转型,并最终实现业务创新。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值