Helm chart

时间:Nov. 20, 2020 分类:

目录:

Helm chart

参考

全文参考https://helm.sh/docs/chart_template_guide/整理

入门

Helm chart结构

mychart/
  Chart.yaml
  values.yaml
  charts/
  templates/
  ...

创建简单的Helm chart

$ helm create mychart
Creating mychart

mychart/templates/目录结构

  • NOTES.txt:帮助文本,运行时helm install时显示
  • _helpers.tpl:放置模板助手的地方,可重复使用

添加个configmap,mychart/templates/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

直接构建即可,full-coral是发行版的名称

$ helm install full-coral ./mychart
NAME: full-coral
LAST DEPLOYED: Tue Nov  1 17:36:01 2016
NAMESPACE: default
STATUS: DEPLOYED
REVISION: 1
TEST SUITE: None

检测已经发布的模板

$ helm get manifest full-coral

---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

卸载使用helm uninstall full-coral

模板调动的helm chart

调整configmap

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"

Release是helm内置对象

$ helm install clunky-serval ./mychart

执行就会生成clunky-serval-configmap

测试可以指定--dry-run参数,打印渲染后的模板

内置对象

Release为对象描述,包含

  • Release.Name:发行名称
  • Release.Namespace:安装的namespace,如果chart中没有进行覆盖
  • Release.IsUpgrade:如是是升级和回滚,该值为true
  • Release.IsInstall:如是是安装,该值为true
  • Release.Revision:版本号,安装的时候为1,之后升级和回滚都会增加
  • Release.Service:模板服务,helm就一直为helm

还有

Values为values.yaml文件内容

Chart为Chart.yaml内容,参考the-chartyaml-file

Files为非特殊文件的访问,参考[accessing_files](https://helm.sh/docs/chart_template_guide/accessing_files/)

  • Files.Get:获取文件
  • Files.GetBytes:获取文件的字节数组
  • Files.Glob:
  • Files.Lines:逐行读取文件
  • Files.AsSecrets:文件内容做base64
  • Files.AsConfig:文件内容作为yaml

Capabilities为kubernetes支持能力

  • Capabilities.APIVersions
  • Capabilities.APIVersions.Has
  • Capabilities.KubeVersion
  • Capabilities.KubeVersion.Version
  • Capabilities.KubeVersion.Major
  • Capabilities.KubeVersion.Minor

Template为模板相关信息

  • Template.Name:模板文件路径(例如 mychart/templates/mytemplate.yaml)
  • Template.BasePath:模板文件路径(例如mychart/templates)

value

value的获取有很多方式

  • chart中的value文件
  • 父级的value文件
  • helm installhelm upgrade传入,例如helm install -f myvals.yaml ./mychart
  • 通过--set传入,例如helm install --set foo=bar ./mychart

优先级是从下到上的顺序,set的优先级最高

使用value

在value.yaml中写入favoriteDrink: coffee

configmap调整为

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favoriteDrink }}

测试一下

$ helm install geared-marsupi ./mychart --dry-run --debug
install.go:158: [debug] Original chart version: ""
install.go:175: [debug] CHART PATH: /home/bagratte/src/playground/mychart

NAME: geared-marsupi
LAST DEPLOYED: Wed Feb 19 23:21:13 2020
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
favoriteDrink: coffee

HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: good-puppy-configmap
data:
  myvalue: "Hello World"
  drink: coffee

value文件调整为

favorite:
  drink: coffee
  food: pizza

configmap调整为

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink }}
  food: {{ .Values.favorite.food }}

在set的指定drink=slurm

删除默认值

默认的探针为

livenessProbe:
  httpGet:
    path: /user/login
    port: http
  initialDelaySeconds: 120

直接set添加是不行的,--set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt]会生成

livenessProbe:
  httpGet:
    path: /user/login
    port: http
  exec:
    command:
    - cat
    - docroot/CHANGELOG.txt
  initialDelaySeconds: 120

需要将livenessProbe.httpGet设置为null,helm install stable/drupal --set image=my-registry/drupal:0.1.0 --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] --set livenessProbe.httpGet=null

模板的方法和管道

模板使用

模板支持很多方法,基本都是go模板语言定义和sprig库提供的

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ quote .Values.favorite.drink }}
  food: {{ quote .Values.favorite.food }}

或则使用管道的方式

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | quote }}
  food: {{ .Values.favorite.food | quote }}

所以.val | quote等价于quote .val

支持多个管道

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | quote }}
  food: {{ .Values.favorite.food | upper | quote }}

模板设置默认字段

在模板内部设置默认值

drink: {{ .Values.favorite.drink | default "tea" | quote }}

查找集群内资源

有apiVersion,kind,namespace和name,语法为lookup apiVersion, kind, namespace, name -> resource or resource list

例如

# kubectl get pod mypod -n mynamespace
lookup "v1" "Pod" "mynamespace" "mypod"
# kubectl get pods -n mynamespace
lookup "v1" "Pod" "mynamespace" ""
# kubectl get pods --all-namespaces 
lookup "v1" "Pod" "" ""
# kubectl get namespace mynamespace 
lookup "v1" "Namespace" "" "mynamespace"
# kubectl get namespaces    
lookup "v1" "Namespace" "" ""

然后使用返回的数据

(lookup "v1" "Namespace" "" "mynamespace").metadata.annotations

对于列表数据通过range来获取

{{ range $index, $service := (lookup "v1" "Service" "mynamespace" "").items }}
    {{/* do something with each service */}}
{{ end }}

但是交互失败就会造成模板处理失败

helm install|update|delete|rollback --dry-run获取到的也为空

运算符

eq,ne,lt,gt,and,or都可以在管道中使用,支持括号

更多方法

更多方法参考官方文档function_list

流程控制

if/else

{{ if PIPELINE }}
  # Do something
{{ else if OTHER PIPELINE }}
  # Do something else
{{ else }}
  # Default case
{{ end }}

为false和go一样,零值

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | default "tea" | quote }}
  food: {{ .Values.favorite.food | upper | quote }}
  {{ if eq .Values.favorite.drink "coffee" }}mug: true{{ end }}

格式对其

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | default "tea" | quote }}
  food: {{ .Values.favorite.food | upper | quote }}
  {{- if eq .Values.favorite.drink "coffee" }}
  mug: true
  {{- end }}

{{- value}}为左侧不留白

也可以通过方法控制{{ indent 2 "mug:true" }}

with

控制变量作用域

{{ with PIPELINE }}
  # restricted scope
{{ end }}

示例,将.的作用域调整为.Values.favorite

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  {{- end }}

但是也会造成无法访问作用域之外了,需要使用$.

{{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  release: {{ $.Release.Name }}
{{- end }}

range

value使用

favorite:
  drink: coffee
  food: pizza
pizzaToppings:
  - mushrooms
  - cheese
  - peppers
  - onions

configmap就可以写成

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  {{- end }}
  toppings: |-
    {{- range .Values.pizzaToppings }}
    - {{ . | title | quote }}
    {{- end }}

也可以在模板中创建一个tuple

sizes: |-
    {{- range tuple "small" "medium" "large" }}
    - {{ . }}
    {{- end }}

产生的就是

sizes: |-
    - small
    - medium
    - large

变量

设置变量

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- $relname := .Release.Name -}}
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  release: {{ $relname }}
  {{- end }}

在循环中使用变量

toppings: |-
    {{- range $index, $topping := .Values.pizzaToppings }}
      {{ $index }}: {{ $topping }}
    {{- end }}

循环map

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- range $key, $val := .Values.favorite }}
  {{ $key }}: {{ $val | quote }}
  {{- end }}

获取全局变量仍然是$

模板

声明模板

语法

{{ define "MY.NAME" }}
  # body of template here
{{ end }}

示例生成一个标签快

{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
{{- end }}

使用模板

{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
  {{- template "mychart.labels" }}
data:
  myvalue: "Hello World"
  {{- range $key, $val := .Values.favorite }}
  {{ $key }}: {{ $val | quote }}
  {{- end }}
···


### 模板文件

模板文件通常放在_helpers.tpl中

{{/* Generate basic labels */}} {{- define "mychart.labels" }} labels: generator: helm date: {{ now | htmlDate }} {{- end }}


这样{{/* ... */}}可以描述作用

### 模板作用域

{{/* Generate basic labels */}} {{- define "mychart.labels" }} labels: generator: helm date: {{ now | htmlDate }} chart: {{ .Chart.Name }} version: {{ .Chart.Version }} {{- end }}


如果在使用的时候不指定作用域,会取不到值,需要指定,例如示例的`.`


{{- template "mychart.labels" . }}


### include

通过include控制模板的缩进,{{ include "mychart.app" . | indent 4 }}

例如模板

{{- define "mychart.app" -}} app_name: {{ .Chart.Name }} app_version: "{{ .Chart.Version }}" {{- end -}}


使用

apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap labels: {{ template "mychart.app" . }} data: myvalue: "Hello World" {{- range $key, $val := .Values.favorite }} {{ $key }}: {{ $val | quote }} {{- end }} {{ template "mychart.app" . }}


得到的就是

kind: ConfigMap metadata: name: measly-whippet-configmap labels: app_name: mychart app_version: "0.1.0+1478129847" data: myvalue: "Hello World" drink: "coffee" food: "pizza" app_name: mychart app_version: "0.1.0+1478129847"


## 访问文件

### Get


config1.toml:

message = Hello from config 1


config2.toml:

message = This is config 2


config3.toml:

message = Goodbye from config 3


获取配置

apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap data: {{- $files := .Files }} {{- range tuple "config1.toml" "config2.toml" "config3.toml" }} {{ . }}: |- {{ $files.Get . }} {{- end }}


### Glob

获取组织

{{ range $path, $_ := .Files.Glob "**.yaml" }} {{ $.Files.Get $path }} {{ end }}


直接生成yaml配置

apiVersion: v1 kind: ConfigMap metadata: name: conf data:

{{ (.Files.Glob "foo/*").AsConfig | indent 2 }}

apiVersion: v1 kind: Secret metadata: name: very-secret type: Opaque data: {{ (.Files.Glob "bar/*").AsSecrets | indent 2 }}


### base编码

apiVersion: v1 kind: Secret metadata: name: {{ .Release.Name }}-secret type: Opaque data: token: |- {{ .Files.Get "config1.toml" | b64enc }}


获取到的结果

Source: mychart/templates/secret.yaml

apiVersion: v1 kind: Secret metadata: name: lucky-turkey-secret type: Opaque data: token: |- bWVzc2FnZSA9IEhlbGxvIGZyb20gY29uZmlnIDEK


### 循环模板文件

data: some-file.txt: {{ range .Files.Lines "foo/bar.txt" }} {{ . }}{{ end }}



## note文件

note文件是用于描述模板功能和可用对象的文件

templates/NOTES.txt

Thank you for installing {{ .Chart.Name }}.

Your release is named {{ .Release.Name }}.

To learn more about the release, try:

$ helm status {{ .Release.Name }} $ helm get all {{ .Release.Name }}





## .helmignore

指定不在chart的文件


comment

Match any file or path named .git

.git

Match any text file

*.txt

Match only directories named mydir

mydir/

Match only text files in the top-level directory

/*.txt

Match only the file foo.txt in the top-level directory

/foo.txt

Match any file named ab.txt, ac.txt, or ad.txt

a[b-d].txt

Match any file under subdir matching temp*

/temp

//temp* temp?


和git的区别

- 不支持**语法
- 不支持!


## debug


查看模板使用

helm install --dry-run --debug 或 helm template --debug


- `helm lint`检查是否满足语法
- `helm get manifest`查看安装的方法

示例

apiVersion: v2

some: problem section

{{ .Values.foo | quote }}


进行`helm install --dry-run --debug`,获得的是

apiVersion: v2

some: problem section

"bar"

```