Helm详细教程

1. 概述

Helm是Kubernetes的包管理工具,类似于Linux系统中常用的apt、yum等包管理工具。使用Helm可以简化Kubernetes应用的部署。

2. 基本概念

  • Chart:一个Helm包,包含了运行一个应用所需的镜像、依赖和资源定义等,类似于Homebrew中的formula、APT的dpkg或者Yum的rpm文件。
  • Release:在Kubernetes集群上运行的Chart的一个实例。一个Chart可以在同一个集群上安装多次,每次安装都会创建一个新的Release。
  • Repository:用于发布和存储Chart的存储库。

3. 架构

Chart Install过程:

  1. Helm从指定的目录或者tgz文件中解析出Chart结构信息。
  2. Helm将指定的Chart结构和Values信息通过gRPC传递给Tiller。
  3. Tiller根据Chart和Values生成一个Release。
  4. Tiller将Release发送给Kubernetes运行。

Chart Update过程:

  1. Helm从指定的目录或者tgz文件中解析出Chart结构信息。
  2. Helm将要更新的Release的名称和Chart结构,Values信息传递给Tiller。
  3. Tiller生成Release并更新指定名称的Release的History。
  4. Tiller将Release发送给Kubernetes运行。

4. 安装helm

Helm包括helm客户端和Tiller服务端两部分,Tiller部署在Kubernetes集群中。

4.1. 安装客户端

可以根据自己的环境从GitHub地址下载对应的安装包:

例如:

下载后解压到自己喜欢的目录,然后配置对应的PATH环境变量。

4.2. 配置kubectl命令

默认情况下,Helm操作Kubernetes集群需要借助kubectl命令的集群配置。也可以直接给Helm命令指定--kubeconfig参数指定Kubernetes集群证书路径。

# 通过--kubeconfig参数指定Kubernetes证书的方式操作Kubernetes集群
# 下面命令是部署一个名字叫app-demo的应用,Helm包在./chart目录中
/alidata/server/helm-v2.13.1/helm --kubeconfig ./config/k8s.conf install app-demo ./chart

4.3. 安装服务端

使用helm init命令,可以一键安装Tiller。

5. 基本用法

以制作一个简单的网站应用Chart包为例介绍Helm的基本用法。

5.1. 创建chart包

通过helm create命令创建一个新的chart包。

例子:

# 在当前目录创建一个myapp chart包
helm create myapp

创建完成后,得到的目录结构如下:

myapp                                   - chart包目录名
├── charts                              - 依赖的子包目录,里面可以包含多个依赖的chart包
├── Chart.yaml                          - chart定义,可以定义chart的名字,版本号信息。
├── templates                           - k8s配置模版目录,我们编写的k8s配置都在这个目录,除了NOTES.txt和下划线开头命名的文件,其他文件可以随意命名。
│   ├── deployment.yaml
│   ├── _helpers.tpl                    - 下划线开头的文件,helm视为公共库定义文件,主要用于定义通用的子模版、函数等,helm不会将这些公共库文件的渲染结果提交给k8s处理。
│   ├── ingress.yaml
│   ├── NOTES.txt                       - chart包的帮助信息文件,执行helm install命令安装成功后会输出这个文件的内容。
│   └── service.yaml
└── values.yaml                         - chart包的参数配置文件,模版可以引用这里的参数。

5.2. 编写k8s应用部署配置文件

为了演示chart包模版的用法,我们先把deployment.yamlservice.yamlingress.yaml三个配置文件的内容清空,重新编写Kubernetes部署文件。

deployment.yaml 配置文件

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: myapp           # deployment应用名
  labels:
    app: myapp          # deployment应用标签定义
spec:
  replicas: 1           # pod副本数
  selector:
    matchLabels:
      app: myapp          # pod选择器标签
  template:
    metadata:
      labels:
        app: myapp          # pod标签定义
    spec:
      containers:
        - name: myapp           # 容器名
          image: xxxxxx:1.7.9    # 镜像地址
          ports:
            - name: http
              containerPort: 80
              protocol: TCP

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc # 服务名
spec:
  selector: # pod选择器定义
    app: myapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: myapp-ingress # ingress应用名
spec:
  rules:
    - host: www.xxxxx.com  # 域名
      http:
        paths:
          - path: /
            backend:
              serviceName: myapp-svc # 服务名
              servicePort: 80

5.3. 提取k8s应用部署配置文件中的参数,作为chart包参数

values.yaml chart包参数定义

# 域名
host: www.XXX.com

# 镜像参数
image: XXXXXXXXXXXXXXXXXX
imageTag: 1.7.9

# pod 副本数
replicas: 1

5.4. 通过helm命令安装/更新应用

安装应用

# 命令格式: helm install chart包目录
helm install --set replicas=2 --set host=www.xxxx.com ./myapp

更新应用

# 命令格式: helm upgrade release名字 chart包目录
helm upgrade myapp ./myapp

也可以指定--set参数:

helm upgrade --set replicas=2 --set host=www.xxxx.com myapp ./myapp

默认情况下,如果release名字不存在,upgrade会失败,可以加上-i参数当release不存在的时候则安装,存在则更新,将install和upgrade命令合并。

helm upgrade -i --set replicas=2 --set host=www.xxxx.com myapp ./myapp

6. 模版语法

6.1. 表达式

模版表达式:{{ 模版表达式 }}

模版表达式:{{- 模版表达式 -}},表示去掉表达式输出结果前面和后面的空格。

6.2. 变量

默认情况点(.), 代表全局作用域,用于引用全局对象。

例子:

{{ .Values.key }}

helm全局作用域中有两个重要的全局对象:Values和Release

  • Values代表的就是values.yaml定义的参数,通过.Values可以引用任意参数。

  • Release代表一次应用发布,下面是Release对象包含的属性字段:

    • Release.Name   - release的名字,一般通过Chart.yaml定义,或者通过helm命令在安装应用的时候指定。
    • Release.Time    - release安装时间
    • Release.Namespace    - k8s名字空间
    • Release.Revision      - release版本号,是一个递增值,每次更新都会加一
    • Release.IsUpgrade   - true代表,当前release是一次更新.
    • Release.IsInstall       - true代表,当前release是一次安装

例子:

{{ .Release.Name }}

除了系统自带的变量,我们自己也可以自定义模版变量。

6.3. 函数&管道运算符

调用函数的语法:{{ functionName arg1 arg2... }}

例子:

{{ quote .Values.favorite.food }}

管道(pipelines)运算符 |

{{ .Values.favorite.food | quote }}

常用的关系运算符>、 >=、 <、!=、与或非在helm模版中都以函数的形式实现。

关系运算函数定义:

  • eq  相当于 =
  • ne  相当于 !=
  • lt  相当于 <
  • gt  相当于 >
  • and  相当于 &&
  • or  相当于 ||
  • not  相当于 !

例子:


{{ if and .Values.fooString (eq .Values.fooString "foo") }}
    {{ ... }}
{{ end }}

6.4. 流程控制语句

6.4.1. IF/ELSE

语法:

{{ if 条件表达式 }}
# Do something
{{ else if 条件表达式 }}
# Do something else
{{ else }}
# Default case
{{ 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}}

6.4.2. with

with主要就是用来修改.作用域的,默认.代表全局作用域,with语句可以修改.的含义.

语法:

{{ with 引用的对象 }}
这里可以使用 . (点),直接引用with指定的对象
{{ end }}

例子:

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

6.4.3. range

range主要用于循环遍历数组类型。

语法1:

{{- range $key, $val := 键值对象 }}
{{ $key }}: {{ $val | quote }}
{{- end}}

语法2:

{{- range 数组 }}
{{ . | title | quote }}
{{- end }}

例子:

# values.yaml定义

# map类型
favorite:
  drink: coffee
  food: pizza

# 数组类型
pizzaToppings:
  - mushrooms
  - cheese
  - peppers
  - onions

map类型遍历例子:
{{- range $key, $val := .Values.favorite }}
{{ $key }}: {{ $val | quote }}
{{- end}}

数组类型遍历例子:
{{- range .Values.pizzaToppings}}
{{ . | quote }}
{{- end}}

6.5. 子模版定义

我们可以在_(下划线)开头的文件中定义子模版,方便后续复用。

子模版语法:

定义模版
{{ define "模版名字" }} 模版内容 {{ end }}
引用模版:
{{ include "模版名字" 作用域}}

例子:

# 模版定义
{{- define "mychart.app" }}
app_name: {{ .Chart.Name }}
app_version: "{{ .Chart.Version }}+{{ .Release.Time.Seconds }}"
{{- end }}

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
  labels:
    {{ include "mychart.app" . | nindent 4 }}
data:
  myvalue: "Hello World"

6.6. 调试

编写好chart包的模版之后,我们可以给helm命令加上--debug--dry-run两个参数,让helm输出模版结果,但是不把模版输出结果交给k8s处理。

例子:

helm upgrade --debug --dry-run -i --set replicas=2 --set host=www.xxxx.com myapp ./myapp

打 赏