Helm使用一种名为charts的包格式,一个chart是描述一组相关的k8s资源的文件集合,单个chart可能用于部署简单的应用,比如memcached pod,或者复杂的应用,如一个带有HTTP服务、数据库、缓存等功能的完整web应用程序。
Charts是创建在特定目录下面的文件集合,然后可以将它们打包到一个版本化的存档中来部署。
文件结构
chart被组织为一个目录中的文件集合,目录名称就是chart的名称(不包含版本信息),下面是一个WordPress的chart,会被存储在wordpress/目录下,基本结构如下:
wordpress/Chart.yaml # 包含当前 chart 信息的 YAML 文件LICENSE # 可选:包含 chart 的 license 的文本文件README.md # 可选:一个可读性高的 README 文件values.yaml # 当前 chart 的默认配置 valuesvalues.schema.json # 可选: 一个作用在 values.yaml 文件上的 JSON 模式charts/ # 包含该 chart 依赖的所有 chart 的目录crds/ # Custom Resource Definitionstemplates/ # 模板目录,与 values 结合使用时,将渲染生成 Kubernetes 资源清单文件templates/NOTES.txt # 可选: 包含简短使用使用的文本文件
另外helm会保留charts/、crds/以及templates/目录以及上面列出的文件名的使用。
Chart.yaml文件
对于一个chart包来说Chart.yaml文件是必须的,它包含下面的这些字段:
apiVersion: chart API版本(必须)
name: chart名(必须)
version: SemVer 2版本(必须)
kubeVersion: 兼容的kubernetes版本(可选)
description: 一句话描述(可选)
type: chatr类型(可选)
keywords:
- 当前项目关键字集合(可选)
home: 当前项目的URL(可选)
sources:
- 当前项目源码URL(可选)
dependencies: chart依赖列表(可选)
- name: chart名称(nginx)
version: chart版本("1.2.3")
repository: 仓库地址("http://example.com/charts")
maintainers: (可选)
- name: 维护者名字(对每个maintainer是必须的)
email: 维护者email(可选)
url: 维护者url(可选)
icon: chart的SVG或者PNG图标URL(可选)
appVersion: 包含的应用程序(可选),不需要SemVer版本
deprecated: chart是否已被弃用(可选,boolean)
其他字段默认会被忽略
版本
每个chart都必须有一个版本号,版本必须遵循SemVer2标准,和Helm Classic不同,kubernetes helm使用版本号作为release的标记,仓库中的软件包通过名称加上版本号来标识的。
例如,将一个nginx的chart包version字段设置为1.2.3,则chart最终名称为:
nginx:1.2.3.tgz
还支持更复杂的SemVer2名称,例如版本:1.2.3-alpha.1+ef365,但是需要注意的是系统明确禁止使用非SemVer的名称。
Chart.yaml中的version字段被很多helm工具使用,包括CLI工具,生成包的时候,命令helm package将使用该字段作为包名称中的标记,系统是默认Chart包中的版本号与chart.yaml中的版本号匹配的,所以如果不匹配的话就导致一系列错误。
apiVersion字段
对于helm 3以上的版本apiVersion字段应该是v2,之前版本的Chart应该设置为1,并且也可以由helm 3进行安装。
appVersion字段
要注意appVersion字段与version字段无关,这是一种指定应用程序版本的方法,比如drupal的Chart包可能有一个appVersion: 8.2.1的字段,表示Chart中包含的drupal版本是8.2.1,该字段仅供参考,对Chart版本的计算不会产生影响。
弃用Charts
当在Chart仓库中管理charts的时候,有时候需要弃用一个chart,Chart.yaml中的可选字段deprecated可以用来标记一个chart为弃用状态。如果将仓库中最新版本的chart标记为弃用,则整个chart都会被当做弃用状态了。以后可以通过发布一个未被标记为弃用状态的新版本来重新使用该chart。弃用charts的工作流程如下:
- 更新chart的
Chart.yaml来标记chart为弃用状态 - 发布该新版本到Chart仓库
- 从源码仓库(比如git)中删除chart
Chart类型
type字段定义chart的类型,可以定义两种类型:应用程序(application)和库(library)。应用程序是默认的类型,它是一个可以完整操作的标准chart,库或者辅助类chart为chart提供了一些实用的功能,library不同于应用程序chart,因为它没有资源对象,所以无法安装。
一个应用chart也可以当做库进行使用。通过将类型设置为library,然后该chart就会渲染成一个库,可以在其中使用所有的实用性功能,chart的所有资源对象都不会被渲染。
LICENSE,README和NOTES
Chart还可以包含用于描述chart的安装、配置、用法和许可证书的文件。
LICENSE是一个纯文本文件,其中包含chart的许可证书。chart可以包含一个许可证书,因为它可能在模板中具有编程逻辑,所以不只是配置,如果需要,chart还可以为应用程序提供单独的license。
Chart的README文件应该采用Markdown格式,并且通常应该包含如下的一些信息:
- chart提供的应用程序的描述信息
- 运行chart的任何先决条件或要求
values.yaml和默认值中的一些选项说明- 与chart的安装或配置有关的任何其他信息
chart还可以包含简短的纯文本模板或者NOTES.txt文件,该文件将在安装后以及查看release状态的时候打印出来。该文件会被当成模板文件,并且可以用于显示使用说明,后续步骤或与release有关的任何其他信息。例如,可以提供用于连接到数据或访问 Web UI 的指令。由于在运行 helm install 或者 helm status 的时候该文件会打印到 STDOUT 中,所以建议该文件内容保持内容简短然后可以指向 README 文件来获取更多详细信息。
依赖
在helm中,一个chart包可能会依赖许多其他的chart。这些依赖关系可以使用Chart.yaml中的依赖关系字段动态链接,也可以引入到chart/目录手动进行管理。
使用dependencies字段管理依赖
当前chart所需的依赖chart需要在dependencies字段中进行定义,如下:
dependencies:
- name: apache
version: 1.2.3
repository: https://example.com/charts
- name: mysql
version: 3.2.1
repository: https://another.example.com/charts
- name:依赖的chart的名称
- version:依赖的chart版本
- repository:依赖的chart的完整URL,必须使用
helm repo add在本地添加该repo
定义了依赖项后,可以运行helm dependency update来更新依赖项,它将根据你的依赖项文件把你所有指定的chart包下载到charts/目录中:
$ helm dependency update foochart
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "local" chart repository
...Successfully got an update from the "stable" chart repository
...Successfully got an update from the "example" chart repository
...Successfully got an update from the "another" chart repository
Update Complete. Happy Helming!
Saving 2 charts
Downloading apache from repo https://example.com/charts
Downloading mysql from repo https://another.example.com/charts
当执行helm dependency update命令的时候会解析chart的依赖项,会将他们作为chart包文件下载存放到charts/目录中。
charts/
apache-1.2.3.tgz
mysql-3.2.1.tgz
alias字段
除了上面几个字段之外,每个依赖项还可以包含一个可选的alias别名字段。为依赖chart添加别名将使用别名作为依赖的名称。在需要访问其他名称的chart情况下,就可以使用别名,如下所示:
# parentchart/Chart.yaml
dependencies:
- name: subchart
repository: http://localhost:10191
version: 0.1.0
alias: new-subchart-1
- name: subchart
repository: http://localhost:10191
version: 0.1.0
alias: new-subchart-2
- name: subchart
repository: http://localhost:10191
version: 0.1.0
上面的示例中,我们将获得3个依赖项:
subchart
new-subchart-1
new-subchart-2
当然其实我们也可以手动来实现,将同一个 chart 以不同的名称多次复制/粘贴到 charts/ 目录中也是可以的。
TEMPALTES和VALUES
helm模板是用go template语言](https://golang.org/pkg/text/template/)进行编写的,另外还额外增加了(【Sprig】库中的50个左右的附加模板函数和一些其他专用函数。
所有模板文件都存储在chart的templates/目录下面,当Helm渲染charts的时候,它将通过模板引擎传递该目录中的每个文件。模板的Values可以通过两种方式提供:
- Chart开发人员可以在chart内部提供一个名为
values.yaml的文件,该文件可以包含默认的values值内容。 - Chart用户可以提供包含values值的YAML文件,可以在命令行中通过
helm install来指定该文件。
当用户提供自定义values值的时候,这些值将覆盖chart中values.yaml文件中的相应的值。
模板文件
模板文件遵循编写Go模板的标准约定(可以查看text/template包文档查看详细信息),模板文件示例:
apiVersion: v1
kind: ReplicationController
metadata:
name: deis-database
namespace: deis
labels:
app.kubernetes.io/managed-by: deis
spec:
replicas: 1
selector:
app.kubernetes.io/name: deis-database
template:
metadata:
labels:
app.kubernetes.io/name: deis-database
spec:
serviceAccount: deis-database
containers:
- name: deis-database
image: {{ .Values.imageRegistry}}/postgres:{{ .Values.dockerTag }}
ports:
- containerPort: 5432
env:
- name: DATABASE_STORAGE
value: {{ default "minio" .Values.storage }}
上面这个示例是kubernetes replication控制器的一个模板,它可以使用以下4个模板值(通常在values.yaml文件中定义的):
imageRegistry:Docker镜像仓库dockerTag:Docker镜像tagpullPolicy:镜像拉取策略storage:存储后端,默认设置为”minio”
这些所有的values值都是由模板作者来定义的,Helm不会也不需要规定这些参数。可以查看kubernetes Charts项目去了解更多charts项目的详细内容。
预定义Values
在模板中用.Values可以获取到Values.yaml文件(或者—set参数)提供的values值,此外,还可以在模板中访问其他预定义的数据。下面是一些预定义的、可用于每个模板、并且不能被覆盖的values值,与所有values值一样,名称都是区分大小写的:
- Release.Name: release的名称(不是chart)
- Release.Namespace: release被安装到的命名空间
- Release.Service: 渲染当前模板的服务,在Helm上,实际上该值始终为Helm
- Release.IsUpgrade: 如果当前操作是升级或回滚,则该值为true
- Release.IsInstall: 如果当前操作是安装,则该值为true
- Chart: Chart.yamlw文件的内容,可以通过
Chart.Version来获取Chart的版本,通过Chart.Maintainers可以获取维护者信息 - File: 一个包含chart中所有非特殊文件的map对象,这不会给你访问模板的权限,但是会给你访问存在的其他文件的权限(除非使用
.helmignore排除他们),可以使用{{ index.Files "file.name" }}或者{{ .Files.Get name }}或者{{ .Files.GetString name }}函数来访问文件,还可以使用{{ .Files.GetBytes }}已[]byte的形式获取访问文件的内容 - Capabilities: 也是一个类map的对象,其中包含有关Kubernetes版本(
{{ .Capabilities.KubeVersion }})和支持的Kubenetes API版本({{ .Capabilities.APIVersions.Has "batch/v1" }})信息任何未知的Chart.yaml字段都会被删除,在 Chart 对象内部无法访问他们,所以Chart.yaml不能用于将任意结构化的数据传递到模板中,但是可以使用 values 文件来传递。
Values文件
为模板提供一些必须的values值,如下:
imageRegistry: "quay.io/deis"
dockerTag: "latest"
pullPolicy: "Always"
storage: "s3"
values文件的格式是YAML,一个chart包可能包含一个默认的values.yaml文件,helm install命令允许用户通过提供其他的YAML值来覆盖默认的值:
helm install --values=myvals.yaml wordpress
用这种方式来传递 values 值的时候,它们将合并到默认值文件中,比如有一个 myvals.yaml 文件如下所示:
storage: "gcs"
将其与 chart 的 values.yaml 文件合并后,得到的结果为:
imageRegistry: "quay.io/deis"
dockerTag: "latest"
pullPolicy: "Always"
storage: "gcs"
chart 内包含的默认 values 文件必须命名为
values.yaml,但是在命令行上指定的文件可以任意命名。 如果在 helm install 或者 helm upgrade 的时候使用--set参数,则这些值将在客户端转换为 YAML 格式。 如果 values 文件存在任何必须的条目,则可以使用 required 函数在 chart 模板中将它们声明为必须选项。
使用.Values对象在模板中访问任意一个values值,类似于下面的模板文件:
apiVersion: v1
kind: ReplicationController
metadata:
name: deis-database
namespace: deis
labels:
app.kubernetes.io/managed-by: deis
spec:
replicas: 1
selector:
app.kubernetes.io/name: deis-database
template:
metadata:
labels:
app.kubernetes.io/name: deis-database
spec:
serviceAccount: deis-database
containers:
- name: deis-database
image: {{ .Values.imageRegistry }}/postgres:{{ .Values.dockerTag }}
imagePullPolicy: {{ .Values.pullPolicy }}
ports:
- containerPort: 5432
env:
- name: DATABASE_STORAGE
value: {{ default "minio" .Values.storage}}
作用范围、依赖和Values
values文件可以声明顶级的chart以及该chart的charts/目录中包含的任何chart的值。换句话说,values文件可以为chart以及他的任何依赖项提供values值。例如,上面的wordpress这个chart同时依赖mysql和apache这两个依赖项,values文件可以为所有这些组件提供values值:
title: "My Wordpress Sit" # 传递到Wordpress模板
mysql:
max_connection: 100 # 传递到Mysql
password: "secret"
apache:
port: 8080 # 传递到Apache
较高级别的Charts可以访问下面定义的所有变量,所以Wordpress这个chart可以通过.Values.mysql.password来访问Mysql的密码,但是级别较低的chart是无法访问父chart中的内容,所以Mysql无法获取到title属性,当然也不能访问apache.port。
Values是有命名空间的,但是会对其进行调整,比如对于Wordpress这个chart来说,他可以通过.Values.mysql.password来进行访问,但是对于Mysql这个chart本身来说,values的范围缩小了,命名空间前缀会被删除,所以它只需要通过.Values.password就可以访问到。
全局Values
从2.0.0-Alpha.2版本开始,Helm开始支持特殊的global全局值,比如将上面的示例修改如下:
title: "My Wordpress Sit" # 传递到Wordpress模板
global:
app: MyWordPress
mysql:
max_connection: 100 # 传递到Mysql
password: "secret"
apache:
port: 8080 # 传递到Apache
上面的全局范围的value值,可以通过.Values.global.app提供给所有的chart使用。
例如,mysql的模板可以以{{ .Values.global.app }}来访问app,apache chart也可以,实际上,上面的文件通俗理解为:
title: "My WordPress Site" # 传递到 WordPress 模板
global:
app: MyWordPress
mysql:
global:
app: MyWordPress
max_connections: 100 # 传递到 MySQL
password: "secret"
apache:
global:
app: MyWordPress
port: 8080 # 传递到 Apache
这种方式提供了一种与所有子chart共享一个顶级变量的方式,这对于设置meta数据这种属性是非常有用的。如果子chart声明了全局变量,则该全局变量将向下(传递给子chart的子chart中)传递。而不会向上传递到父chart,子chart无法影响父chart的值。同样,父chart的全局变量优先与子chart中的全局变量。
Schema文件
有时候chart开发者可能希望在其values值上定义一个结构,这种情况下可以通过在values.schema.json文件中定义一个schema来完成,这里schema就是一个JSON Schema文件结构规范,如下所示:
{
"$schema": "https://json-schema.org/draft-07/schema#",
"properties": {
"image": {
"description": "Container Image",
"properties": {
"repo": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"type": "object"
},
"name": {
"description": "Service name",
"type": "string"
},
"port": {
"description": "Port",
"minimum": 0,
"type": "integer"
},
"protocol": {
"type": "string"
}
},
"required": [
"protocol",
"port"
],
"title": "Values",
"type": "object"
}
该schema会对values值进行校验,调用以下任何命令时,都会进行验证:
- helm install
- helm upgrade
- helm lint
- helm template
比如下面的示例文件就可以满足上面的schema要求:
name: frontend
protocol: https
port: 443
需要主机的是该schema将应用于最终的.Values对象,而不仅仅是应用于values.yaml文件,所以下面的文件也是可以满足schema要求的:
name: frontend
protocol: https
因为在安装的时候可以通过--set选项传递了必须的port属性:
$ helm install --set port=443
此外,还会根据所有的子chart schemas来检查最终的.Values对象,这意味着父chart无法规避对子chart的限制。同样的,如果子chart要求未满足子chart的values.yaml文件,则父chart必须满足这些限制才能生效。
参考文档
在编写模板、values、和 schema 文件的时候,下面这些文档可以提供一些帮助:
- Go Template: https://godoc.org/text/template
- 额外的模板函数: https://godoc.org/github.com/Masterminds/sprig
- YAML 文件: https://yaml.org/spec/
- JSON Schema: https://json-schema.org/
CRDS
k8s提供了一种声明新类型的k8s对象的机制,使用CustomResourceDefinitions(CRDS)可以让k8s开发人员声明自定义资源类型。
在Helm3中,CRD被视为一种特殊的对象,它们在chart部分之前被安装,并且会收到一些限制。CRD YAML文件应该放置chart内的crds/目录下面。多个CRDs可以放在同一个文件中,Helm将尝试将CRD目录中所有文件加载到k8s中。
需要注意的是CRD文件不能模板化,他们必须是纯的YAML文件。
使用Helm管理Charts
helm工具有一个用于操作charts的命令,如下所示:
创建一个新的chart包:
$ helm create mychart
Created mychart/
已经编辑了一个chart包,helm可以将其打包到一个独立文件中:
$ helm package mychart
Archived mychart-0.1.-.tgz
使用helm帮助查找chart包的格式要求或者其他问题:
$ helm lint mychart
No issues found
Chart仓库
chart仓库实际上就是一个HTTP服务器,其中包含一个或多个打包的chart包,虽然可以使用helm来管理本地chart目录,但是在共享charts的时候,最好还是使用chart仓库。
可以提供YAML文件和tar文件并可以相应GET请求的任何HTTP服务器都可以作为chart仓库服务器。仓库的主要特征是存在一个名为index.yaml的特殊文件,该文件具有仓库中提供的所有软件包的列表以及允许检索和验证这些软件包的元数据
在客户端,可以使用helm repo命令来管理仓库,但是helm不提供用于将chart上传到远程chart仓库的工具。
