库图表

库图表是 Helm 图表 的一种类型,它定义了可以由其他图表中的 Helm 模板共享的图表基本元素或定义。 这允许用户共享代码片段,这些代码片段可以在图表之间重复使用,从而避免重复并保持图表 DRY

库图表在 Helm 3 中引入,正式认可自 Helm 2 以来图表维护者使用的通用或辅助图表。 通过将其包含为图表类型,它提供了

  • 一种明确区分通用图表和应用程序图表的方法
  • 防止安装通用图表的逻辑
  • 不会在可能包含发布工件的通用图表中渲染模板
  • 允许依赖图表使用导入器的上下文

图表维护者可以将通用图表定义为库图表,现在可以确信 Helm 将以标准一致的方式处理图表。 这也意味着应用程序图表中的定义可以通过更改图表类型来共享。

创建一个简单的库图表

如前所述,库图表是 Helm 图表 的一种类型。 这意味着您可以从创建脚手架图表开始

$ helm create mylibchart
Creating mylibchart

您首先将删除 templates 目录中的所有文件,因为我们将在本例中创建自己的模板定义。

$ rm -rf mylibchart/templates/*

值文件也不需要。

$ rm -f mylibchart/values.yaml

在我们开始创建通用代码之前,让我们快速回顾一下一些相关的 Helm 概念。 命名模板(有时称为部分或子模板)只是在文件中定义并赋予名称的模板。 在 templates/ 目录中,任何以下划线(_)开头的文件都不希望输出 Kubernetes 清单文件。 所以按照惯例,辅助模板和部分被放置在 _*.tpl_*.yaml 文件中。

在本例中,我们将编写一个创建空 ConfigMap 资源的通用 ConfigMap。 我们将在文件 mylibchart/templates/_configmap.yaml 中定义通用 ConfigMap,如下所示

{{- define "mylibchart.configmap.tpl" -}}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name | printf "%s-%s" .Chart.Name }}
data: {}
{{- end -}}
{{- define "mylibchart.configmap" -}}
{{- include "mylibchart.util.merge" (append . "mylibchart.configmap.tpl") -}}
{{- end -}}

ConfigMap 结构在命名模板 mylibchart.configmap.tpl 中定义。 它是一个简单的 ConfigMap,具有一个空资源 data。 在此文件中,还有一个名为 mylibchart.configmap 的命名模板。 此命名模板包含另一个名为 mylibchart.util.merge 的命名模板,该模板将接受两个命名模板作为参数:调用 mylibchart.configmap 的模板和 mylibchart.configmap.tpl

辅助函数 mylibchart.util.mergemylibchart/templates/_util.yaml 中的命名模板。 它是 通用 Helm 辅助图表 中的一个便捷实用程序,因为它合并了两个模板并覆盖了两个模板中任何公共部分

{{- /*
mylibchart.util.merge will merge two YAML templates and output the result.
This takes an array of three values:
- the top context
- the template name of the overrides (destination)
- the template name of the base (source)
*/}}
{{- define "mylibchart.util.merge" -}}
{{- $top := first . -}}
{{- $overrides := fromYaml (include (index . 1) $top) | default (dict ) -}}
{{- $tpl := fromYaml (include (index . 2) $top) | default (dict ) -}}
{{- toYaml (merge $overrides $tpl) -}}
{{- end -}}

当图表想要使用需要使用其配置进行自定义的通用代码时,这一点很重要。

最后,让我们将图表类型更改为 library。 这需要编辑 mylibchart/Chart.yaml,如下所示

apiVersion: v2
name: mylibchart
description: A Helm chart for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
# type: application
type: library

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application and it is recommended to use it with quotes.
appVersion: "1.16.0"

库图表现在已准备好共享,其 ConfigMap 定义可以重复使用。

在继续之前,值得检查 Helm 是否将图表识别为库图表

$ helm install mylibchart mylibchart/
Error: library charts are not installable

使用简单的库图表

现在是使用库图表的时候了。 这意味着再次创建一个脚手架图表

$ helm create mychart
Creating mychart

让我们再次清理模板文件,因为我们只想要创建一个 ConfigMap

$ rm -rf mychart/templates/*

当我们想要在 Helm 模板中创建一个简单的 ConfigMap 时,它可能类似于以下内容

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name | printf "%s-%s" .Chart.Name }}
data:
  myvalue: "Hello World"

但是,我们将重复使用在 mylibchart 中创建的通用代码。 ConfigMap 可以创建在文件 mychart/templates/configmap.yaml 中,如下所示

{{- include "mylibchart.configmap" (list . "mychart.configmap") -}}
{{- define "mychart.configmap" -}}
data:
  myvalue: "Hello World"
{{- end -}}

您可以看到,它通过继承通用 ConfigMap 定义简化了我们的工作,该定义为 ConfigMap 添加了标准属性。 在我们的模板中,我们添加了配置,在本例中是数据键 myvalue 及其值。 该配置覆盖了通用 ConfigMap 的空资源。 这是可行的,因为我们在上一节中提到的辅助函数 mylibchart.util.merge

为了能够使用通用代码,我们需要将 mylibchart 添加为依赖项。 将以下内容添加到文件 mychart/Chart.yaml 的末尾

# My common code in my library chart
dependencies:
- name: mylibchart
  version: 0.1.0
  repository: file://../mylibchart

这将库图表包含为来自文件系统的动态依赖项,该文件系统与我们的应用程序图表位于同一父路径。 由于我们将库图表包含为动态依赖项,因此我们需要运行 helm dependency update。 它将库图表复制到您的 charts/ 目录中。

$ helm dependency update mychart/
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 1 charts
Deleting outdated charts

我们现在已准备好部署图表。 在安装之前,值得先检查渲染后的模板。

$ helm install mydemo mychart/ --debug --dry-run
install.go:159: [debug] Original chart version: ""
install.go:176: [debug] CHART PATH: /root/test/helm-charts/mychart

NAME: mydemo
LAST DEPLOYED: Tue Mar  3 17:48:47 2020
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
  pullPolicy: IfNotPresent
  repository: nginx
imagePullSecrets: []
ingress:
  annotations: {}
  enabled: false
  hosts:
  - host: chart-example.local
    paths: []
  tls: []
mylibchart:
  global: {}
nameOverride: ""
nodeSelector: {}
podSecurityContext: {}
replicaCount: 1
resources: {}
securityContext: {}
service:
  port: 80
  type: ClusterIP
serviceAccount:
  annotations: {}
  create: true
  name: null
tolerations: []

HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
data:
  myvalue: Hello World
kind: ConfigMap
metadata:
  labels:
    app: mychart
    chart: mychart-0.1.0
    release: mydemo
  name: mychart-mydemo

这看起来像我们想要的 ConfigMap,其中数据覆盖为 myvalue: Hello World。 让我们安装它

$ helm install mydemo mychart/
NAME: mydemo
LAST DEPLOYED: Tue Mar  3 17:52:40 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

我们可以检索发布并查看实际加载的模板。

$ helm get manifest mydemo
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
data:
  myvalue: Hello World
kind: ConfigMap
metadata:
  labels:
    app: mychart
    chart: mychart-0.1.0
    release: mydemo
  name: mychart-mydemo

库图表优势

由于无法充当独立图表,库图表可以利用以下功能

  • .Files 对象引用父图表上的文件路径,而不是库图表本地路径
  • .Values 对象与父图表相同,与接收其标题下配置的值部分的应用程序 子图表 形成对比。

通用 Helm 辅助图表

Note: The Common Helm Helper Chart repo on Github is no longer actively maintained, and the repo has been deprecated and archived.

图表 是通用图表的原始模式。 它提供了反映 Kubernetes 图表开发最佳实践的实用程序。 最重要的是,您在开发图表时可以立即使用它,为您提供便捷的共享代码。

以下是如何快速使用它。 有关更多详细信息,请查看 自述文件

再次创建一个脚手架图表

$ helm create demo
Creating demo

让我们使用辅助图表中的通用代码。 首先,编辑部署 demo/templates/deployment.yaml,如下所示

{{- template "common.deployment" (list . "demo.deployment") -}}
{{- define "demo.deployment" -}}
## Define overrides for your Deployment resource here, e.g.
apiVersion: apps/v1
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "demo.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "demo.selectorLabels" . | nindent 8 }}

{{- end -}}

现在是服务文件 demo/templates/service.yaml,如下所示

{{- template "common.service" (list . "demo.service") -}}
{{- define "demo.service" -}}
## Define overrides for your Service resource here, e.g.
# metadata:
#   labels:
#     custom: label
# spec:
#   ports:
#   - port: 8080
{{- end -}}

这些模板显示了如何从辅助图表继承通用代码,将您的编码简化为资源的配置或自定义。

为了能够使用通用代码,我们需要将 common 添加为依赖项。 将以下内容添加到文件 demo/Chart.yaml 的末尾

dependencies:
- name: common
  version: "^0.0.5"
  repository: "https://charts.helm.sh/incubator/"

注意:您需要将 incubator 仓库添加到 Helm 仓库列表中(helm repo add)。

由于我们将图表包含为动态依赖项,因此我们需要运行 helm dependency update。 它将辅助图表复制到您的 charts/ 目录中。

由于辅助图表使用了一些 Helm 2 结构,因此您需要将以下内容添加到 demo/values.yaml 中,以启用 nginx 映像加载,因为这在 Helm 3 脚手架图表中已更新

image:
  tag: 1.16.0

您可以使用 helm linthelm template 命令测试图表模板是否正确,然后再部署。

如果一切正常,请使用 helm install 部署!