编写 kubectl 插件
最近忙的晕头转向,博客停更了 1 个月,感觉对不起党、对不起人民、对不起
CCAV…不过在忙的时候操作 Kubernetes 集群要频繁的使用kubectl
命令,而在多个 NameSpace 下来回切换每次都得加个-n
简直让我想打人;索性翻了下kubectl
的插件机制,顺便写了一个快速切换 NameSpace 的小插件,以下记录一下插件编写过程
一、插件介绍
kubectl
命令从 v1.8.0
版本开始引入了 alpha feature 的插件机制;在此机制下我们可以对 kubectl
命令进行扩展,从而编写一些自己的插件集成进 kubectl
命令中;**kubectl
插件机制是与语言无关的,也就是说你可以用任何语言编写插件,可以是 bash
、python
脚本,也可以是 go
、java
等编译型语言;所以选择你熟悉的语言即可**,以下是一个用 go
编写的用于快速切换 NameSpace 的小插件,运行截图如下:
所谓: 开局一张图,功能全靠编 😂
当前插件代码放在 mritd/swns 这个项目下面
二、插件加载
kubectl
插件机制目前并不提供包管理器一样的功能,比如你想执行 kuebctl plugin install xxx
这种操作目前还没有实现(个人感觉差个规范);所以一旦我们编写或者下载一个插件后,我们只有正确放在特定目录才会生效;
目前插件根据文档描述只有两部分内容: plugin.yaml
和其依赖的二进制/脚本等可执行文件;根据文档说明,kubectl
会尝试在如下位置查找并加载插件,所以我们只需要将 plugin.yaml
和相关二进制放在在对应位置即可:
${KUBECTL_PLUGINS_PATH}
: 如果这个环境变量定义了,那么kubectl
只会从这里查找;注意: 这个变量可以是多个目录,类似 PATH 变量一样,做好分割即可${XDG_DATA_DIRS}/kubectl/plugins
: 关于这个变量具体请看 XDG System Directory Structure,我了解也不多;如果这个变量没定义则默认为/usr/local/share:/usr/share
~/.kube/plugins
: 这个没啥可说的,我推荐还是将插件放在这个位置比较友好一点
所以最终插件目录结构类似这样:
1 |
|
三、Plugin.yaml
plugin.yaml
这个文件实际上才是插件的核心,在这个文件里声明了插件如何使用、调用的二进制/脚本等重要配置;一个插件可以没有任何脚本/二进制可执行文件,但至少应当有一个 plugin.yaml
描述文件;目前 plugin.yaml
的结构如下:
1 |
|
四、插件环境变量
在编写插件时,有时插件运行时需要获取到一些参数,比如 kubectl
执行时的全局 flag 等,为了方便插件开发者,kuebctl
的插件机制提供一些预置的环境变量方便我们读取;即如果你用 bash
写插件,那么这些变量你只需要 ${xxxx}
即可拿到,然后做一些你想做的事情;这些变量目前支持如下:
KUBECTL_PLUGINS_CALLER
:kubectl
二进制文件所在位置;作为插件编写者,我们无需关系 api server 是否能联通,因为配置是否正确应当由使用者决定;在需要时我们只需要直接调用kubectl
即可;比如在bash
脚本中执行get pod
等KUBECTL_PLUGINS_CURRENT_NAMESPACE
: 当前kuebctl
命令所对应的 NameSpace,插件机制确保了该值一定正确;即这是经过解析了--namespace
选项或者kubeconfig
配置后的最终结果;作为插件编写者,我们无需关心处理过程;想详细了解的的可以去看源码,以及Cobra
库(Kubernetes 用这个库解析命令行参数和配置)KUBECTL_PLUGINS_DESCRIPTOR_*
: 插件自己本身位于plugin.yaml
中的描述信息,比如KUBECTL_PLUGINS_DESCRIPTOR_NAME
输出plugin.yaml
下的name
属性;一般可以用作插件输出自己的帮助文档等KUBECTL_PLUGINS_GLOBAL_FLAG_*
: 获取kubectl
所有全局 flag 值的变量,比如KUBECTL_PLUGINS_GLOBAL_FLAG_NAMESPACE
能拿到--namespace
选项的值KUBECTL_PLUGINS_LOCAL_FLAG_*
: 同上面类似,只不过这个是获取插件自己本身 flag 的值,个人认为在脚本语言中,比如bash
等处理选项不怎么好用时,可以考虑直接从变量拿
以上变量我并未都测试,具体以测试为准,删库跑路等情况本人概不负责
五、写一个切换 NameSpace 的插件
前面墨迹一大堆只是为了描述清楚 要写一个插件应该怎么干 的问题,下面开始 这么干
5.1、编写配置
上面已经介绍好了 plugin.yaml
怎么写,那么根据我自己的需求,我写的这个切换 NameSpace 插件的名字暂且叫做 swns
;我希望 swns
执行后接受一个 NameSpace 的字符串,然后调用 kuebctl config
去设置当前默认的 NameSpace,这样在后续命令中我就不用再一直加个 -n xxx
参数了;同时我希望使用更方便点,当执行 swns
命令时,如果不提供 NameSpace 的字符串,那我就弹出下拉列表供用户选择;综上需求自己想明白后,就写一个 plugin.yaml
,如下:
1 |
|
5.2、编写插件
上面 plugin.yaml
已经定义好了,那么接下来就简单了,撸代码实现了就好;代码如下:
1 |
|
最后编译后放到上面所说的插件加载目录即可
到此,**”全局一张图,功能全靠编”** 图上面也有了,编的的也差不多 😂