跳到主要内容
版本:3.19.0

Helm 插件指南

Helm 插件是一个可以通过 helm CLI 访问的工具,但不是 Helm 的内置代码。

已有插件可以在 相关项目 部分找到,也可以搜索 GitHub

本指南介绍如何使用和创建插件。

概述

Helm 插件是与 Helm 无缝集成的附加工具。插件提供一种扩展 Helm 核心特性集的方法,但不需要每个新的特性都用 Go 编写并加入核心工具中。

Helm 插件有以下特性:

  • 可以在不影响 Helm 核心工具的情况下添加和移除。
  • 可以用任意编程语言编写。
  • 与 Helm 集成,并展示在 helm help 和其他地方。

Helm 插件位于 $HELM_PLUGINS。你可以使用 helm env 命令找到该变量的当前值,包括未在环境中设置时的默认值。

Helm 插件模型部分基于 Git 的插件模型。为此,你有时可能听到 helm 被称为 porcelain 层,而插件是 plumbing 层。这是一种简写方式,表示 Helm 提供用户体验和顶层处理逻辑,而插件执行所需操作的"细节工作"。

安装插件

使用 helm plugin install <path|url> 命令安装插件。你可以传入本地文件系统上的插件路径或远程 VCS 仓库的 URL。helm plugin install 命令会将给定路径/URL 的插件克隆或复制到 $HELM_PLUGINS。如果从 VCS 安装,可以使用 --version 参数指定版本。

$ helm plugin install https://github.com/adamreese/helm-env

如果是插件 tar 包,只需将插件解压到 $HELM_PLUGINS 目录。也可以直接从 URL 安装 tar 包插件:helm plugin install https://domain/path/to/plugin.tar.gz

插件文件结构

在很多方面,插件类似于 chart。每个插件都有一个包含 plugin.yaml 文件的顶级目录。可能存在其他文件,但只有 plugin.yaml 文件是必需的。

$HELM_PLUGINS/
|- last/
|- plugin.yaml

plugin.yaml 文件

plugin.yaml 文件是插件的必需文件。它包含以下字段:

name: 插件名称(必需)
version: SemVer 2 版本号(必需)
usage: 在帮助中显示的单行使用说明
description: 在 helm help 等位置显示的详细描述
ignoreFlags: 忽略从 Helm 传入的参数
platformCommand: # 根据平台配置要执行的命令
- os: 操作系统匹配,可以为空或省略以匹配所有操作系统
arch: 架构匹配,可以为空或省略以匹配所有架构
command: 要执行的插件命令
args: 插件命令参数
command: (已弃用)插件命令,请改用 platformCommand
platformHooks: # 根据平台配置插件生命周期钩子
install: # 安装生命周期命令
- os: 操作系统匹配,可以为空或省略以匹配所有操作系统
arch: 架构匹配,可以为空或省略以匹配所有架构
command: 要执行的插件安装命令
args: 插件安装命令参数
update: # 更新生命周期命令
- os: 操作系统匹配,可以为空或省略以匹配所有操作系统
arch: 架构匹配,可以为空或省略以匹配所有架构
command: 要执行的插件更新命令
args: 插件更新命令参数
delete: # 删除生命周期命令
- os: 操作系统匹配,可以为空或省略以匹配所有操作系统
arch: 架构匹配,可以为空或省略以匹配所有架构
command: 要执行的插件删除命令
args: 插件删除命令参数
hooks: # (已弃用)插件生命周期钩子,请改用 platformHooks
install: 安装插件的命令
update: 更新插件的命令
delete: 删除插件的命令
downloaders: # 配置下载器能力
- command: 要调用的命令
protocols:
- 支持的协议方案

name 字段

name 是插件的名称。当 Helm 执行此插件时使用此名称(例如,helm NAME 会调用此插件)。

name 应该匹配目录名称。 在上面的例子中,这意味着 name: last 的插件应该包含在名为 last 的目录中。

name 的限制:

  • name 不能与现有的 helm 顶级命令重复。
  • name 的字符必须限制为 ASCII a-z、A-Z、0-9、_-

version 字段

version 是插件的 SemVer 2 版本。usagedescription 都用于生成命令的帮助文本。

ignoreFlags 字段

ignoreFlags 开关告诉 Helm 不要 将参数传递给插件。因此,如果插件使用 helm myplugin --foo 调用且 ignoreFlags: true,那么 --foo 会被静默丢弃。

platformCommand 字段

platformCommand 配置插件被调用时将执行的命令。你不能同时设置 platformCommandcommand,否则会导致错误。以下规则用于决定使用哪个命令:

  • 如果 platformCommand 存在,它将被使用。
    • 如果 osarch 都匹配当前平台,搜索将停止并使用该命令。
    • 如果 os 匹配且 arch 为空,将使用该命令。
    • 如果 osarch 都为空,将使用该命令。
    • 如果没有匹配,Helm 会报错退出。
  • 如果 platformCommand 不存在但已弃用的 command 存在,将使用 command
    • 如果命令为空,Helm 会报错退出。

platformHooks 字段

platformHooks 配置插件针对生命周期事件将执行的命令。你不能同时设置 platformHookshooks,否则会导致错误。以下规则用于决定使用哪个钩子命令:

  • 如果 platformHooks 存在,它将被使用,并处理生命周期事件的命令。
    • 如果 osarch 都匹配当前平台,搜索将停止并使用该命令。
    • 如果 os 匹配且 arch 为空,将使用该命令。
    • 如果 osarch 都为空,将使用该命令。
    • 如果没有匹配,Helm 将跳过该事件。
  • 如果 platformHooks 不存在但已弃用的 hooks 存在,将使用生命周期事件的命令。
    • 如果命令为空,Helm 将跳过该事件。

构建插件

下面是一个简单插件的 YAML,用于获取最后一个 release 名称:

name: last
version: 0.1.0
usage: get the last release name
description: get the last release name
ignoreFlags: false
platformCommand:
- command: ${HELM_BIN}
args:
- list
- --short
- --max=1
- --date
- -r

插件可能需要额外的脚本和可执行文件。脚本可以包含在插件目录中,可执行文件可以通过钩子下载。以下是一个示例插件:

$HELM_PLUGINS/
|- myplugin/
|- scripts/
|- install.ps1
|- install.sh
|- plugin.yaml
name: myplugin
version: 0.1.0
usage: example plugin
description: example plugin
ignoreFlags: false
platformCommand:
- command: ${HELM_PLUGIN_DIR}/bin/myplugin
- os: windows
command: ${HELM_PLUGIN_DIR}\bin\myplugin.exe
platformHooks:
install:
- command: ${HELM_PLUGIN_DIR}/scripts/install.sh
- os: windows
command: pwsh
args:
- -c
- ${HELM_PLUGIN_DIR}\scripts\install.ps1
update:
- command: ${HELM_PLUGIN_DIR}/scripts/install.sh
args:
- -u
- os: windows
command: pwsh
args:
- -c
- ${HELM_PLUGIN_DIR}\scripts\install.ps1
- -Update

环境变量会在插件执行前被插值。上述模式说明了表示插件程序所在位置的首选方法。

插件命令

以下是使用插件命令的一些策略:

  • 如果插件包含可执行文件,platformCommand: 的可执行文件应该打包在插件目录中或通过钩子安装。
  • platformCommand:command: 行会在执行前展开所有环境变量。$HELM_PLUGIN_DIR 会指向插件目录。
  • 命令本身不是在 shell 中执行的。所以你不能写成一行 shell 脚本。
  • Helm 在环境变量中注入了大量配置。查看环境变量以了解可用信息。
  • Helm 对插件的语言不做任何假设。你可以用任何你喜欢的语言编写。
  • 命令负责实现 -h--help 的特定帮助文本。Helm 会在 helm helphelm help myplugin 中使用 usagedescription,但不会处理 helm myplugin --help

测试本地插件

首先你需要找到你的 HELM_PLUGINS 路径,运行以下命令:

helm env

切换到 HELM_PLUGINS 设置的目录。

现在你可以添加一个指向插件构建输出的符号链接,在这个例子中我们为 mapkubeapis 创建链接。

ln -s ~/GitHub/helm-mapkubeapis ./helm-mapkubeapis

下载器插件

默认情况下,Helm 可以使用 HTTP/S 拉取 Chart。从 Helm 2.4.0 开始,插件有一种特殊能力可以从任意来源下载 Chart。

插件应该在 plugin.yaml 文件(顶层)中声明这个特殊能力:

downloaders:
- command: "bin/mydownloader"
protocols:
- "myprotocol"
- "myprotocols"

如果安装了这样的插件,Helm 可以通过调用 command 使用指定的协议方案与仓库进行交互。特殊仓库的添加与常规仓库类似:helm repo add favorite myprotocol://example.com/。特殊仓库的规则与常规仓库相同:Helm 必须能够下载 index.yaml 文件以发现和缓存可用 Chart 的列表。

已定义的命令将使用以下格式调用:command certFile keyFile caFile full-URL。SSL 证书来自仓库定义,存储在 $HELM_REPOSITORY_CONFIG(即 $HELM_CONFIG_HOME/repositories.yaml)。下载器插件应将原始内容输出到 stdout,并在 stderr 报告错误。

下载器命令也支持子命令或参数,允许你在 plugin.yaml 中指定,例如 bin/mydownloader subcommand -d。如果你想为主插件命令和下载器命令使用相同的可执行文件,但每个使用不同的子命令,这将非常有用。

环境变量

当 Helm 执行插件时,会将外部环境传递给插件,并且会注入一些额外的环境变量。

KUBECONFIG 这样的变量,如果在外部环境中设置了,则会为插件设置。

以下变量保证会被设置:

  • HELM_PLUGINS:插件目录的路径。
  • HELM_PLUGIN_NAME:由 helm 调用的插件名称。所以 helm myplug 的短名称是 myplug
  • HELM_PLUGIN_DIR:包含插件的目录。
  • HELM_BINhelm 命令的路径(如用户执行的那样)。
  • HELM_DEBUG:表示 helm 是否设置了 debug 标志。
  • HELM_REGISTRY_CONFIG:注册表配置的位置(如果使用)。注意,Helm 与注册表的使用是实验性功能。
  • HELM_REPOSITORY_CACHE:仓库缓存文件的路径。
  • HELM_REPOSITORY_CONFIG:仓库配置文件的路径。
  • HELM_NAMESPACE:给 helm 命令的命名空间(通常使用 -n 标志)。
  • HELM_KUBECONTEXT:给 helm 命令的 Kubernetes 配置上下文名称。

另外,如果明确指定了 Kubernetes 配置文件,它将被设置为 KUBECONFIG 变量。

参数解析说明

当执行插件时,Helm 会解析全局标志供自己使用。这些标志都不会传递给插件。

  • --burst-limit:转换为 $HELM_BURST_LIMIT
  • --debug:如果指定,$HELM_DEBUG 设置为 1
  • --kube-apiserver:转换为 $HELM_KUBEAPISERVER
  • --kube-as-group:转换为 $HELM_KUBEASGROUPS
  • --kube-as-user:转换为 $HELM_KUBEASUSER
  • --kube-ca-file:转换为 $HELM_KUBECAFILE
  • --kube-context:转换为 $HELM_KUBECONTEXT
  • --kube-insecure-skip-tls-verify:转换为 $HELM_KUBEINSECURE_SKIP_TLS_VERIFY
  • --kube-tls-server-name:转换为 $HELM_KUBETLS_SERVER_NAME
  • --kube-token:转换为 $HELM_KUBETOKEN
  • --kubeconfig:转换为 $KUBECONFIG
  • --namespace-n:转换为 $HELM_NAMESPACE
  • --qps:转换为 $HELM_QPS
  • --registry-config:转换为 $HELM_REGISTRY_CONFIG
  • --repository-cache:转换为 $HELM_REPOSITORY_CACHE
  • --repository-config:转换为 $HELM_REPOSITORY_CONFIG

插件 应该-h--help 显示帮助文本然后退出。在所有其他情况下,插件可以根据需要使用参数。

提供 shell 自动补全

从 Helm 3.2 开始,作为 Helm 现有自动补全机制的一部分,插件可以选择性地提供 shell 自动补全支持。

静态自动补全

如果插件提供了自己的标志和/或子命令,可以通过在插件根目录中放置 completion.yaml 文件来通知 Helm。completion.yaml 文件格式如下:

name: <pluginName>
flags:
- <flag 1>
- <flag 2>
validArgs:
- <arg value 1>
- <arg value 2>
commands:
name: <commandName>
flags:
- <flag 1>
- <flag 2>
validArgs:
- <arg value 1>
- <arg value 2>
commands:
<以此类推,递归>

注意:

  1. 所有部分都是可选的,但应在适用时提供。
  2. 标志不应包含 --- 前缀。
  3. 可以且应该指定短标志和长标志。短标志不需要与其对应的长格式关联,但两种形式都应列出。
  4. 标志不需要以任何方式排序,但需要列在文件子命令层次结构的正确位置。
  5. Helm 现有的全局标志已由 Helm 的自动补全机制处理,因此插件不需要指定以下标志:--debug--namespace-n--kube-context--kubeconfig,或任何其他全局标志。
  6. validArgs 列表提供了子命令后第一个参数的可能补全的静态列表。并非总是能事先提供这样的列表(参见下面的动态补全部分),在这种情况下可以省略 validArgs 部分。

completion.yaml 文件是完全可选的。如果没有提供,Helm 将不会为插件提供 shell 自动补全功能(除非插件支持动态补全)。另外,添加 completion.yaml 文件是向后兼容的,不会影响在旧版 helm 中使用插件的行为。

例如,对于 fullstatus 插件,它没有子命令但接受与 helm status 命令相同的标志,completion.yaml 文件是:

name: fullstatus
flags:
- o
- output
- revision

一个更复杂的例子是 2to3 插件,它的 completion.yaml 文件是:

name: 2to3
commands:
- name: cleanup
flags:
- config-cleanup
- dry-run
- l
- label
- release-cleanup
- s
- release-storage
- tiller-cleanup
- t
- tiller-ns
- tiller-out-cluster
- name: convert
flags:
- delete-v2-releases
- dry-run
- l
- label
- s
- release-storage
- release-versions-max
- t
- tiller-ns
- tiller-out-cluster
- name: move
commands:
- name: config
flags:
- dry-run

动态补全

同样从 Helm 3.2 开始,插件可以提供自己的动态 shell 自动补全。动态 shell 自动补全是对无法事先定义的参数值或标志值的补全。例如,补全集群中当前可用的 helm release 名称。

对于支持动态自动补全的插件,必须在其根目录中提供一个名为 plugin.complete可执行文件。当 Helm 补全脚本需要插件的动态补全时,它将执行 plugin.complete 文件,传递需要补全的命令行。plugin.complete 可执行文件需要有逻辑来确定正确的补全选项,并将它们输出到标准输出以供 Helm 补全脚本使用。

plugin.complete 文件是完全可选的。如果没有提供,Helm 将不会为插件提供动态自动补全。另外,添加 plugin.complete 文件是向后兼容的,不会影响在旧版 helm 中使用插件的行为。

plugin.complete 脚本的输出应该是以换行分隔的列表,例如:

rel1
rel2
rel3

当调用 plugin.complete 时,插件环境的设置与调用插件主脚本时相同。因此,变量 $HELM_NAMESPACE$HELM_KUBECONTEXT 和所有其他插件变量都已设置,并且它们对应的全局标志会被移除。

plugin.complete 文件可以是任何可执行形式;它可以是 shell 脚本、Go 程序或任何其他 Helm 可以执行的程序。plugin.complete 文件 必须 对用户具有可执行权限。plugin.complete 文件 必须 以成功代码(值 0)退出。

在某些情况下,动态补全需要从 Kubernetes 集群获取信息。例如,helm fullstatus 插件需要 release 名称作为输入。在 fullstatus 插件中,它的 plugin.complete 脚本要提供当前 release 名称的补全,只需运行 helm list -q 并输出结果即可。

如果希望插件执行和插件补全使用相同的可执行文件,可以让 plugin.complete 脚本使用某些特殊参数或标志调用主插件可执行文件;当主插件可执行文件检测到特殊参数或标志时,它就知道要运行补全。在我们的例子中,plugin.complete 可以这样实现:

#!/usr/bin/env sh

# "$@" is the entire command-line that requires completion.
# It is important to double-quote the "$@" variable to preserve a possibly empty last parameter.
$HELM_PLUGIN_DIR/status.sh --complete "$@"

fullstatus 插件的实际脚本(status.sh)必须查找 --complete 标志,如果找到,则打印出正确的补全。

提示和技巧

  1. Shell 会自动过滤掉与用户输入不匹配的补全选项。因此,插件可以返回所有相关的补全,而不需要移除与用户输入不匹配的选项。例如,如果命令行是 helm fullstatus ngin<TAB>plugin.complete 脚本可以打印 所有default 命名空间的)release 名称,而不仅仅是以 ngin 开头的;shell 只会保留以 ngin 开头的。
  2. 为了简化动态补全支持,特别是如果你有一个复杂的插件,你可以让 plugin.complete 脚本调用你的主插件脚本并请求补全选项。参见上面的动态补全部分的例子。
  3. 要调试动态补全和 plugin.complete 文件,可以运行以下命令查看补全结果:
    • helm __complete <pluginName> <arguments to complete>。例如:
    • helm __complete fullstatus --output js<ENTER>
    • helm __complete fullstatus -o json ""<ENTER>