使用插件扩展 kubectl

通过创建和安装 kubectl 插件来扩展 kubectl。

本指南演示如何安装和编写 kubectl 的扩展。将核心的 kubectl 命令视为与 Kubernetes 集群交互的基本构建块,集群管理员可以将插件视为利用这些构建块来创建更复杂行为的一种方式。插件通过新的子命令扩展了 kubectl,从而允许添加 kubectl 主发行版中未包含的新功能和自定义功能。

开始之前

你需要安装一个可工作的 kubectl 二进制文件。

安装 kubectl 插件

插件是名称以 kubectl- 开头的独立可执行文件。要安装插件,将其可执行文件移动到你的 PATH 环境变量的任何位置。

你还可以使用 Krew 发现和安装开源中提供的 kubectl 插件。Krew 是由 Kubernetes SIG CLI 社区维护的插件管理器。

发现插件

kubectl 提供了一个命令 kubectl plugin list,该命令会搜索你的 PATH 环境变量以查找有效的插件可执行文件。执行此命令会遍历你 PATH 中的所有文件。任何可执行且名称以 kubectl- 开头的文件,都会 按照它们在 PATH 中出现的顺序 显示在该命令的输出中。对于任何名称以 kubectl- 开头但 不可执行 的文件,将包含一个警告。对于任何名称相互重叠的有效插件文件,也将包含一个警告。

你可以使用 Krew 从社区维护的 插件索引中发现并安装 kubectl 插件。

Create 插件

通过在 PATH 中提供一个名为 kubectl-create-something 的二进制文件,kubectl 允许插件添加自定义的形状为 kubectl create something 的 create 命令。

限制

目前无法创建覆盖现有 kubectl 命令或扩展除 create 以外的其他命令的插件。例如,创建名为 kubectl-version 的插件将导致该插件永远不会被执行,因为现有的 kubectl version 命令始终优先于它。由于此限制,也 无法 使用插件向现有 kubectl 命令添加新的子命令。例如,通过将插件命名为 kubectl-attach-vm 来添加子命令 kubectl attach vm 将导致该插件被忽略。

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 插件必须解析和验证传递给它们的所有参数。有关面向插件作者的 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-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 下的警告告诉你,此插件永远不会被执行。相反,kubectl 插件机制将始终首先找到并执行在 PATH 中首先出现的那个可执行文件,即 /usr/local/bin/plugins/kubectl-foo

解决此问题的一种方法是确保你希望与 kubectl 一起使用的插件的位置始终位于你的 PATH 中的首位。例如,如果你希望在调用 kubectl foo 命令时始终使用 /usr/local/bin/moreplugins/kubectl-foo,请将 PATH 的值更改为 /usr/local/bin/moreplugins:/usr/local/bin/plugins

调用名称最长的可执行文件

插件文件名还可能出现另一种遮蔽情况。给定用户 PATH 中存在的两个插件:kubectl-foo-barkubectl-foo-bar-bazkubectl 插件机制对于给定的用户命令将始终选择名称最长的可能插件。下面的一些示例对此做了进一步阐述:

# 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

使用命令行运行时包

如果你正在使用 Go 语言编写 kubectl 插件,可以使用 cli-runtime 工具库。

这些库提供了帮助解析或更新用户的 kubeconfig 文件、向 API Server 发出 REST 风格请求或绑定与配置和打印相关的标志的功能。

请查看 Sample CLI Plugin 示例,了解 CLI Runtime 仓库中提供的工具的用法。

分发 kubectl 插件

如果你开发了一个供他人使用的插件,你应该考虑如何打包、分发它并向用户提供更新。

Krew

Krew 提供了一种跨平台的方式来打包和分发你的插件。通过这种方式,你可以使用单一的打包格式来支持所有目标平台(Linux、Windows、macOS 等),并向用户提供更新。Krew 还维护着一个 插件索引,以便其他人可以发现和安装你的插件。

原生 / 平台特定的包管理

或者,你可以使用传统的包管理器,例如 Linux 上的 aptyum,Windows 上的 Chocolatey,以及 macOS 上的 Homebrew。任何可以将新的可执行文件放置到用户的 PATH 中某个位置的包管理器都可以。作为插件作者,如果选择此选项,你还需要承担为每个版本更新多个平台上 kubectl 插件分发包的负担。

源代码

你可以发布源代码;例如,作为一个 Git 仓库。如果选择此选项,想要使用该插件的人必须获取代码,设置构建环境(如果需要编译),然后部署该插件。如果你同时提供编译好的包,或者使用 Krew,这将使安装更容易。

下一步

  • 查看 Sample CLI Plugin 仓库,获取一个使用 Go 语言编写的插件的详细示例。如有任何问题,请随时联系 SIG CLI 团队
  • 阅读关于 Krew 的信息,它是 kubectl 插件的包管理器。
最后修改于 2024 年 10 月 10 日太平洋标准时间 7:50:kubectl: document create plugins (#48265) (2e1763d1d8)