3.1 Helm Hooks 简介
Helm 提供了 Hook 机制,可以允许 Chart 开发人员在 Release 生命周期中的某些节点进行干预。Hooks 的用途通常有:
- 加载其它 Charts 之前,在安装过程中加载 ConfigMap 或 Secret。
- 在安装新 Chart 之前,执行作业来备份数据库;然后在升级后执行第二个作业来恢复数据。
- 在删除 Release 之前运行作业用于停止服务。
Helm 的工作方式与模板一样,但是它们有特殊的注释,可以使 Helm 以不同的方式使用它们。
Helm 的基本用法是在 metadata 中以 annotations 的方式声明,示例如下:
---
metadata:
annotations:
"helm.sh/hook": "pre-upgrade"
可用的 Hooks 值
有如下已经定义好了的 Hooks 供我们使用,列表如下:
| annotations 的值 | 描述 |
|---|---|
| pre-install | 预安装。在模板渲染后,kubernetes 创建资源之前执行 |
| post-install | 安装后。kubernetes 创建资源后执行 |
| pre-delete | 预删除。在 kubernetes 删除任何资源之前执行删除请求 |
| post-delete | 删除后。删除所有 release 资源后执行 |
| pre-upgrade | 升级前。在模板渲染后,但在任何资源升级之前执行 |
| post-upgrade | 升级后。在所有资源升级后执行 |
| pre-rollback | 预回滚。在模板渲染后,任何资源回滚前执行 |
| post-rollback | 回滚后。在修改所有资源后执行 |
生命周期
Hooks 允许开发人员在 release 生命周期的关键节点执行操作。比如,我们执行 helm install 安装命令时 release 的生命周期如下所示:
- 用户运行命令 helm install foo。
- 调用 Helm 仓库的安装 API。
- 经过验证后,仓库渲染 foo 模板。
- 仓库加载渲染后的模板到 kubernetes 中。
- 仓库返回 release 资源对象(和其他数据)到客户端。
- 客户端退出。
Helm 为 install 生命周期定义了两个 Hooks:pre-install 和 post-install。如果对于 foo Chart 使用这两个 Hooks,那么生命周期就变成如下所示:
- 用户运行命令 helm install foo。
- 调用 Helm 仓库的安装 API。
- 安装 crds/ 文件夹中定义的资源对象。
- 经过验证后,仓库渲染 foo 模板。
- 仓库准备执行 pre-install hook(加载 hook 资源到 kubernetes 中)。
- 仓库根据权重对 hooks 进行排序(默认权重为 0,相同权重的 hooks 会按照升序进行排序)。
- 仓库首先加载最低权重的 hooks(从负到正)。
- 仓库等待,直到 hook 准备就绪(除了 CRDs)。
- 仓库加载渲染后的模板到 kubernetes 中。如果设置了 --wait 标志,仓库将等待直到所有资源都处于就绪状态,在就绪之前不会运行 post-upgrade hook。
- 仓库执行 post-upgrade hook(加载 hook 资源到 kubernetes 中)。
- 仓库等待,直到 hook 准备就绪。
- 仓库返回 release 资源对象(和其他数据)到客户端。
- 客户端退出。
等到 hook 准备就绪的特性,取决于 hook 中声明的资源对象类型,比如是 Job 或是 Pod 资源类型,Helm 将会等待直到作业完成。如果这个 hook 失败,那么 Release 的发布也是失败的。
Hook 创建的资源不作为 Release 的一部分进行跟踪或管理。当 Helm 验证 Hook 达到了就绪状态,就不会再管该 Hook 资源了。换句话说,如果使用 Hook 创建资源,无法使用 helm uninstall 删除资源,如果想要销毁这类资源,需要将 helm.sh/hook-delete-policy 注释添加到 hook 模板文件。
3.2 Hook 用例
Hook 的写法和普通模板是一样的,可以使用模板函数和对象,比如:.Values、.Release、.Template等,唯一和普通模板有区别的地方是在 metadata 部分包含一些特殊的注释 annotations。
比如需要在安装后 post-install 执行 hook 运行一个 job,向 templates/post-install-job.yaml 文件中写入如下内容:
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ .Release.Name }}"
labels:
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
annotations:
# 通过添加 annotations,这个资源会被视为 hook。如果没有这行注释,这个 Job 资源只会当做 Release 的一部分。
"helm.sh/hook": post-install # hook 的类型
"helm.sh/hook-weight": "-5" # hook 的权重
"helm.sh/hook-delete-policy": hook-succeeded # hook 的删除方式
spec:
template:
metadata:
name: "{{ .Release.Name }}"
labels:
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
spec:
restartPolicy: Never
containers:
- name: post-install-job
image: "alpine:3.3"
command: ["/bin/sleep","{{ default "10" .Values.sleepyTime }}"]
一个资源可以部署多个 hook,写法如下:
annotations:
"helm.sh/hook": post-install,post-upgrade
为 hook 设置权重可以帮助确定执行顺序,权重可以是正数或是负数,但是必须是字符串。当 Helm 开始执行某个特定类型的 hook 时(比如:pre-install hooks、post-install hooks),会按升序对这些 hook 进行排序:
annotations:
"helm.sh/hook-weight": "5"
还可以定义 hook 的删除策略:
annotations:
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
与删除策略有关的注释值有:
- before-hook-creation:在新 hook 创建之前删除以前的 hook。这是默认的删除策略。
- hook-succeeded:在 hook 成功执行后删除 hook 资源。
- hook-failed:如果 hook 在执行期间失败就删除该 hook 资源。
比如现在使用 Helm 部署一个 nginx Pod,并且干扰正常的安装过程,设置 pre-install 和 post-install。先创建一个 Chart:
$ helm create nginx-helm
Creating nginx-helm
然后在 nginx-helm/templates 目录下新建 pre-install-HookPod.yaml 文件,并向其中写入如下内容:
apiVersion: v1
kind: Pod
metadata:
name: pre-install-hook-pod
annotations:
"helm.sh/hook": "pre-install"
spec:
containers:
- name: hook1-container
image: busybox
imagePullPolicy: IfNotPresent
command:
["sh", "-c", "echo The pre-install hook Pod is running && sleep 10"]
restartPolicy: Never
terminationGracePeriodSeconds: 0
然后在该目录下新建 post-install-HookPod.yaml 文件,并向其中写入如下内容:
apiVersion: v1
kind: Pod
metadata:
name: post-install-hook-pod
annotations:
"helm.sh/hook": "post-install"
spec:
containers:
- name: hook1-container
image: busybox
imagePullPolicy: IfNotPresent
command: ["sh", "-c", "echo post-install hook Pod is running && sleep 10"]
restartPolicy: Never
terminationGracePeriodSeconds: 0
现在执行安装:
$ helm install mynginx ./nginx-helm
NAME: mynginx
LAST DEPLOYED: Sat Nov 21 11:13:02 2020
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace kube-system -l "app.kubernetes.io/name=nginx-helm,app.kubernetes.io/instance=mynginx" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace kube-system $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace kube-system port-forward $POD_NAME 8080:$CONTAINER_PORT
现在查看所有的 Pod 状态:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mynginx-nginx-helm-84f8bc846d-jht9k 1/1 Running 0 57s
post-install-hook-pod 0/1 Completed 0 57s
pre-install-hook-pod 0/1 Completed 0 69s
当不需要的时候,执行删除 nginx:
$ helm uninstall mynginx
release "mynginx" uninstalled
但hook需要手动删除:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
post-install-hook-pod 0/1 Completed 0 3m15s
pre-install-hook-pod 0/1 Completed 0 3m27s
$ kubectl delete pod post-install-hook-pod pre-install-hook-pod
pod "post-install-hook-pod" deleted
pod "pre-install-hook-pod" deleted
3.3 Chart 仓库
下面介绍如何创建和使用 Helm Chart repo。仓库的主要用途是存储和分享 chart 包。
创建 Chart 仓库
Chart 仓库是带有一个 index.yaml 文件和任意个打包文件并能回答 GET 请求的 HTTP 服务器。如果想要分享 Chart 包,最好是先将其上传到仓库中。
当选择托管 Chart 仓库时可以有多种选择,比如:Google 云端存储,Amazon S3 存储桶,Github Pages,或者是搭建自己的服务器。
Chart 仓库结构
一个 Chart 仓库由两部分组成:
- index.yaml 文件:包含 Chart 仓库中所有 Chart 的索引。
- Chart 包:这些打包文件通常都是在 index.yaml 文件中列出的。
比如,https://example.com/charts 仓库的文件结构如下所示:
charts/
|
|- index.yaml
|
|- alpine-0.1.2.tgz
|
|- alpine-0.1.2.tgz.prov
在这个例子中,index.yaml 文件中只包含一个 Chart 的信息。即:Alpine Chart,对应的下载链接地址为 https://example.com/charts/alpine-0.1.2.tgz。
index.yaml 索引文件
index.yaml 索引文件中包含关于包的元数据。使用 helm repo index 命令根据包含打包文件的本地目录生成索引文件。
下面是 index.yaml 文件的一个示例:
apiVersion: v1
entries:
alpine:
- created: 2016-10-06T16:23:20.499814565-06:00
description: Deploy a basic Alpine Linux pod
digest: 99c76e403d752c84ead610644d4b1c2f2b453a74b921f422b9dcb8a7c8b559cd
home: https://helm.sh/helm
name: alpine
sources:
- https://github.com/helm/helm
urls:
- https://technosophos.github.io/tscharts/alpine-0.2.0.tgz
version: 0.2.0
- created: 2016-10-06T16:23:20.499543808-06:00
description: Deploy a basic Alpine Linux pod
digest: 515c58e5f79d8b2913a10cb400ebb6fa9c77fe813287afbacf1a0b897cd78727
home: https://helm.sh/helm
name: alpine
sources:
- https://github.com/helm/helm
urls:
- https://technosophos.github.io/tscharts/alpine-0.1.0.tgz
version: 0.1.0
nginx:
- created: 2016-10-06T16:23:20.499543808-06:00
description: Create a basic nginx HTTP server
digest: aaff4545f79d8b2913a10cb400ebb6fa9c77fe813287afbacf1a0b897cdffffff
home: https://helm.sh/helm
name: nginx
sources:
- https://github.com/helm/charts
urls:
- https://technosophos.github.io/tscharts/nginx-1.1.0.tgz
version: 1.1.0
generated: 2016-10-06T16:23:20.499029981-06:00
托管 Chart 库
这里介绍两种常用的方式,一种是使用 GitHub Pages 托管,另一种是使用普通的 Web 服务器。
方法一:使用 GitHub Pages 托管
GitHub 可以使用两种不同的方式提供静态 web 页面:
- 通过配置项目来提供 docs/ 目录下的文件。
- 通过配置项目为特定分支提供服务。
这里采用第二种方式提供演示。在仓库中新建名为 gh-pages 的分支。

然后将 gh-pages 分支设置为 Github Pages,点击 repo Settings,向下滚动到 GitHub Pages,并按照如下方式进行设置:

方法二:使用普通的 Web 服务器
如果配置普通的 Web 服务器存储 Helm Chart,需要确保:
- index.yaml 文件和 Chart 都处于服务器目录中。
- 无需认证就可以访问 index.yaml 文件。
- yaml 文件格式是正确的。
管理 Chart 库
准备好打包 Chart,创建一个新目录,然后将打包 Chart 移动到该目录下:
# 打包
$ helm package docs/examples/alpine/
# 创建新目录
$ mkdir fantastic-charts
# 将打包好的文件移动到新目录下
$ mv alpine-0.1.0.tgz fantastic-charts/
# helm repo index 命令为 fantastic-charts 目录生成 index.yaml 文件,https://xxx.com 表示的是远程库的 URL
$ helm repo index fantastic-charts --url https://xxx.com
如果在 fantastic-charts 目录下添加了新文件,可以使用 helm repo index 命令重新生成新的索引,或是使用 --merge 参数向 index.yaml 文件增量添加新 Chart 索引。
如果要分享 Chart,只需要提供仓库 URL 即可,完整命令为 helm repo add [NAME] [URL]。比如:
$ helm repo add fantastic-charts https://xxx.com
$ helm repo list
fantastic-charts https://xxx.com
3.4 配置 Harbor 为 Helm 的存储仓库
介绍
Harbor 也是 CNCF 基金会托管的开源项目,它主要是作为 kubernetes 的云原生存储库。之前用于镜像管理,在 V1.6 版本中增加了对于 Helm Charts 的管理功能。
本次挑战需要完成如下的步骤:
1.在集群中使用 Helm 安装 Harbor。
添加harbor库
$ helm repo add goharbor https://helm.goharbor.io
"goharbor" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "goharbor" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm search repo goharbor
NAME CHART VERSION APP VERSION DESCRIPTION
goharbor/harbor 1.5.1 2.1.1 An open source trusted cloud native registry th...
查看harbor安装文件:
$ helm install --dry-run --debug testHarbor goharbor/harbor >> harborHelmInstall.out
$ ls ~/.cache/helm/repository/harbor-1.5.1.tgz
$ tar zxf ~/.cache/helm/repository/harbor-1.5.1.tgz
$ tree harbor
harbor
├── cert
│ ├── tls.crt
│ └── tls.key
├── Chart.yaml
├── conf
│ ├── clair.yaml
│ ├── notary-server.json
│ └── notary-signer.json
├── LICENSE
├── README.md
├── templates
│ ├── chartmuseum
│ │ ├── chartmuseum-cm.yaml
│ │ ├── chartmuseum-dpl.yaml
│ │ ├── chartmuseum-pvc.yaml
│ │ ├── chartmuseum-secret.yaml
│ │ ├── chartmuseum-svc.yaml
│ │ └── chartmuseum-tls.yaml
│ ├── clair
│ │ ├── clair-dpl.yaml
│ │ ├── clair-secret.yaml
│ │ ├── clair-svc.yaml
│ │ └── clair-tls.yaml
│ ├── core
│ │ ├── core-cm.yaml
│ │ ├── core-dpl.yaml
│ │ ├── core-secret.yaml
│ │ ├── core-svc.yaml
│ │ └── core-tls.yaml
│ ├── database
│ │ ├── database-secret.yaml
│ │ ├── database-ss.yaml
│ │ └── database-svc.yaml
│ ├── _helpers.tpl
│ ├── ingress
│ │ ├── ingress.yaml
│ │ └── secret.yaml
│ ├── internal
│ │ └── auto-tls.yaml
│ ├── jobservice
│ │ ├── jobservice-cm-env.yaml
│ │ ├── jobservice-cm.yaml
│ │ ├── jobservice-dpl.yaml
│ │ ├── jobservice-pvc.yaml
│ │ ├── jobservice-secrets.yaml
│ │ ├── jobservice-svc.yaml
│ │ └── jobservice-tls.yaml
│ ├── nginx
│ │ ├── configmap-https.yaml
│ │ ├── configmap-http.yaml
│ │ ├── deployment.yaml
│ │ ├── secret.yaml
│ │ └── service.yaml
│ ├── notary
│ │ ├── notary-secret.yaml
│ │ ├── notary-server.yaml
│ │ ├── notary-signer.yaml
│ │ └── notary-svc.yaml
│ ├── NOTES.txt
│ ├── portal
│ │ ├── configmap.yaml
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── tls.yaml
│ ├── redis
│ │ ├── service.yaml
│ │ └── statefulset.yaml
│ ├── registry
│ │ ├── registry-cm.yaml
│ │ ├── registry-dpl.yaml
│ │ ├── registry-pvc.yaml
│ │ ├── registry-secret.yaml
│ │ ├── registry-svc.yaml
│ │ └── registry-tls.yaml
│ └── trivy
│ ├── trivy-secret.yaml
│ ├── trivy-sts.yaml
│ ├── trivy-svc.yaml
│ └── trivy-tls.yaml
└── values.yaml
这里为了方便使用,需要对官方提供的 Chart 进行一定的修改,包括:
- 关闭持久存储。
--set persistence.enabled=false - 关闭 TLS 认证。
--set expose.tls.enabled=false - 配置服务类型为 NodePort,并指定外部访问地址为 http://192.168.0.32:30002
Shell --set expose.type=nodePort # 上面已经关闭TLS认证了,这行执行时也不采用 --set expose.nodePort.ports.https=null # 以下两行设置与默认值相同,执行时不采用 --set expose.nodePort.ports.http.port=80 --set expose.nodePort.ports.http.nodePort=30002 # 设置externalURL, --set externalURL=http://192.168.0.32:30002
执行创建:
$ helm install --set persistence.enabled=false --set expose.tls.enabled=false --set expose.type=nodePort --set externalURL=http://192.168.0.32:30002 harbor goharbor/harbor
NAME: harbor
...
NOTES:
Please wait for several minutes for Harbor deployment to complete.
Then you should be able to visit the Harbor portal at http://192.168.0.32:30002
For more details, please visit https://github.com/goharbor/harbor
2.登录 Harbor 页面,创建测试仓库。
当 Harbor 部署完成后,在浏览器访问http://192.168.0.32:30002,登录时默认的账号名为 admin,密码为 Harbor12345。

创建测试仓库,创建测试用户


3.配置本地 Helm 推送 Chart 到 Harbor。
在 Helm 中添加远端仓库
$ helm repo add repo_test http://192.168.0.32:30002/chartrepo/chart_repo
"repo_test" has been added to your repositories
安装 helm-push 插件
$ helm plugin install https://github.com/chartmuseum/helm-push
Downloading and installing helm-push v0.9.0 ...
https://github.com/chartmuseum/helm-push/releases/download/v0.9.0/helm-push_0.9.0_linux_amd64.tar.gz
Installed plugin: push
从标准仓库中获取一个 MySQL Chart 包
$ helm fetch stable/mysql
$ ls mysql-1.6.9.tgz
mysql-1.6.9.tgz
将打包好的chart包推送到远端仓库中,需要制定user和password。
$ helm push mysql-1.6.9.tgz repo_test -u admin -p Harbor12345
Pushing mysql-1.6.9.tgz to repo_test...
Done.
评论区