使用插件扩展 kubectl
本指南演示了如何为 kubectl 安装和编写扩展。通过将核心 kubectl
命令视为与 Kubernetes 集群交互的基本构建块,集群管理员可以将插件视为利用这些构建块创建更复杂行为的一种方式。插件通过新的子命令扩展 kubectl
,从而实现 kubectl
主发行版中未包含的新功能和自定义功能。
开始之前
您需要安装一个有效的 kubectl
二进制文件。
安装 kubectl 插件
插件是一个独立的可执行文件,其名称以 kubectl-
开头。要安装插件,请将其可执行文件移动到 PATH
中的任何位置。
您还可以使用 Krew 发现和安装开源中提供的 kubectl 插件。Krew 是由 Kubernetes SIG CLI 社区维护的插件管理器。
警告
通过 Krew 插件索引 提供的 kubectl 插件未经安全审计。您应自行承担安装和运行第三方插件的风险,因为它们是在您的机器上运行的任意程序。发现插件
kubectl
提供了一个命令 kubectl plugin list
,该命令搜索您的 PATH
以查找有效的插件可执行文件。执行此命令会导致遍历 PATH
中的所有文件。任何可执行且以 kubectl-
开头的文件都将以它们在 PATH
中出现的顺序出现在此命令的输出中。对于以 kubectl-
开头但不可执行的任何文件,将包含警告。对于任何重叠彼此名称的有效插件文件,也将包含警告。
您可以使用 Krew 从社区策划的 插件索引 中发现和安装 kubectl
插件。
限制
目前无法创建覆盖现有 kubectl
命令的插件。例如,创建一个名为 kubectl-version
的插件将导致该插件永远不会被执行,因为现有的 kubectl version
命令将始终优先于它。由于此限制,也无法使用插件向现有 kubectl
命令添加新的子命令。例如,通过将插件命名为 kubectl-create-foo
来添加一个子命令 kubectl create foo
将导致该插件被忽略。
kubectl plugin list
会显示对尝试执行此操作的任何有效插件的警告。
编写 kubectl 插件
您可以在任何允许您编写命令行命令的编程语言或脚本中编写插件。
不需要插件安装或预加载。插件可执行文件从 kubectl
二进制文件继承的环境。插件根据其名称确定它希望实现的命令路径。例如,名为 kubectl-foo
的插件提供了命令 kubectl foo
。您必须将插件可执行文件安装到 PATH
中的某个位置。
示例插件
#!/bin/bash
# optional argument handling
if [[ "$1" == "version" ]]
then
echo "1.0.0"
exit 0
fi
# optional argument handling
if [[ "$1" == "config" ]]
then
echo "$KUBECONFIG"
exit 0
fi
echo "I am a plugin named kubectl-foo"
使用插件
要使用插件,请使插件可执行
sudo chmod +x ./kubectl-foo
并将其放置在 PATH
中的任何位置
sudo mv ./kubectl-foo /usr/local/bin
现在,您可以将插件作为 kubectl
命令调用
kubectl foo
I am a plugin named kubectl-foo
所有参数和标志将按原样传递给可执行文件
kubectl foo version
1.0.0
所有环境变量也按原样传递给可执行文件
export KUBECONFIG=~/.kube/config
kubectl foo config
/home/<user>/.kube/config
KUBECONFIG=/etc/kube/config kubectl foo config
/etc/kube/config
此外,传递给插件的第一个参数始终是调用它的位置的完整路径(在上面的示例中,$0
将等于 /usr/local/bin/kubectl-foo
)。
命名插件
如上面的示例所示,插件根据其文件名确定它将实现的命令路径。插件目标的命令路径中的每个子命令都用连字符 (-
) 分隔。例如,一个希望在用户调用 kubectl foo bar baz
命令时被调用的插件,其文件名将为 kubectl-foo-bar-baz
。
标志和参数处理
注意
插件机制不会为插件进程创建任何自定义的特定于插件的值或环境变量。
较旧的 kubectl 插件机制提供了诸如 KUBECTL_PLUGINS_CURRENT_NAMESPACE
之类的环境变量;那不再发生了。
kubectl 插件必须解析和验证传递给它们的所有参数。有关针对插件作者的 Go 库的详细信息,请参阅使用命令行运行时包。
以下是一些用户在提供其他标志和参数时调用插件的其他情况。这建立在上面场景中的 kubectl-foo-bar-baz
插件之上。
如果您运行 kubectl foo bar baz arg1 --flag=value arg2
,kubectl 的插件机制将首先尝试找到名称最长的插件,在本例中将是 kubectl-foo-bar-baz-arg1
。在找不到该插件后,kubectl 将最后一个以连字符分隔的值视为参数(在本例中为 arg1
),并尝试找到下一个最长的可能名称 kubectl-foo-bar-baz
。在找到具有此名称的插件后,kubectl 将调用该插件,并将插件名称后的所有参数和标志作为参数传递给插件进程。
示例
# create a plugin
echo -e '#!/bin/bash\n\necho "My first command-line argument was $1"' > kubectl-foo-bar-baz
sudo chmod +x ./kubectl-foo-bar-baz
# "install" your plugin by moving it to a directory in your $PATH
sudo mv ./kubectl-foo-bar-baz /usr/local/bin
# check that kubectl recognizes your plugin
kubectl plugin list
The following kubectl-compatible plugins are available:
/usr/local/bin/kubectl-foo-bar-baz
# test that calling your plugin via a "kubectl" command works
# even when additional arguments and flags are passed to your
# plugin executable by the user.
kubectl foo bar baz arg1 --meaningless-flag=true
My first command-line argument was arg1
如您所见,您的插件是根据用户指定的 kubectl
命令找到的,所有额外的参数和标志在找到插件可执行文件后按原样传递。
包含连字符和下划线的名称
虽然 kubectl
插件机制在插件文件名中使用连字符 (-
) 来分隔插件处理的子命令序列,但仍然可以通过在其文件名中使用下划线 (_
) 来创建在其命令行调用中包含连字符的插件命令。
示例
# create a plugin containing an underscore in its filename
echo -e '#!/bin/bash\n\necho "I am a plugin with a dash in my name"' > ./kubectl-foo_bar
sudo chmod +x ./kubectl-foo_bar
# move the plugin into your $PATH
sudo mv ./kubectl-foo_bar /usr/local/bin
# You can now invoke your plugin via kubectl:
kubectl foo-bar
I am a plugin with a dash in my name
请注意,在插件文件名中引入下划线不会阻止您使用诸如 kubectl foo_bar
之类的命令。上面的示例中的命令可以使用连字符 (-
) 或下划线 (_
) 调用
# You can invoke your custom command with a dash
kubectl foo-bar
I am a plugin with a dash in my name
# You can also invoke your custom command with an underscore
kubectl foo_bar
I am a plugin with a dash in my name
名称冲突和覆盖
在整个 PATH
中的不同位置可能存在多个具有相同文件名的插件。例如,给定具有以下值的 PATH
:PATH=/usr/local/bin/plugins:/usr/local/bin/moreplugins
,插件 kubectl-foo
的副本可能存在于 /usr/local/bin/plugins
和 /usr/local/bin/moreplugins
中,因此 kubectl plugin list
命令的输出为
PATH=/usr/local/bin/plugins:/usr/local/bin/moreplugins kubectl plugin list
The following kubectl-compatible plugins are available:
/usr/local/bin/plugins/kubectl-foo
/usr/local/bin/moreplugins/kubectl-foo
- warning: /usr/local/bin/moreplugins/kubectl-foo is overshadowed by a similarly named plugin: /usr/local/bin/plugins/kubectl-foo
error: one plugin warning was found
在上述场景中,/usr/local/bin/moreplugins/kubectl-foo
下面的警告告诉您该插件永远不会被执行。相反,始终会在您的 PATH
中首先出现 可执行文件 /usr/local/bin/plugins/kubectl-foo
,并且 kubectl
插件机制始终会先找到它并执行它。
解决此问题的办法是确保您希望与 kubectl
一起使用的插件的位置始终出现在 PATH
中的第一个位置。例如,如果您希望在每次调用 kubectl
命令 kubectl foo
时始终使用 /usr/local/bin/moreplugins/kubectl-foo
,请将 PATH
的值更改为 /usr/local/bin/moreplugins:/usr/local/bin/plugins
。
调用最长的可执行文件名
在插件文件名中还会发生另一种覆盖。给定用户 PATH
中存在的两个插件:kubectl-foo-bar
和 kubectl-foo-bar-baz
,kubectl
插件机制始终会为给定的用户命令选择最长的可能插件名称。以下是一些示例,进一步说明了这一点
# for a given kubectl command, the plugin with the longest possible filename will always be preferred
kubectl foo bar baz
Plugin kubectl-foo-bar-baz is executed
kubectl foo bar
Plugin kubectl-foo-bar is executed
kubectl foo bar baz buz
Plugin kubectl-foo-bar-baz is executed, with "buz" as its first argument
kubectl foo bar buz
Plugin kubectl-foo-bar is executed, with "buz" as its first argument
此设计选择确保可以跨多个文件实现插件子命令(如果需要),并且这些子命令可以嵌套在“父”插件命令下
ls ./plugin_command_tree
kubectl-parent
kubectl-parent-subcommand
kubectl-parent-subcommand-subsubcommand
检查插件警告
您可以使用前面提到的 kubectl plugin list
命令来确保您的插件对 kubectl
可见,并验证是否有任何警告阻止它被调用为 kubectl
命令。
kubectl plugin list
The following kubectl-compatible plugins are available:
test/fixtures/pkg/kubectl/plugins/kubectl-foo
/usr/local/bin/kubectl-foo
- warning: /usr/local/bin/kubectl-foo is overshadowed by a similarly named plugin: test/fixtures/pkg/kubectl/plugins/kubectl-foo
plugins/kubectl-invalid
- warning: plugins/kubectl-invalid identified as a kubectl plugin, but it is not executable
error: 2 plugin warnings were found
使用命令行运行时包
如果您正在为 kubectl 编写插件,并且正在使用 Go,那么您可以使用 cli-runtime 实用程序库。
这些库提供了解析或更新用户 kubeconfig 文件的帮助程序,用于对 API 服务器发出 REST 样式的请求,或绑定与配置和打印相关的标志。
有关 CLI 运行时存储库中提供的工具的使用示例,请参阅 示例 CLI 插件。
分发 kubectl 插件
如果您已经开发了供其他人使用的插件,您应该考虑如何打包、分发和向用户提供更新。
Krew
Krew 提供了一种跨平台的方式来打包和分发您的插件。这样,您就可以对所有目标平台(Linux、Windows、macOS 等)使用单一打包格式,并向用户提供更新。Krew 还维护一个 插件索引,以便其他人可以发现您的插件并安装它。
原生/特定于平台的包管理
或者,您可以使用传统的包管理器,例如 Linux 上的 apt
或 yum
、Windows 上的 Chocolatey 以及 macOS 上的 Homebrew。任何包管理器都可以,只要它可以将新的可执行文件放在用户的 PATH
中的某个位置。作为插件作者,如果您选择此选项,那么您还必须在每个版本中跨多个平台更新 kubectl 插件的分发包。
源代码
您可以发布源代码;例如,作为 Git 仓库。如果您选择此选项,想要使用该插件的人员必须获取代码,设置构建环境(如果需要编译),并部署插件。如果您还提供编译后的软件包,或使用 Krew,这将使安装更加容易。
下一步
- 查看 示例 CLI 插件存储库,了解用 Go 编写的插件的详细示例。如有任何疑问,请随时联系 SIG CLI 团队。
- 阅读有关 Krew 的信息,这是一个用于 kubectl 插件的包管理器。