下面我们通过一个完整的示例来学习如何使用 Helm 创建、打包、分发、安装、升级及回退Kubernetes应用

创建一个名为 mychart 的 Chart

使用$ helm create mychart当前目录创建了一个 mychart 目录,该目录结构如下所示:

  1. $ tree mychart/
  2. mychart/
  3. ├── charts
  4. ├── Chart.yaml
  5. ├── templates
  6. ├── deployment.yaml
  7. ├── _helpers.tpl
  8. ├── ingress.yaml
  9. ├── NOTES.txt
  10. ├── serviceaccount.yaml
  11. ├── service.yaml
  12. └── tests
  13. └── test-connection.yaml
  14. └── values.yaml
  15. chartname/
  16. Chart.yaml # 包含 Chart 基本信息(例如版本和名称)的 YAML 文件。
  17. LICENSE # (可选)包含 Chart 许可证的纯文本文件。
  18. README.md # (可选)应用说明和使用指南。
  19. values.yaml # 该 Chart 的默认配置值。
  20. values.schema.json # (可选)向 values.yaml 文件添加结构的 JSON Schema。
  21. charts/ # 一个目录,包含该 Chart 所依赖的任意 Chart。
  22. crds/ # 定制资源定义。
  23. templates/ # 模板的目录,若提供相应值便可以生成有效的 Kubernetes 配置文件。
  24. templates/NOTES.txt # (可选)包含使用说明的纯文本文件。
  • Chart.yaml 用于描述这个 Chart的相关信息,包括名字、描述信息以及版本等。
  • values.yaml 用于存储 templates 目录中模板文件中用到变量的值。
  • NOTES.txt 用于介绍 Chart 部署后的一些信息,例如:如何使用这个 Chart、列出缺省的设置等。
  • Templates 目录下是 YAML 文件的模板,该模板文件遵循 Go template 语法。

    Chart.yaml 文件

    ```yaml apiVersion: (必需)Chart API 版本。 name: (必需)Chart 名称。 version: (必需)版本,遵循 SemVer 2 标准。 kubeVersion: (可选)兼容的 Kubernetes 版本,遵循 SemVer 2 标准。 description: (可选)对应用的一句话说明。 type: (可选)Chart 的类型。 keywords:
  • (可选)关于应用的关键字列表。 home: (可选)应用的 URL。 sources:
  • (可选)应用源代码的 URL 列表。 dependencies: (可选)Chart 必要条件的列表。
  • name: Chart 的名称,例如 nginx。 version: Chart 的版本,例如 “1.2.3”。 repository: 仓库 URL (“https://example.com/charts“) 或别名 (“@repo-name”)。 condition: (可选)解析为布尔值的 YAML 路径,用于启用/禁用 Chart (例如 subchart1.enabled)。 tags: (可选)
  • 用于将 Chart 分组,一同启用/禁用。 import-values: (可选)
  • ImportValues 保存源值到待导入父键的映射。每一项可以是字符串或者一对子/父子列表项。 alias: (可选)Chart 要使用的别名。当您要多次添加同一个 Chart 时,它会很有用。 maintainers: (可选)
  • name: (必需)维护者姓名。 email: (可选)维护者电子邮件。 url: (可选)维护者 URL。 icon: (可选)要用作图标的 SVG 或 PNG 图片的 URL。 appVersion: (可选)应用版本。不需要是 SemVer。 deprecated: (可选,布尔值)该 Chart 是否已被弃用。 annotations: example: (可选)按名称输入的注解列表。
  1. **Templates **目录下 YAML 文件模板的值默认都是在 values.yaml 里定义的<br />比如在 deployment.yaml 中定义的容器镜像` image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" `其中的 `.Values.image.repository `的值就是在 values.yaml 里定义的 nginx,.Values.image.tag 的值就是 stable
  2. ```shell
  3. $ cat helm-chart/values.yaml|grep repository
  4. repository: nginx
  5. $ cat helm-chart/values.yaml|grep tag
  6. tag: stable

以上两个变量值是在 create chart 的时候就自动生成的默认值,你可以根据实际情况进行修改。

编写应用的介绍信息

  1. apiVersion: v2
  2. name: mychart
  3. description: A Helm chart for Kubernetes
  4. type: application
  5. # This is the chart version. This version number should be incremented each time you make changes
  6. # to the chart and its templates, including the app version.
  7. version: 0.1.0
  8. # This is the version number of the application being deployed. This version number should be
  9. # incremented each time you make changes to the application.
  10. appVersion: 1.16.0

编写应用具体部署信息

  1. # Default values for mychart.
  2. # This is a YAML-formatted file.
  3. # Declare variables to be passed into your templates.
  4. replicaCount: 1
  5. image:
  6. repository: nginx
  7. pullPolicy: IfNotPresent
  8. imagePullSecrets: []
  9. nameOverride: ""
  10. fullnameOverride: ""
  11. serviceAccount:
  12. # Specifies whether a service account should be created
  13. create: true
  14. # Annotations to add to the service account
  15. annotations: {}
  16. # The name of the service account to use.
  17. # If not set and create is true, a name is generated using the fullname template
  18. name:
  19. podSecurityContext: {}
  20. # fsGroup: 2000
  21. securityContext: {}
  22. # capabilities:
  23. # drop:
  24. # - ALL
  25. # readOnlyRootFilesystem: true
  26. # runAsNonRoot: true
  27. # runAsUser: 1000
  28. service:
  29. type: ClusterIP
  30. port: 80
  31. ingress:
  32. enabled: false
  33. annotations: {}
  34. # kubernetes.io/ingress.class: nginx
  35. # kubernetes.io/tls-acme: "true"
  36. hosts:
  37. - host: chart-example.local
  38. paths: []
  39. tls: []
  40. # - secretName: chart-example-tls
  41. # hosts:
  42. # - chart-example.local
  43. resources: {}
  44. # We usually recommend not to specify default resources and to leave this as a conscious
  45. # choice for the user. This also increases chances charts run on environments with little
  46. # resources, such as Minikube. If you do want to specify resources, uncomment the following
  47. # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  48. # limits:
  49. # cpu: 100m
  50. # memory: 128Mi
  51. # requests:
  52. # cpu: 100m
  53. # memory: 128Mi
  54. nodeSelector: {}
  55. tolerations: []
  56. affinity: {}

检查依赖和模板配置是否正确

  1. $ helm lint mychart/
  2. ==> Linting mychart/
  3. [INFO] Chart.yaml: icon is recommended
  4. 1 chart(s) linted, 0 chart(s) failed

如果文件格式错误,可以根据提示进行修改。

将应用打包

  1. $ helm package mychart
  2. Successfully packaged chart and saved it to: /root/mychart-0.1.0.tgz

mychart 目录会被打包为一个 mychart-0.1.0.tgz 格式的压缩包,该压缩包会被放到当前目录下。如果你想看到更详细的输出,可以加上 —debug 参数来查看打包的输出。

离线部署

注意: ~/.kube/config不存在的情况下要用 helm —kubeconfig 指定配置文件

  1. # 方式一
  2. $ helm install demo-test ./mychart
  3. # 可根据不同的配置来install,默认是values.yaml
  4. # helm install demo-test ./mychart -f ./mychart/values-prod.yaml
  5. # 方式二
  6. $ helm install demo-test ./mychart-0.1.0.tgz
  7. $ helm list
  8. # 升级
  9. # $ helm upgrade demo-test ./mychart-0.2.0.tgz
  10. $ helm uninstall demo-test

将应用发布到 Repository

harbor1.6+ 支持存储 helm charts,这里使用 helm 安装 harbor
这里为了简化测试操作,我关闭了数据卷的挂载并使用的是 NodePort 方式进行访问。

  1. $ helm repo add goharbor https://helm.goharbor.io
  2. $ helm repo update
  3. # 查看harbor chart的各个版本
  4. $ helm search repo harbor -l
  5. # --version选择chart的版本
  6. $ helm install harbor goharbor/harbor --set persistence.enabled=false --set expose.type=nodePort --set expose.tls.enabled=false --set externalURL=http://10.13.84.187:30002
  7. #参数说明:
  8. - persistence.enabled=false 关闭存储,为了方便操作,真实使用时需要挂在存储
  9. - expose.type=nodePort 使用 NodePort 访问
  10. - expose.tls.enabled=false 关闭tls
  11. - externalURL=http://10.13.84.187:30002 设置登录 harbor 的外部链接,ip是某个node的ip

harbor 装好之后,我们访问 http://10.13.84.187:30002 进行登录 harbor, harbor 的默认账号密码是 admin/Harbor12345
新建一个项目 chart_repo; 新建一个用户test,密码Test1234,加入到项目的成员里面,并赋予权限

安装使用 helm-push 插件 helm plugin install [https://github.com/chartmuseum/helm-push](https://github.com/chartmuseum/helm-push)
超时没装成功,直接下载:

  1. $ mkdir ~/.local/share/helm/plugins/helm-push
  2. $ wget https://github.com/chartmuseum/helm-push/releases/download/v0.8.1/helm-push_0.8.1_linux_amd64.tar.gz
  3. $ tar -zxvf helm-push_0.8.1_linux_amd64.tar.gz -C ~/.local/share/helm/plugins/helm-push
  4. $ helm push --help

添加repo

  1. # helm repo add --ca-file <ca file> --cert-file <cert file> --key-file <key file> --username <username> --password <password> <repo name> http://10.13.84.187:30002/chartrepo/chart_repo
  2. $ helm repo add myrepo http://10.13.84.187:30002/chartrepo/chart_repo

push chart

  1. $ helm push mychart/ myrepo -u test -p Test1234
  2. Pushing mychart-0.1.0.tgz to myrepo...
  3. Done.

查找chart

  1. $ helm repo update
  2. $ helm search repo mychart
  3. NAME CHART VERSION APP VERSION DESCRIPTION
  4. myrepo/mychart 0.1.0 1.16.0 A Helm chart for Kubernetes

部署应用

注意: ~/.kube/config不存在的情况下要用 helm —kubeconfig 指定配置文件

  1. # helm install --ca-file <ca file> --cert-file <cert file> --key-file <key file> --username=<username> --password=<password> --version 0.2.0 <repo name>/mychart
  2. # 在部署前使用 --dry-run 参数验证 Chart 的配置
  3. $ helm install demo-test --dry-run --debug myrepo/mychart
  4. # 没问题就install
  5. $ helm install demo-test myrepo/mychart
  6. NAME: demo-test
  7. LAST DEPLOYED: Tue Apr 21 11:06:27 2020
  8. NAMESPACE: default
  9. STATUS: deployed
  10. REVISION: 1
  11. NOTES:
  12. 1. Get the application URL by running these commands:
  13. export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=demo-test" -o jsonpath="{.items[0].metadata.name}")
  14. echo "Visit http://127.0.0.1:8080 to use your application"
  15. kubectl --namespace default port-forward $POD_NAME 8080:80

测试访问:

  1. export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=demo-test" -o jsonpath="{.items[0].metadata.name}")
  2. echo "Visit http://127.0.0.1:8080 to use your application"
  3. kubectl --namespace default port-forward $POD_NAME 8080:80
  4. #访问nginx
  5. curl http://127.0.0.1:8080

使用下面的命令列出的所有已部署的 Release 以及其对应的 Chart。

  1. $ helm list
  2. NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
  3. demo-test default 1 2020-04-21 11:06:27.672714497 +0800 CST deployed mychart-0.1.0 1.16.0

从上面 helm list 输出的结果中我们可以看到有一个 REVISION(更改历史)字段,该字段用于表示某一个 Release 被更新的次数,我们可以用该特性对已部署的 Release 进行回滚。

查看状态

  1. $ helm status demo-test
  2. NAME: demo-test
  3. LAST DEPLOYED: Tue Apr 21 11:06:27 2020
  4. NAMESPACE: default
  5. STATUS: deployed
  6. REVISION: 1
  7. NOTES:
  8. 1. Get the application URL by running these commands:
  9. export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=demo-test" -o jsonpath="{.items[0].metadata.name}")
  10. echo "Visit http://127.0.0.1:8080 to use your application"
  11. kubectl --namespace default port-forward $POD_NAME 8080:80

升级应用

修改 mychart/Chart.yaml 文件

  1. apiVersion: v2
  2. name: mychart
  3. description: A Helm chart for Kubernetes
  4. type: application
  5. # 改了下面两行
  6. version: 0.2.0
  7. appVersion: 1.17.0

上传chart

  1. $ helm push mychart/ myrepo -u test -p Test1234
  2. Pushing mychart-0.2.0.tgz to myrepo...
  3. Done.
  4. $ helm repo udpate
  5. $ helm search repo mychart -l
  6. NAME CHART VERSION APP VERSION DESCRIPTION
  7. myrepo/mychart 0.2.0 1.17.0 A Helm chart for Kubernetes
  8. myrepo/mychart 0.1.0 1.16.0 A Helm chart for Kubernetes

现在用helm upgrade 命令将已部署的 demo-test 升级到新版本。你可以通过--version 参数指定需要升级的版本号,如果没有指定版本号,则缺省使用最新版本。

  1. $ helm upgrade demo-test myrepo/mychart
  2. Release "demo-test" has been upgraded. Happy Helming!
  3. NAME: demo-test
  4. LAST DEPLOYED: Tue Apr 21 11:33:12 2020
  5. NAMESPACE: default
  6. STATUS: deployed
  7. REVISION: 2
  8. NOTES:
  9. 1. Get the application URL by running these commands:
  10. export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=demo-test" -o jsonpath="{.items[0].metadata.name}")
  11. echo "Visit http://127.0.0.1:8080 to use your application"
  12. kubectl --namespace default port-forward $POD_NAME 8080:80
  13. $ helm list
  14. NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
  15. demo-test default 2 2020-04-21 11:33:12.376727722 +0800 CST deployed mychart-0.2.0 1.17.0

完成后,可以看到已部署的 demo-test 被升级到chart的 0.2.0 版本。

回退应用

如果更新后的程序由于某些原因运行有问题,需要回退到旧版本的应用。可以使用 helm history 命令查看一个 Release 的所有变更记录

  1. $ helm history demo-test
  2. REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
  3. 1 Tue Apr 21 11:06:27 2020 superseded mychart-0.1.0 1.16.0 Install complete
  4. 2 Tue Apr 21 11:33:12 2020 deployed mychart-0.2.0 1.17.0 Upgrade complete

其次,我们可以使用下面的命令对指定的应用进行回退。

  1. $ helm rollback demo-test 1
  2. Rollback was a success! Happy Helming!

注:其中的参数 1 是 helm history 查看到 Release 的历史记录中 REVISION 对应的值。

  1. $ helm list
  2. NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
  3. demo-test default 3 2020-04-21 11:40:50.782129072 +0800 CST deployed mychart-0.1.0 1.16.0
  4. $ helm history demo-test
  5. REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
  6. 1 Tue Apr 21 11:06:27 2020 superseded mychart-0.1.0 1.16.0 Install complete
  7. 2 Tue Apr 21 11:33:12 2020 superseded mychart-0.2.0 1.17.0 Upgrade complete
  8. 3 Tue Apr 21 11:40:50 2020 deployed mychart-0.1.0 1.16.0 Rollback to 1

删除应用

  1. helm uninstall demo-test

参考: