首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Helm Chart 开发 :7个常用的Helm 函数

Helm Chart 开发 :7个常用的Helm 函数

作者头像
DevOps云学堂
发布于 2023-08-22 00:32:51
发布于 2023-08-22 00:32:51
1.1K03
代码可运行
举报
文章被收录于专栏:DevOps持续集成DevOps持续集成
运行总次数:3
代码可运行

点击上方蓝字⭐️关注“DevOps云学堂”,接收最新技术实践

今天是「DevOps云学堂」与你共同进步的第 34 Helm是Kubernetes包管理器。我们大部分时间花在使用现成的Chart上。但通常企业中应用部署的情况下,我们会具有开发创建Helm Chart的必要性。

想要制作自己的 Helm Chart的原因有很多。也许最直接的就是打包您自己的应用程序。有时可能是修改现有Chart以满足特定需求。在所有情况下,创建(或修改)Helm Chart通常涉及使用以下文件(从最常见的文件开始):

  • YAML templates
  • _helpers.tpl

这些文件位于Helm Chart的templates目录中。除了从Sprig库借用的一些功能之外,它们都还使用Go模板语言。这意味着您可以使用Go模板函数 + Sprig 的模板函数来制作最强大的模板。

在一篇文章中几乎不可能讨论 Helm可用的每一个功能。那更像是一本电子书!此外,您不会每天都使用它们。相反,我们列出了七个最广泛使用的 Helm 功能以及一些实际示例。

设置Helm环境

幸运的是,Helm 创建者可以非常轻松地通过命令创建一个 Helm Chart示例,该Chart可以根据用户的特定需求进行自定义。我们需要做的就是运行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
helm create mychart

上面的命令将创建一个名为mychart的目录,其中包含部署功能齐全的 Helm Chart所需的文件。目录内容如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mychart
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml

我们不会一一命名这些函数并显示每个函数的语法及其使用方式。您可以参考Helm 文档来获取此类参考。相反,我们将介绍一些一起使用多个函数的用例。 现在,让我们开始我们的 Helm 函数之旅。

1. 设置副本数上限

我们的第一个场景是为Chart用户可以设置的最大副本数设置上限。

挑战

我们注意到,当部署的Pod数量超过10个时,我们的应用程序在Kubernetes上无法正常运行。我们希望确保每当允许用户设置副本计数(通常在部署中)时,该数量都小于 10。如果指定了更高的数字,Chart应自动将其降低到10。

解决方案

为了实现这个逻辑,我们可以使用以下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{{- if gt (.Values.replicaCount | int ) 10 }} 
   {{- print  10 }} 
{{- else }} 
   {{- print .Values.replicaCount }} 
{{- end }}

让我们分解一下这段代码:

  1. 我们使用该if..else..end结构来做出条件判断。
  2. gt函数测试一个值是否大于一个数字。语法是gt .Arg1 .Arg2. 这里Arg1需要是replicaCount用户在部署Chart时指定的参数。所以,我们使用.Values.replicaCount
  3. 问题是该gt函数只接受数字值。Values.replicaCount作为字符串传递。因此,我们使用该int函数将其转换为整数。Go 中的函数可以在同一行或使用|管道符号接受值(与 Linux shell 的工作方式相同)。我们使用括号来确保将整个内容作为第一个参数.Values.replicaCount | int传递给函数gt。
  4. 传递给该gt函数的第二个参数是10。因此,现在该gt函数正在检查 是否.Value.replicaCount大于 10 并将返回trueorfalse作为结果。
  5. 如果结果是true,则条件成立。该函数只是回显传递给它的任何内容。这里是10。
  6. 否则,让用户自己指定repicaCount,只要小于即可10。

现在,让我们使用这段代码。打开templates/deployment.yaml并将引用 的行replicaCount(应该是第 9 行或第 10 行)更改为如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
replicas: {{ if gt (.Values.replicaCount | int) 10 }}{{- printf "10" }}{{- else }}{{- print .Values.replicaCount }}{{- end }}{{- end }}

为了测试我们的更改,让我们打开values.yaml文件并将replicaCount变量更改为100例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#values.yaml
replicaCount: 100

尝试使用以下命令(在目录mychart内)运行Helm Chart,而不将其安装到集群:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
helm install mychart --dry-run .

输出将是一个YAML清单。通过向上滚动直到部署部分,您会看到如下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Source: mychart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mychart
  labels:
    helm.sh/chart: mychart-0.1.0
    app.kubernetes.io/name: mychart
    app.kubernetes.io/instance: mychart
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  replicas: 10
  selector:
    matchLabels:
      app.kubernetes.io/name: mychart
      app.kubernetes.io/instance: mychart

请思考下我们的副本是如何自动减少到10的, 因为我们打算运行100个副本。 Cool !但现在我们有两个问题:

  1. 模板看起来很丑。我们必须将整个代码片段放在一行上以避免空格问题。
  2. 如果我们想在其他部署模板或也需要遵守相同规则的 StatefulSet 中使用相同的代码片段怎么办?这就是include函数发挥作用的地方。

2. 使用子模板在模板之间共享代码片段

include函数用于将子模板嵌入到模板中的任何位置。子模板可以存储在以下划线开头的任何文件中。如果您注意到,我们的 Helm Chart已经使用了存储在文件中的子模板templates/_helpers.tpl。它包含一些常见的功能,例如如何根据Chart名称和版本名称命名资源以及其他类似用途。在我们的场景中,我们希望将replicaCount限制逻辑存储在子模板中,以便我们可以在任何需要实现它的模板中使用它。让我们看看如何。

打开templates/_helpers.tpl文件(请注意,我们可以创建另一个模板文件,因为 Helm 只会查找以_下划线开头的任何文件并将其视为子模板。我们使用 是_helpers.tpl为了保持一致性和简单性)。将我们的代码片段添加到文件末尾,使其如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{{- define "replicaCountCeiling" -}}
    {{- if gt (.Values.replicaCount | int) 10 }}
        {{- print 10 }}
    {{- else }}
        {{- print .Values.replicaCount }}
    {{- end }}
{{- end }}

注意这里使用define函数,该define函数是一个Go模板函数,用于定义嵌套模板。它在Helm中使用,因为我们追求相同的目的。它接受子模板名称作为参数。直到关键字end为止的任何内容都被视为模板。在这里,我们将逻辑创建为名为 replicaCountCeiling的嵌套模板。

要使用此子模板,请打开templates/deployment.yaml文件并替换我们之前使用的代码,以使该行如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
replicas: {{ include "replicaCountCeiling" . }}

运行helm install mychart --dry-run .应该给出相同的结果。但请注意代码如何更加简洁,并且存储在一个中心位置,只需使用该include函数就可以在许多模板中使用它。但该include功能实际上是如何发挥作用的呢?

include函数采用两个参数:子模板名称和根变量。当我开始学习该include函数时,我认为. 指的是当前目录,就像 UNIX/Linux 指代相对目录一样!然而,这与事实相差甚远。这里的点表示您正在传递子模板可用的所有变量。这意味着当我们在子模板内部调用.Values.replicaCount时,Helm Values可以使用.Values 为了更好地理解这个重要的概念,请考虑更改include函数并传递它,.Values而不是.如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
replicas: {{ include "replicaCountCeiling" .Values }}

如果您尝试试运行Chart,您会收到类似于以下内容的错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Error: INSTALLATION FAILED: template: mychart/templates/deployment.yaml:9:15: executing "mychart/templates/deployment.yaml" at <include "replicaCountCeiling" .Values>: error calling include: template: mychart/templates/_helpers.tpl:64:22: executing "replicaCountCeiling" at <.Values.replicaCount>: nil pointer evaluating interface {}.replicaCount

现在,让我们通过修改replicaCount子模板源中的变量的方式来修复此错误templates/_helpers.tpl

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{{ define "replicaCountCeiling" }}
    {{- if gt (.replicaCount | int) 10 }}
        {{- print 10 }}
    {{- else }}
        {{- print .replicaCount }}
    {{- end }}
{{- end }}

如果您现在尝试试运行Chart,它将毫无问题地工作。但我们改变了什么?我们只是简单地调用该变量而不引用它的父.Values变量。为什么?因为当我们通过函数调用它时,我们已经将它作为根变量传递给子模板include。 大多数时候,您需要将.作为根变量传递以避免混淆并访问Chart可用的所有变量。

3. 生成 YAML 片段

ConfigMap在Kubernetes中被大量使用。它们用于存储可供集群中运行的容器使用的配置参数。假设我们有一个需要提供给容器的配置文件。文件本身如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
db:
  name: mydb
  port: 3306
api:
  url: "http://someurl"
  port: 8080

容器期望在/app/config.yaml下找到该文件。由于我们想要使用 Helm 将应用程序安装到 Kubernetes,因此我们获取文件内容并将值文件放入名为config的键下,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# The last few lines of the values.yaml file
tolerations: []

affinity: {}

config:
  db:
    name: mydb
    port: 3306
  api:
    url: "http://someurl"
    port: 8080

我们创建一个 ConfigMap 模板来保存数据,以便可以将其作为文件安装到容器中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.yaml: | 
# The contents of the config.yaml file

我们有一个键名为的config.yaml,我们需要将数据添加到其中。但如何实现呢?仅引用values文件中的键config,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.yaml: |
{{ .Values.config }}

但是,如果您尝试使用此配置部署Chart,它将失败。以下命令可以帮助我们了解此Chart失败的原因:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
helm template --debug test .

即使 Helm 无法处理它们,这也会为您提供生成的原始 YAML。这对于解决此类问题非常有用。如果我们查看生成的输出,我们会看到生成的 ConfigMap 如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.yaml: |
map[api:map[port:8080 url:http://someurl] db:map[name:mydb port:3306]]

显然,这不是我们所期望的。原因是Go将values.yaml文件中的值转换为它可以使用的数据结构。我们的config数据被转换成一个Map,其中包含一个包含Map的列表。这就是 Go 理解 YAML 并使用它的方式。但我们对Go数据结构的文本表示非常感兴趣!这就是该toYaml功能派上用场的地方。 修改templates/configmap.yaml如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.yaml: |
{{ .Values.config | toYaml }}

toYaml函数仅接受数据结构并将其转换为相应的YAML。这就是我们所需要的。让我们再次重新运行最后一个命令,看看生成的 YAML 是什么样子的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.yaml: |
api:
  port: 8080
  url: http://someurl
db:
  name: mydb
  port: 3306

是的,好多了。至少我们有有效的 YAML,而不是Go映射和列表。但等一下。这并不完全有效,是吗?从values文件中获取的内容与键config.yaml具有相同的缩进级别。这意味着它们没有嵌套在其下,整个 ConfigMap无效。幸运的是,我们有indent功能。indent顾名思义,该函数将内容缩进到指定的缩进级别。我们将templates/configmap.yaml最后一次修改为如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.yaml: |
{{ .Values.config | toYaml | indent 4 }}

我们将values缩进四个空格,因为它有两级深,并且我们使用两个空格进行缩进 (2 + 2 = 4)。如果我们最后一次运行调试命令,ConfigMap 应如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.yaml: |
    api:
      port: 8080
      url: http://someurl
    db:
      name: mydb
      port: 3306

如您所见,该文件包含构造正确ConfigMap的有效YAML。 为了完整起见,关联的部署如下所示(为简洁起见,仅显示相关部分):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      serviceAccountName: {{ include "mychart.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          volumeMounts:
            - name: config-volume
              mountPath: /app/config.yaml
              subPath: config.yaml
# more content
      volumes:
        - name: config-volume
          configMap:
            name: my-configmap
# rest of the file

结论

Helm是一头野兽。但是,如果驯服得当,它将成为你最好的朋友。在本文中,我们探讨了七个最常用的 Helm 函数。使用它们,您已经可以通过模板使用许多强大的技巧来满足非常复杂的需求。然而,Helm 还有许多其他功能可供探索,这将为您在制作Chart时提供更多功能。

往期推荐

ConfigMap:动态更新应用程序配置

Helm指南:Kubernetes包管理器简介

如何实施有效的CI/CD流水线

如果这篇文章对您有帮助,欢迎转发点赞分享。您的关注是我持续分享的动力!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DevOps云学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Helm chart 实践
Helm chart是一个软件包,其中包含将应用程序部署到Kubernetes集群的所有必要资源。这包括用于部署、服务、秘密和配置映射的YAML配置文件,这些配置文件定义了应用程序的所需状态。
五分钟学SRE
2024/03/22
6320
Helm  chart 实践
kubernetes(十七) Helm V3 入门到放弃
K8S上的应用对象,都是由特定的资源描述组成,包括deployment、service等。都保存各自文件中或者集中写到一个配置文件。然后kubectl apply –f 部署。
alexhuiwang
2020/09/23
4.6K0
kubernetes(十七) Helm V3 入门到放弃
【K8s】Kubernetes 包管理工具之 Helm 语法
前文我们介绍过,Helm Chart 是一个包含 Kubernetes 资源定义文件的集合,通过模板化机制,可以灵活地配置和部署应用程序。本文将继续介绍 Helm Chart 的结构和语法,帮助读者更好地理解和和自定义 Helm Chart。
行者Sun
2025/03/13
5060
【K8s】Kubernetes 包管理工具之 Helm 语法
Helm Charts 开发完整示例
Helm 的使用是比较简单的,但是要让我们自己开发一个 Chart 包还是有不小难度的,主要还是 go template 的语法规则不够人性化,这里我们用一个完整的实例来演示下如何开发一个 Helm Chart 包。
我是阳明
2022/04/06
2.2K0
Helm Charts 开发完整示例
helm 构建 chart
如果我们想要在 Kubernetes 集群中部署两个副本的 Ghost,可以直接应用下面的资源清单文件即可:
看、未来
2022/05/20
2.1K0
helm 构建 chart
Helm Chart语法概要
前面分别写到了 JenkinsPipeline语法概要 和 Dockerfile语法概要,最近又重新拾起了Helm Chart,刚好回忆一下其语法 ~
仙人技术
2021/11/08
5.2K0
Helm Chart语法概要
Helm3 使用Harbor仓库存储Chart
本文讲述的是使用Helm3和Harbor v2.3.1的经验,使用Harbor作为Chart仓库服务。来实现更高效、便捷的DevOps运维管理,学习如何撰写自己的Chart应用。文中如有错误的地方,还望各位大佬在评论区指正。
王先森sec
2023/04/24
1.6K0
Helm使用自定义Chart模板来部署k8s应用
它本质上就是一个Go的template模板。Helm在Go template模板的基础上,还会增加很多东西。如一些自定义的元数据信息、扩展的库以及一些类似于编程形式的工作流,例如条件语句、管道等等。这些东西都会使得我们的模板变得更加丰富。
王先森sec
2023/04/24
5K0
Helm v3
K8S上的应用对象,都是由特定的资源描述组成,包括deployment、service等。都保存各自文件中或者集中写到一个配置文件。然后kubectl apply –f 部署。
yuezhimi
2020/09/30
4.7K0
Helm v3
helm charts 模板编程
比如我们需要从.Values中读取的值变成字符串的时候就可以通过调用quote模板函数来实现:(templates/configmap.yaml)
看、未来
2022/05/23
7.2K0
kubernetes-helm程序包管理器(二十)
Helm是Kubernetes的包管理器,Helm 让我们能够像 yum 管理 rpm 包那样安装、部署、升级和删除容器化应用。
yuezhimi
2020/09/30
7430
kubernetes-helm程序包管理器(二十)
k8s的Helm
● kubernetes上的应用对象,都是由特定的资源描述组成,包括Deployment、Service等,都保存在各自文件中或者集中写在一个配置文件,然后通过kubectl apply -f 部署。如果应用只由一个或几个这样的服务组成,上面的部署方式就足够了。但是对于一个复杂的应用,会有很多类似上面的资源描述文件,例如微服务架构应用,组成应用的服务可能多达几十、上百个,如果有更新或回滚应用的需求,可能要修改和维护所涉及到大量的资源文件,而这种组织和管理应用的方式就显得力不从心了。并且由于缺少对发布过的应用进行版本管理和控制,使得kubernetes上的应用维护和更新面临诸多的挑战,主要面临以下的问题:
大忽悠爱学习
2022/09/28
2.4K0
k8s的Helm
K8S包管理神器-Helm
在我们学习 kubernetes 的过程中,用的最多的是 kubectl 命令行工具,使用 kubectl 工具需要我们编写好各种部署文件,这在生产中是非常不方便的,因此 Helm 这个 kubernetes 包管理工具就应运而生了。
星星在线
2021/01/04
5.3K0
K8S包管理神器-Helm
kubernetes(十二) 准入控制和helm v3包管理
RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。
alexhuiwang
2020/09/23
1.5K0
kubernetes(十二) 准入控制和helm v3包管理
Helm 从入门到实践
Helm 是 Kubernetes 的软件包管理工具。本文需要读者对 Docker、Kubernetes 等相关知识有一定的了解。 本文将介绍 Helm 中的相关概念和基本工作原理,并通过一些简单的示例来演示如何使用Helm来安装、升级、回滚一个 Kubernetes 应用。
py3study
2020/05/12
2.3K0
Helm 从入门到实践
Helmfile对已存在的helm release的管理实践
当前示例中,chart的位置位于./chartexample,这个在配置helmfile会用到。
yxxhero
2022/11/11
1.6K0
Istio Helm Chart 详解 - Galley
这里可以看到 Galley 使用 Service Account istio-galley-service-account 的身份运行。全局变量中如果定义了 imagePullSecrets,则会在 serviceaccount.yaml 中进行引用。
崔秀龙
2019/07/23
1.2K0
mac 上学习k8s系列(5)helm chart
类似php 的composer ,go 的go vendor ,linux 的yum ,helm是k8s 应用部署的管理工具。
golangLeetcode
2022/08/02
6570
k8s使用helm打包chart并上传到腾讯云TencentHub
在容器化的时代,我们很多应用都可以部署在docker,很方便,而再进一步,我们还有工具可以对docker进行编排,Kubernetes就是一个很好的工具。再再进一步,Kubernetes出现了helm,可以将多个服务更好的编排组合成一个应用。
饭勺oO
2023/10/18
6490
k8s使用helm打包chart并上传到腾讯云TencentHub
使用 Docker Hub 完美地存储 Helm 图表实战
Helm[1] 是 Kubernetes 的包管理器。它是一个开源容器编排系统。它通过提供一种简单的方法来定义、安装和升级复杂的 Kubernetes 应用程序,帮助您管理 Kubernetes 应用程序。
我的小碗汤
2023/03/20
6390
使用 Docker Hub 完美地存储 Helm 图表实战
相关推荐
Helm chart 实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档