diff --git a/content/zh/docs/tasks/extend-kubectl/kubectl-plugins.md b/content/zh/docs/tasks/extend-kubectl/kubectl-plugins.md index c22481b71c..bba139ae1d 100644 --- a/content/zh/docs/tasks/extend-kubectl/kubectl-plugins.md +++ b/content/zh/docs/tasks/extend-kubectl/kubectl-plugins.md @@ -1,9 +1,7 @@ --- title: 用插件扩展 kubectl -reviewers: -- juanvallejo -- soltysh -description: 使用 kubectl 插件,你可以通过添加新的子命令来扩展 kubectl 命令的功能。 +description: 通过创建和安装 kubectl 插件扩展 kubectl +content_type: task --- -{{< feature-state state="stable" >}} - -本指南演示了如何为 [kubectl](/docs/reference/kubectl/kubectl/) 安装和编写扩展。 -通过将核心 `kubectl` 命令看作与 Kubernetes 集群交互的基本构建块,集群管理员可以将插件视为一种利用这些构建块创建更复杂行为的方法。 +本指南演示了如何为 [kubectl](/zh/docs/reference/kubectl/kubectl/) 安装和编写扩展。 +通过将核心 `kubectl` 命令看作与 Kubernetes 集群交互的基本构建块, +集群管理员可以将插件视为一种利用这些构建块创建更复杂行为的方法。 插件用新的子命令扩展了 `kubectl`,允许新的和自定义的特性不包括在 `kubectl` 的主要发行版中。 - - ## {{% heading "prerequisites" %}} - -您需要安装一个工作的二进制 `kubectl`。 - -{{< note >}} - - -插件在 v1.8.0 版本中正式作为 alpha 特性引入。它们已经在 v1.12.0 版本中工作,以支持更广泛的用例。因此,虽然在以前的版本中已经提供了部分插件特性,但如果您遵循这些文档,建议使用 1.12.0 或更高版本的 `kubectl`。 - -{{< /note >}} - - +你需要安装一个可用的 `kubectl` 可执行文件。 -## 安装 kubectl 插件 - - -插件只不过是一个独立的可执行文件,名称以 `kubectl-` 开头。要安装插件,只需将此可执行文件移动到路径上的任何位置。 +## 安装 kubectl 插件 -{{< note >}} +插件只不过是一个独立的可执行文件,名称以 `kubectl-` 开头。 +要安装插件,只需将此可执行文件移动到 PATH 中的任何位置。 -Kubernetes 不提供包管理器或任何类似于安装或更新插件的东西。你有责任确保插件可执行文件的文件名以 `kubectl-` 开头,并将它们放在你路径的某个位置。 -{{< /note >}} +你也可以使用 [Krew](https://krew.dev/) 来发现和安装开源的 kubectl 插件。 +Krew 是一个由 Kubernetes SIG CLI 社区维护的插件管理器。 + + +{{< caution >}} +Krew [插件索引](https://index.krew.dev/)所维护的 kubectl 插件并未经过安全性审查。 +你要了解安装和运行第三方插件的安全风险,因为它们本质上时是一些在你的机器上 +运行的程序。 +{{< /caution >}} -### 发现插件 - - +### 发现插件 + `kubectl` 提供一个命令 `kubectl plugin list`,用于搜索路径查找有效的插件可执行文件。 执行此命令将遍历路径中的所有文件。任何以 `kubectl-` 开头的可执行文件都将在这个命令的输出中以它们在路径中出现的顺序显示。 任何以 `kubectl-` 开头的文件如果`不可执行`,都将包含一个警告。 @@ -88,52 +79,58 @@ A warning will also be included for any valid plugin files that overlap each oth +It is currently not possible to create plugins that overwrite existing `kubectl` commands. For example, creating a plugin `kubectl-version` will cause that plugin to never be executed, as the existing `kubectl version` command will always take precedence over it. Due to this limitation, it is also *not* possible to use plugins to add new subcommands to existing `kubectl` commands. For example, adding a subcommand `kubectl create foo` by naming your plugin `kubectl-create-foo` will cause that plugin to be ignored. + +`kubectl plugin list` shows warnings for any valid plugins that attempt to do this. +--> #### 限制 - -目前无法创建覆盖现有 `kubectl` 命令的插件,例如,创建一个插件 `kubectl-version` 将导致该插件永远不会被执行,因为现有的 `kubectl-version` 命令总是优先于它执行。 -由于这个限制,也不可能使用插件将新的子命令添加到现有的 `kubectl` 命令中。例如,通过将插件命名为 `kubectl-create-foo` 来添加子命令 `kubectl create foo` 将导致该插件被忽略。对于任何试图这样做的有效插件 `kubectl plugin list` 的输出中将显示警告。 +目前无法创建覆盖现有 `kubectl` 命令的插件。 +例如,创建一个插件 `kubectl-version` 将导致该插件永远不会被执行, +因为现有的 `kubectl-version` 命令总是优先于它执行。 +由于这个限制,也不可能使用插件将新的子命令添加到现有的 `kubectl` 命令中。 +例如,通过将插件命名为 `kubectl-create-foo` 来添加子命令 `kubectl create foo` 将导致该插件被忽略。 + +对于任何试图这样做的有效插件 `kubectl plugin list` 的输出中将显示警告。 -## 编写 kubectl 插件 - - -你可以用任何编程语言或脚本编写插件,允许您编写命令行命令。 +## 编写 kubectl 插件 + +你可以用任何编程语言或脚本编写插件,允许你编写命令行命令。 -不需要安装插件或预加载,插件可执行程序从 `kubectl` 二进制文件接收继承的环境,插件根据其名称确定它希望实现的命令路径。 -例如,一个插件想要提供一个新的命令 `kubectl foo`,它将被简单地命名为 `kubectl-foo`,并且位于用户路径的某个位置。 +不需要安装插件或预加载,插件可执行程序从 `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 @@ -146,7 +143,6 @@ echo "I am a plugin named kubectl-foo" - ### 使用插件 -并将它放在你的路径中的任何地方: +并将它放在你的 PATH 中的任何地方: ``` sudo mv ./kubectl-foo /usr/local/bin @@ -218,72 +214,86 @@ Additionally, the first argument that is passed to a plugin will always be the f -### 命名插件 - - +### 命名插件 + 如上面的例子所示,插件根据文件名确定要实现的命令路径,插件所针对的命令路径中的每个子命令都由破折号(`-`)分隔。 例如,当用户调用命令 `kubectl foo bar baz` 时,希望调用该命令的插件的文件名为 `kubectl-foo-bar-baz`。 - #### 参数和标记处理 -{{< note >}} -与以前版本的 `kubectl` 不同,插件机制不会为插件进程创建任何定制的、特定于插件的值或环境变量,这意味着像 `KUBECTL_PLUGINS_CURRENT_NAMESPACE` 这样的环境变量不再提供给插件。 -插件必须解析用户传递给它们的所有参数,并将参数验证作为它们自己实现的一部分处理。对于用 Go 编写的插件,在 [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) 下提供了一组实用程序来帮助实现这一点。 +The plugin mechanism doest _not_ create any custom, plugin-specific values or environment variables to a plugin process. +An older kubectl plugin mechanism provided environment variables such as `KUBECTL_PLUGINS_CURRENT_NAMESPACE`; that no longer happens. +--> +{{< note >}} +插件机制不会为插件进程创建任何定制的、特定于插件的值或环境变量。 + +较老的插件机制会提供环境变量(例如 `KUBECTL_PLUGINS_CURRENT_NAMESPACE`);这种机制已被废弃。 {{< /note >}} -从上面的场景中使用我们的 `kubectl-foo-bar-baz` 插件,我们将进一步研究用户在提供额外标记和参数的同时调用我们的插件的其他情况。 -例如,在用户调用命令 `kubectl foo bar baz arg1 --flag=value arg2` 的情况下,插件机制将首先尝试找到名称可能最长的插件,在本例中是 `kubectl-foo-bar-baz-arg1`。 -当没有找到这个插件时,它就会将最后一个以破折号分隔的值视为参数(在本例中为 `arg1`),并尝试找到下一个最长的名称 `kubectl-foo-bar-baz`。 -在找到具有此名称的插件后,它将调用该插件,并在其名称之后将所有参数和标志传递给插件可执行文件。 +kubeclt 插件必须解析并检查传递给它们的所有参数。 +参阅[使用命令行运行时包](#using-the-command-line-runtime-package)了解针对 +插件开发人员的 Go 库的细节。 +这里是一些用户调用你的插件的时候提供额外标志和参数的场景。 +这些场景时基于上述案例中的 `kubectl-foo-bar-baz` 插件的。 + + + +如果你运行 `kubectl foo bar baz arg1 --flag=value arg2`,kubeclt 的插件机制将首先尝试找到 +最长可能名称的插件,在本例中是 `kubectl-foo-bar-baz-arg1`。 +当没有找到这个插件时,kubectl 就会将最后一个以破折号分隔的值视为参数(在本例中为 `arg1`), +并尝试找到下一个最长的名称 `kubectl-foo-bar-baz`。 +在找到具有此名称的插件后,它将调用该插件,并在其名称之后将所有参数和标志传递给插件进程。 + + 示例: ```bash -# 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" our plugin by placing it on our PATH +# 将插件放到 PATH 下完成"安装" sudo mv ./kubectl-foo-bar-baz /usr/local/bin -# ensure our plugin is recognized by kubectl +# 确保 kubectl 能够识别我们的插件 kubectl plugin list ``` + ``` The following kubectl-compatible plugins are available: /usr/local/bin/kubectl-foo-bar-baz ``` -``` -# test that calling our plugin via a "kubectl" command works -# even when additional arguments and flags are passed to our -# plugin executable by the user. + +```shell +# 测试通过 "kubectl" 命令来调用我们的插件时可行的 +# 即使我们给插件传递一些额外的参数或标志 kubectl foo bar baz arg1 --meaningless-flag=true ``` + ``` My first command-line argument was arg1 ``` @@ -291,35 +301,32 @@ My first command-line argument was arg1 -正如你所看到的,我们的插件是基于用户指定的 `kubectl` 命令找到的,所有额外的参数和标记都是按原样传递给插件可执行文件的。 +正如你所看到的,我们的插件是基于用户指定的 `kubectl` 命令找到的, +所有额外的参数和标记都是按原样传递给插件可执行文件的。 -#### 带有破折号和下划线的名称 - - -虽然 `kubectl` 插件机制在插件文件名中使用破折号(`-`)分隔插件处理的子命令序列,但是仍然可以通过在文件名中使用下划线(`-`)来创建命令行中包含破折号的插件命令。 +#### 带有破折号和下划线的名称 - +虽然 `kubectl` 插件机制在插件文件名中使用破折号(`-`)分隔插件处理的子命令序列, +但是仍然可以通过在文件名中使用下划线(`-`)来创建命令行中包含破折号的插件命令。 + 例子: ```bash -# 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 +# 将插件放到 PATH 下 sudo mv ./kubectl-foo_bar /usr/local/bin -# our plugin can now be invoked from `kubectl` like so: +# 现在可以通过 kubectl 来调用插件 kubectl foo-bar ``` ``` @@ -330,42 +337,46 @@ I am a plugin with a dash in my name Note that the introduction of underscores to a plugin filename does not prevent us from having commands such as `kubectl foo_bar`. The command from the above example, can be invoked using either a dash (`-`) or an underscore (`_`): --> -请注意,在插件文件名中引入下划线并不会阻止我们使用 `kubectl foo_bar` 之类的命令。可以使用破折号(`-`)或下划线(`-`)调用上面示例中的命令: +请注意,在插件文件名中引入下划线并不会阻止我们使用 `kubectl foo_bar` 之类的命令。 +可以使用破折号(`-`)或下划线(`-`)调用上面示例中的命令: -```bash -# our plugin can be invoked with a dash +```shell +# 我们的插件也可以用破折号来调用 kubectl foo-bar ``` + ``` I am a plugin with a dash in my name ``` -```bash -# it can also be invoked using an underscore +```shell +# 你也可以使用下划线来调用我们的定制命令 kubectl foo_bar ``` + ``` I am a plugin with a dash in my name ``` -#### 命名冲突和弊端 - - -可以在路径的不同位置使用多个文件名相同的插件, -例如,给定一个路径的值为: `PATH=/usr/local/bin/plugins:/usr/local/bin/moreplugins`,在 `/usr/local/bin/plugins` 和 `/usr/local/bin/moreplugins` 中可以存在一个插件 `kubectl-foo` 的副本,这样 `kubectl plugin list` 命令的输出就是: +#### 命名冲突和弊端 + +可以在 `PATH` 的不同位置提供多个文件名相同的插件, +例如,给定一个 `PATH` 为: `PATH=/usr/local/bin/plugins:/usr/local/bin/moreplugins`, +在 `/usr/local/bin/plugins` 和 `/usr/local/bin/moreplugins` 中可以存在一个插件 +`kubectl-foo` 的副本,这样 `kubectl plugin list` 命令的输出就是: ```bash PATH=/usr/local/bin/plugins:/usr/local/bin/moreplugins kubectl plugin list ``` -```bash + +``` The following kubectl-compatible plugins are available: /usr/local/bin/plugins/kubectl-foo @@ -378,28 +389,29 @@ error: one plugin warning was found -在上面的场景中 `/usr/local/bin/moreplugins/kubectl-foo` 下的警告告诉我们这个插件永远不会被执行。相反,首先出现在我们路径中的可执行文件 `/usr/local/bin/plugins/kubectl-foo` 总是首先被 `kubectl` 插件机制找到并执行。 +在上面的场景中 `/usr/local/bin/moreplugins/kubectl-foo` 下的警告告诉我们这个插件永远不会被执行。 +相反,首先出现在我们路径中的可执行文件 `/usr/local/bin/plugins/kubectl-foo` +总是首先被 `kubectl` 插件机制找到并执行。 解决这个问题的一种方法是你确保你希望与 `kubectl` 一起使用的插件的位置总是在你的路径中首先出现。 -例如,如果我们总是想使用 `/usr/local/bin/moreplugins/kubectl foo`,那么在调用 `kubectl` 命令 `kubectl foo` 时,我们只需将路径的值更改为 `PATH=/usr/local/bin/moreplugins:/usr/local/bin/plugins`。 - +例如,如果我们总是想使用 `/usr/local/bin/moreplugins/kubectl foo`, +那么在调用 `kubectl` 命令 `kubectl foo` 时,我们只需将路径的值更改为 `PATH=/usr/local/bin/moreplugins:/usr/local/bin/plugins`。 -#### 调用最长的可执行文件名 - - -对于插件文件名而言还有另一种弊端,给定用户路径中的两个插件 `kubectl-foo-bar` 和 `kubectl-foo-bar-baz` ,`kubectl` 插件机制总是为给定的用户命令选择尽可能长的插件名称。下面的一些例子进一步的说明了这一点: +#### 调用最长的可执行文件名 + +对于插件文件名而言还有另一种弊端,给定用户路径中的两个插件 `kubectl-foo-bar` 和 `kubectl-foo-bar-baz` +`kubectl` 插件机制总是为给定的用户命令选择尽可能长的插件名称。下面的一些例子进一步的说明了这一点: ```bash -# for a given kubectl command, the plugin with the longest possible filename will always be preferred +# 对于给定的 kubectl 命令,最长可能文件名的插件是被优先选择的 kubectl foo bar baz ``` ``` @@ -435,6 +447,7 @@ This design choice ensures that plugin sub-commands can be implemented across mu ```bash ls ./plugin_command_tree ``` + ``` kubectl-parent kubectl-parent-subcommand @@ -443,14 +456,13 @@ kubectl-parent-subcommand-subsubcommand -### 检查插件警告 - - -你可以使用前面提到的 `kubectl plugin list` 命令来确保你的插件可以被 `kubectl` 看到,并且验证没有警告防止它被称为 `kubectl` 命令。 +### 检查插件警告 + +你可以使用前面提到的 `kubectl plugin list` 命令来确保你的插件可以被 `kubectl` 看到, +并且验证没有警告防止它被称为 `kubectl` 命令。 ```bash kubectl plugin list @@ -469,46 +481,105 @@ error: 2 plugin warnings were found -### 使用命令行 runtime 包 +If you're writing a plugin for kubectl and you're using Go, you can make use +of the +[cli-runtime](https://github.com/kubernetes/cli-runtime) utility libraries. + +These libraries provide helpers for parsing or updating a user's +[kubeconfig](/docs/concepts/configuration/organize-cluster-access-kubeconfig/) +file, for making REST-style requests to the API server, or to bind flags +associated with configuration and printing. + +See the [Sample CLI Plugin](https://github.com/kubernetes/sample-cli-plugin) for +an example usage of the tools provided in the CLI Runtime repo. +--> +### 使用命令行运行时包 {#using-the-command-line-runtime-package} + +如果你在编写 kubectl 插件,而且你选择使用 Go 语言,你可以利用 +[cli-runtime](https://github.com/kubernetes/cli-runtime) 工具库。 + +这些库提供了一些辅助函数,用来解析和更新用户的 +[kubeconfig](/zh/docs/concepts/configuration/organize-cluster-access-kubeconfig/) +文件,向 API 服务器发起 REST 风格的请求,或者将参数绑定到某配置上, +抑或将其打印输出。 + +关于 CLI Runtime 仓库所提供的工具的使用实例,可参考 +[CLI 插件示例](https://github.com/kubernetes/sample-cli-plugin) 项目。 -作为 v1.12.0 版本中插件机制更新的一部分,插件作者可以使用另外一组实用程序。这些实用程序在, -[k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) 存储库,并且可以被编写在 Go 中的插件用来解析和更新, -用户的 KUBECONFIG 文件,获取 REST 客户端与 API 服务器通信,并自动绑定与配置和打印相关的参数。 +## 分发 kubectl 插件 + +如果你开发了一个插件给别人使用,你应该考虑如何为其封装打包、如何分发软件 +以及将来的更新到用户。 -插件*不*必须用 Go 编写才能被 `kubectl` 识别为有效的插件,但是它们必须使用 Go 才能使用的 CLI Runtime 存储库中的工具和实用程序。 +### Krew {#distributing-krew} + +[Krew](https://krew.dev/) 提供了一种对插件进行打包和分发的跨平台方式。 +基于这种方式,你会在所有的目标平台(Linux、Windows、macOS 等)使用同一 +种打包形式,包括为用户提供更新。 +Krew 也维护一个[插件索引(plugin index)](https://index.krew.dev/) +以便其他人能够发现你的插件并安装之。 -参见 [CLI 插件示例](https://github.com/kubernetes/sample-cli-plugin)了解 CLI Runtime 存储库中提供的工具的使用示例。 +### 原生的与特定平台的包管理 {#distributing-native} +另一种方式是,你可以使用传统的包管理器(例如 Linux 上 的 `apt` 或 `yum`, +Windows 上的 Chocolatey、macOs 上的 Homebrew)。 +只要能够将新的可执行文件放到用户的 `PATH` 路径上某处,这种包管理器就符合需要。 +作为一个插件作者,如果你选择这种方式来纷飞,你就需要自己来管理和更新 +你的 kubectl 插件的分发包,包括所有平台和所有发行版本。 + +### 源代码 {#distributing-source-code} + +你也可以发布你的源代码,例如,发布为某个 Git 仓库。 +如果你选择这条路线,希望使用该插件的用户必须取回代码、配置一个构造环境 +(如果需要编译的话)并部署该插件。 +如果你也提供编译后的软件包,或者使用 Krew,那就会大大简化安装过程了。 ## {{% heading "whatsnext" %}} - * 查看 CLI 插件库示例,查看用 Go 编写的插件的[详细示例](https://github.com/kubernetes/sample-cli-plugin) -* 如有任何问题,请随时联系 [CLI SIG 小组](https://github.com/kubernetes/community/tree/master/sig-cli) -* 二进制插件是 beta 版的特性,所以现在是时候为代码库贡献一些想法和改进了。我们也很高兴听到您计划用插件实现什么,所以[让我们知道](https://github.com/kubernetes/community/tree/master/sig-cli)! - - - +* 如有任何问题,请随时联系 [SIG CLI ](https://github.com/kubernetes/community/tree/master/sig-cli) +* 了解 [Krew](https://krew.dev/),一个 kubectl 插件管理器。