├── .gitignore ├── Makefile ├── README.md ├── SUMMARY.md ├── architecture-zh_cn.md ├── book.json ├── chart ├── chart_repository-zh_cn.md ├── chart_repository_faq-zh_cn.md ├── chart_repository_sync_example-zh_cn.md ├── chart_tests-zh_cn.md ├── charts-zh_cn.md ├── charts_hooks-zh_cn.md ├── charts_tips_and_tricks-zh_cn.md └── provenance-zh_cn.md ├── chart_best_practices ├── README-zh_cn.md ├── conventions-zh_cn.md ├── custom_resource_definitions-zh_cn.md ├── labels-zh_cn.md ├── pods-zh_cn.md ├── rbac-zh_cn.md ├── requirements-zh_cn.md ├── templates-zh_cn.md └── values-zh_cn.md ├── chart_template_guide ├── accessing_files-zh_cn.md ├── builtin_objects-zh_cn.md ├── control_structures-zh_cn.md ├── data_types-zh_cn.md ├── debugging-zh_cn.md ├── functions_and_pipelines-zh_cn.md ├── getting_started-zh_cn.md ├── helm_ignore_file-zh_cn.md ├── index-zh_cn.md ├── named_templates-zh_cn.md ├── notes_files-zh_cn.md ├── subcharts_and_globals-zh_cn.md ├── values_files-zh_cn.md ├── variables-zh_cn.md ├── wrapping_up-zh_cn.md └── yaml_techniques-zh_cn.md ├── content.md ├── cover.jpg ├── developers-zh_cn.md ├── glossary-zh_cn.md ├── history-zh_cn.md ├── images ├── create-a-bucket.png ├── create-a-gh-page-button.png ├── edit-permissions.png ├── make-bucket-public.png ├── nothing.png └── set-a-gh-page.png ├── quickstart ├── install-zh_cn.md ├── install_faq-zh_cn.md ├── kubernetes_distros-zh_cn.md ├── plugins-zh_cn.md ├── quickstart-zh_cn.md ├── rbac-zh_cn.md ├── securing_installation-zh_cn.md ├── tiller_ssl-zh_cn.md └── using_helm-zh_cn.md ├── related-zh_cn.md └── release_checklist-zh-cn.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Node rules: 2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 3 | .grunt 4 | 5 | ## Dependency directory 6 | ## Commenting this out is preferred by some people, see 7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 8 | node_modules 9 | 10 | # Book build output 11 | _book 12 | 13 | # eBook build output 14 | *.epub 15 | *.mobi 16 | *.pdf 17 | 18 | # Github Pages 19 | deploy.sh 20 | .DS_Store 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | BOOK_NAME := "Helm User and Developer's Guide" 3 | BOOK_OUTPUT := _book 4 | 5 | .PHONY: build 6 | build: 7 | gitbook build . $(BOOK_OUTPUT) 8 | 9 | .PHONY: serve 10 | serve: 11 | gitbook serve . $(BOOK_OUTPUT) 12 | 13 | .PHONY: epub 14 | epub: 15 | gitbook epub . $(BOOK_NAME).epub 16 | 17 | .PHONY: pdf 18 | pdf: 19 | gitbook pdf . $(BOOK_NAME).pdf 20 | 21 | .PHONY: mobi 22 | mobi: 23 | gitbook mobi . $(BOOK_NAME).pdf 24 | 25 | .PHONY: install 26 | install: 27 | npm install gitbook-cli -g 28 | gitbook install 29 | 30 | .PHONY: clean 31 | clean: 32 | rm -rf $(BOOK_OUTPUT) 33 | 34 | .PHONY: help 35 | help: 36 | @echo "Help for make" 37 | @echo "make - Build the book" 38 | @echo "make build - Build the book" 39 | @echo "make serve - Serving the book on localhost:4000" 40 | @echo "make install - Install gitbook and plugins" 41 | @echo "make epub - Build epub book" 42 | @echo "make pdf - Build pdf book" 43 | @echo "make clean - Remove generated files" 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Helm User and Developer's Guide - Helm 用户与开发者指南 2 | 3 | 本指南是官方 Kubernetes 的 github 库下,helm 子目录下的文档的翻译,依照 https://docs.helm.sh/ 的文档架构和组织,当前非常粗糙的翻译了一版(剩余命令参考和术语表两部分还没有翻译),后续会陆续更新优化,用于给刚接触 Helm 这个工具的朋友一个参考。 4 | 5 | 备注:(如果有朋友知道如何更好的在 gitbook 里面处理花括弧 - 模板里的值引用,欢迎告知我)!! 6 | 7 | 电子书下载链接 https://github.com/whmzsu/helm-doc-zh-cn/releases 8 | 9 | # 目录 10 | 11 | ### 前言 12 | 13 | - [序言](README.md) 14 | 15 | ### 用户指南 16 | 17 | - [快速入门](quickstart/quickstart-zh_cn.md) 18 | - [安装](quickstart/install-zh_cn.md) 19 | - [Kubernetes 各发行版 Helm](quickstart/kubernetes_distros-zh_cn.md) 20 | - [安装 FAQ](quickstart/install_faq-zh_cn.md) 21 | - [使用](quickstart/using_helm-zh_cn.md) 22 | - [插件](quickstart/plugins-zh_cn.md) 23 | - [RBAC](quickstart/rbac-zh_cn.md) 24 | - [使用 SSL](quickstart/tiller_ssl-zh_cn.md) 25 | - [安全安装](quickstart/securing_installation-zh_cn.md) 26 | 27 | ### Helm 命令参考 28 | ### Charts 29 | 30 | - [Charts](chart/charts-zh_cn.md) 31 | - [Hooks](chart/charts_hooks-zh_cn.md) 32 | - [提示和技巧](chart/charts_tips_and_tricks-zh_cn.md) 33 | - [存储库 repository](chart/chart_repository-zh_cn.md) 34 | - [同步 repository](chart/chart_repository_sync_example-zh_cn.md) 35 | - [验证出处和完整性](chart/provenance-zh_cn.md) 36 | - [测试](chart/chart_tests-zh_cn.md) 37 | - [Repository FAQ](chart/chart_repository_faq-zh_cn.md) 38 | 39 | ### 开发 chart 模板 40 | 41 | - [介绍](chart_template_guide/index-zh_cn.md) 42 | - [入门](chart_template_guide/getting_started-zh_cn.md) 43 | - [内置对象](chart_template_guide/builtin_objects-zh_cn.md) 44 | - [Values 文件](chart_template_guide/values_files-zh_cn.md) 45 | - [函数和管道](chart_template_guide/functions_and_pipelines-zh_cn.md) 46 | - [控制结构](chart_template_guide/control_structures-zh_cn.md) 47 | - [变量](chart_template_guide/variables-zh_cn.md) 48 | - [命名模板](chart_template_guide/named_templates-zh_cn.md) 49 | - [访问文件](chart_template_guide/accessing_files-zh_cn.md) 50 | - [忽略不需要的文件和文件夹](chart_template_guide/helm_ignore_file-zh_cn.md) 51 | - [notes 文件](chart_template_guide/notes_files-zh_cn.md) 52 | - [子 chart 和全局值](chart_template_guide/subcharts_and_globals-zh_cn.md) 53 | - [调试模板](chart_template_guide/debugging-zh_cn.md) 54 | - [总结](chart_template_guide/wrapping_up-zh_cn.md) 55 | - [附录 1:Yaml 技巧](chart_template_guide/yaml_techniques-zh_cn.md) 56 | - [附录 2:数据类型](chart_template_guide/data_types-zh_cn.md) 57 | 58 | ### chart 最佳实践 59 | - [介绍](chart_best_practices/README-zh_cn.md) 60 | - [通用约定](chart_best_practices/conventions-zh_cn.md) 61 | - [Values](chart_best_practices/values-zh_cn.md) 62 | - [Templates](chart_best_practices/templates-zh_cn.md) 63 | - [Requirements](chart_best_practices/requirements-zh_cn.md) 64 | - [Labels 和 Annotations](chart_best_practices/labels-zh_cn.md) 65 | - [Pods 和 PodTemplates](chart_best_practices/pods-zh_cn.md) 66 | - [资源定义定制](chart_best_practices/custom_resource_definitions-zh_cn.md) 67 | - [RBAC](chart_best_practices/rbac-zh_cn.md) 68 | 69 | ### 相关项目和文档 70 | - [相关项目和文档](related-zh_cn.md) 71 | 72 | ### Kubernetes Helm 架构 73 | - [Kubernetes Helm 架构](architecture-zh_cn.md) 74 | 75 | ### 开发者指南 76 | - [开发者指南](developers-zh_cn.md) 77 | 78 | ### 项目历史 79 | - [项目历史](history-zh_cn.md) 80 | 81 | ### 术语表 82 | - [术语表](glossary-zh_cn.md) 83 | 84 | ### [何处寻找 Charts](https://hub.kubeapps.com/) 85 | 86 | ### Helm 版本发布 checklist 87 | - [版本发布checklist](release_checklist-zh-cn.md) 88 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # 目录 2 | 3 | ### 前言 4 | 5 | - [序言](README.md) 6 | 7 | ### 用户指南 8 | 9 | - [快速入门](quickstart/quickstart-zh_cn.md) 10 | - [安装](quickstart/install-zh_cn.md) 11 | - [Kubernetes 各发行版 Helm](quickstart/kubernetes_distros-zh_cn.md) 12 | - [安装 FAQ](quickstart/install_faq-zh_cn.md) 13 | - [使用](quickstart/using_helm-zh_cn.md) 14 | - [插件](quickstart/plugins-zh_cn.md) 15 | - [RBAC](quickstart/rbac-zh_cn.md) 16 | - [使用 SSL](quickstart/tiller_ssl-zh_cn.md) 17 | - [安全安装](quickstart/securing_installation-zh_cn.md) 18 | 19 | ### Helm 命令参考 20 | ### Charts 21 | 22 | - [Charts](chart/charts-zh_cn.md) 23 | - [Hooks](chart/charts_hooks-zh_cn.md) 24 | - [提示和技巧](chart/charts_tips_and_tricks-zh_cn.md) 25 | - [存储库 repository](chart/chart_repository-zh_cn.md) 26 | - [同步 repository](chart/chart_repository_sync_example-zh_cn.md) 27 | - [验证出处和完整性](chart/provenance-zh_cn.md) 28 | - [测试](chart/chart_tests-zh_cn.md) 29 | - [Repository FAQ](chart/chart_repository_faq-zh_cn.md) 30 | 31 | ### 开发 chart 模板 32 | 33 | - [介绍](chart_template_guide/index-zh_cn.md) 34 | - [入门](chart_template_guide/getting_started-zh_cn.md) 35 | - [内置对象](chart_template_guide/builtin_objects-zh_cn.md) 36 | - [Values 文件](chart_template_guide/values_files-zh_cn.md) 37 | - [函数和管道](chart_template_guide/functions_and_pipelines-zh_cn.md) 38 | - [控制结构](chart_template_guide/control_structures-zh_cn.md) 39 | - [变量](chart_template_guide/variables-zh_cn.md) 40 | - [命名模板](chart_template_guide/named_templates-zh_cn.md) 41 | - [访问文件](chart_template_guide/accessing_files-zh_cn.md) 42 | - [忽略不需要的文件和文件夹](chart_template_guide/helm_ignore_file-zh_cn.md) 43 | - [notes 文件](chart_template_guide/notes_files-zh_cn.md) 44 | - [子 chart 和全局值](chart_template_guide/subcharts_and_globals-zh_cn.md) 45 | - [调试模板](chart_template_guide/debugging-zh_cn.md) 46 | - [总结](chart_template_guide/wrapping_up-zh_cn.md) 47 | - [附录 1:Yaml 技巧](chart_template_guide/yaml_techniques-zh_cn.md) 48 | - [附录 2:数据类型](chart_template_guide/data_types-zh_cn.md) 49 | 50 | ### chart 最佳实践 51 | - [介绍](chart_best_practices/README-zh_cn.md) 52 | - [通用约定](chart_best_practices/conventions-zh_cn.md) 53 | - [Values](chart_best_practices/values-zh_cn.md) 54 | - [Templates](chart_best_practices/templates-zh_cn.md) 55 | - [Requirements](chart_best_practices/requirements-zh_cn.md) 56 | - [Labels 和 Annotations](chart_best_practices/labels-zh_cn.md) 57 | - [Pods 和 PodTemplates](chart_best_practices/pods-zh_cn.md) 58 | - [资源定义定制](chart_best_practices/custom_resource_definitions-zh_cn.md) 59 | - [RBAC](chart_best_practices/rbac-zh_cn.md) 60 | 61 | ### 相关项目和文档 62 | - [相关项目和文档](related-zh_cn.md) 63 | 64 | ### Kubernetes Helm 架构 65 | - [Kubernetes Helm 架构](architecture-zh_cn.md) 66 | 67 | ### 开发者指南 68 | - [开发者指南](developers-zh_cn.md) 69 | 70 | ### 项目历史 71 | - [项目历史](history-zh_cn.md) 72 | 73 | ### 术语表 74 | - [术语表](glossary-zh_cn.md) 75 | 76 | ### [何处寻找 Charts](https://hub.kubeapps.com/) 77 | 78 | ### Helm 版本发布 checklist 79 | - [版本发布checklist](release_checklist-zh-cn.md) 80 | -------------------------------------------------------------------------------- /architecture-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Helm 架构 2 | 3 | 本文档介绍了 Helm 高层次体系结构。 4 | 5 | ## Helm 的目的 6 | Helm 是管理称为 chart 的 Kubernetes 包的工具。Helm 可以做到以下几点: 7 | 8 | - 从头开始创建新 chart 9 | - 将 chart 打包成 chart 归档(tgz)文件 10 | - 与存储 chart 的 chart 存储库交互 11 | - 安装或卸载 chart 到现有的 Kubernetes 集群中 12 | - 管理用 Helm 安装的 chart 的 release 周期 13 | 14 | 对于 Helm,有三个重要的概念: 15 | 16 | - chart 是创建 Kubernetes 应用程序实例所需的一系列信息。 17 | - 配置包含可以合并到打包 chart 以创建可发布对象的配置信息。 18 | - Release 是一个的运行实例的 chart,具有特定的组合配置。 19 | 20 | ## 组件 21 | Helm 有两个主要部分: 22 | 23 | Helm Client 是最终用户的命令行客户端。客户端负责以下部分: 24 | 25 | - 本地 chart 开发 26 | - 管理存储库 27 | - 与 Tiller 服务交互 28 | - 发送要安装的 chart 29 | - 查询有关发布的信息 30 | - 请求升级或卸载现有 release 31 | 32 | **Tiller Server** 是一个集群内服务,与 Helm 客户端进行交互,并与 Kubernetes API 服务进行交互。服务负责以下内容: 33 | 34 | - 监听来自 Helm 客户端的传入请求 35 | - 结合 chart 和配置来构建发布 36 | - 将 chart 安装到 Kubernetes 中,然后跟踪后续 release 37 | - 通过与 Kubernetes 交互来升级和卸载 chart 38 | 39 | 简而言之,客户端负责管理 chart,而服务端负责管理 release。 40 | 41 | ## 部署 42 | 43 | Helm 客户端使用 Go 编程语言编写,并使用 gRPC 协议套件与 Tiller 服务进行交互。 44 | 45 | Tiller 服务也用 Go 编写。它提供了一个与客户端连接的 gRPC 服务,它使用 Kubernetes 客户端库与 Kubernetes 进行通信。目前,该库使用 REST + JSON。 46 | 47 | Tiller 服务将信息存储在位于 Kubernetes 内的 ConfigMaps 中。它不需要自己的数据库。 48 | 49 | 如有可能,配置文件用YAML编写。 50 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Helm用户与开发者指南", 3 | "description": "Helm用户与开发者指南|Helm User and Developer's Guide|Mingo|吴洪明", 4 | "language": "zh-hans", 5 | "author": "Mingo", 6 | "plugins": [ 7 | "github", 8 | "codesnippet", 9 | "splitter", 10 | "page-toc-button", 11 | "image-captions", 12 | "3-ba", 13 | "editlink", 14 | "back-to-top-button", 15 | "-lunr", "-search", "search-plus", 16 | "github-buttons@2.1.0", 17 | "favicon@^0.0.2", 18 | "tbfed-pagefooter@^0.0.1", 19 | "theme-default", 20 | "-highlight", "prism", "prism-themes" 21 | ], 22 | "pluginsConfig": { 23 | "3-ba": { 24 | "token": "4c047edc6924037f9f149230b592da80" 25 | }, 26 | "theme-default": { 27 | "showLevel": true 28 | }, 29 | "image-captions": { 30 | "caption": "图片 - _CAPTION_" 31 | }, 32 | "github-buttons": { 33 | "repo": "whmzsu/helm-doc-zh-cn", 34 | "types": ["star"], 35 | "size": "small" 36 | }, 37 | "github": { 38 | "url": "https://github.com/whmzsu/helm-doc-zh-cn" 39 | }, 40 | "editlink": { 41 | "base": "https://github.com/whmzsu/helm-doc-zh-cn/blob/master/", 42 | "label": "编辑本页", 43 | "multilingual": false 44 | }, 45 | "tbfed-pagefooter": { 46 | "copyright": "Copyright © Mingo(whmzsu@gmail.com) 2017-2018", 47 | "modify_label": "Updated at ", 48 | "modify_format": "YYYY-MM-DD HH:mm:ss" 49 | }, 50 | "favicon": { 51 | "shortcut": "favicon.ico", 52 | "bookmark": "favicon.ico" 53 | }, 54 | "prism": { 55 | "css": [ 56 | "prism-themes/themes/prism-ghcolors.css" 57 | ] 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /chart/chart_repository-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Chart Repository 存储库指南 2 | 3 | 本节介绍如何创建和使用 Helm chart repo。在高层次上,chart 库是可以存储和共享打包 chart 的位置。 4 | 5 | 官方 chart 库由 [Helm Charts](https://github.com/helm/charts) 维护 ,我们欢迎参与贡献。Helm 还可以轻松创建和运行自己的 chart 库。本指南讲解了如何做到这一点。 6 | 7 | ## 前提条件 8 | 9 | * 阅读快速入门指南 [Quickstart](quickstart.md) 10 | * 通读 chart 文件 [Charts](charts.md) 11 | 12 | ## 创建 chart 库 13 | 14 | chart 库是带有一个 index.yaml 文件和任意个打包 chart 的 HTTP 服务器。当准备好分享 chart 时,首选方法是将其上传到 chart 库。 15 | 16 | ** 注意:** 对于 Helm 2.0.0,chart 库没有任何内部认证。 在 GitHub 中有一个跟踪进度的问题 [issue tracking progress](https://github.com/helm/issues/1038)。 17 | 18 | 由于 chart 库可以是任何可以提供 YAML 和 tar 文件并可以回答 GET 请求的 HTTP 服务器,因此当托管自己的 chart 库时,很多选择。例如,可以使用 Google 云端存储(GCS)存储桶,Amazon S3 存储桶,Github Pages,甚至可以创建自己的 Web 服务器。 19 | 20 | ### chart 库结构 21 | 22 | chart 库由打包的 chart 和一个名为的特殊文件组成, index.yaml 其中包含 chart 库中所有 chart 的索引。通常,index.yaml 描述的 chart 也是托管在同一台服务器上,源代码文件也是如此。 23 | 24 | 例如,chart 库的布局 https://example.com/charts 可能如下所示: 25 | 26 | ``` 27 | charts/ 28 | | 29 | |- index.yaml 30 | | 31 | |- alpine-0.1.2.tgz 32 | | 33 | |- alpine-0.1.2.tgz.prov 34 | ``` 35 | 36 | 这种情况下,索引文件包含有关一个 chart(Alpine chart)的信息,并提供该 chart 的下载 URL `https://example.com/charts/alpine-0.1.2.tgz`。 37 | 38 | 不要求 chart 包与 index.yaml 文件位于同一台服务器上 。但是,放在一起这样做通常是最简单的。 39 | 40 | ### 索引文件 41 | 索引文件是一个叫做 yaml 文件 index.yaml。它包含一些关于包的元数据,包括 chart 的 Chart.yaml 文件的内容。一个有效的 chart 库必须有一个索引文件。索引文件包含有关 chart 库中每个 chart 的信息。`helm repo index` 命令将根据包含打包的 chart 的给定本地目录生成索引文件。 42 | 43 | 下面一个索引文件的例子: 44 | 45 | ``` 46 | apiVersion: v1 47 | entries: 48 | alpine: 49 | - created: 2016-10-06T16:23:20.499814565-06:00 50 | description: Deploy a basic Alpine Linux pod 51 | digest: 99c76e403d752c84ead610644d4b1c2f2b453a74b921f422b9dcb8a7c8b559cd 52 | home: https://k8s.io/helm 53 | name: alpine 54 | sources: 55 | - https://github.com/helm 56 | urls: 57 | - https://technosophos.github.io/tscharts/alpine-0.2.0.tgz 58 | version: 0.2.0 59 | - created: 2016-10-06T16:23:20.499543808-06:00 60 | description: Deploy a basic Alpine Linux pod 61 | digest: 515c58e5f79d8b2913a10cb400ebb6fa9c77fe813287afbacf1a0b897cd78727 62 | home: https://k8s.io/helm 63 | name: alpine 64 | sources: 65 | - https://github.com/helm 66 | urls: 67 | - https://technosophos.github.io/tscharts/alpine-0.1.0.tgz 68 | version: 0.1.0 69 | nginx: 70 | - created: 2016-10-06T16:23:20.499543808-06:00 71 | description: Create a basic nginx HTTP server 72 | digest: aaff4545f79d8b2913a10cb400ebb6fa9c77fe813287afbacf1a0b897cdffffff 73 | home: https://k8s.io/helm 74 | name: nginx 75 | sources: 76 | - https://github.com/helm/charts 77 | urls: 78 | - https://technosophos.github.io/tscharts/nginx-1.1.0.tgz 79 | version: 1.1.0 80 | generated: 2016-10-06T16:23:20.499029981-06:00 81 | ``` 82 | 83 | 生成的索引和包可以从基本的网络服务器提供。可以使用 helm serve 启动本地服务器,在本地测试所有内容。 84 | 85 | ```bash 86 | $ helm serve --repo-path ./charts 87 | Regenerating index. This may take a moment. 88 | Now serving you on 127.0.0.1:8879 89 | ``` 90 | 91 | 上面启动了一个本地 web 服务器,为它在 `./charts` 目录找到的 chart 提供服务。serve 命令将在启动过程中自动生成一个 `index.yaml` 文件。 92 | 93 | ## 托管 chart 库 94 | 95 | 本部分介绍了提供 chart 库的几种方法。 96 | 97 | ### ChartMuseum 98 | 99 | Helm 提供了一个 open-source Helm 库服务叫 [ChartMuseum](https://chartmuseum.com) ,你可以自己托管这个服务. 100 | 101 | ChartMuseum 支撑多种云存储后端. 配置它指向你存放 chart 包的目录或者 bucket,index.yaml 文件会自动动态生成。 102 | 103 | 它也可以通过 [Helm chart](https://github.com/helm/charts/tree/master/stable/chartmuseum) 部署: 104 | ``` 105 | helm install stable/chartmuseum 106 | ``` 107 | 108 | 或者 [Docker image](https://hub.docker.com/r/chartmuseum/chartmuseum/tags): 109 | ``` 110 | docker run --rm -it \ 111 | -p 8080:8080 \ 112 | -v $(pwd)/charts:/charts \ 113 | -e DEBUG=true \ 114 | -e STORAGE=local \ 115 | -e STORAGE_LOCAL_ROOTDIR=/charts \ 116 | chartmuseum/chartmuseum 117 | ``` 118 | 119 | 你可以将它加到本地存储库: 120 | ``` 121 | helm repo add chartmuseum http://localhost:8080 122 | ``` 123 | 124 | ChartMuseum 提供其他特性, 如 chart 上传的 API. 查看更多信息 [README](https://github.com/helm/chartmuseum). 125 | 126 | 127 | ### Google 云端存储 128 | 129 | 第一步是创建 GCS 存储桶。我们会给我们称之为 `fantastic-charts`。 130 | 131 | 创建一个 GCS 桶 132 | 133 | ![Create a GCS Bucket](../images/create-a-bucket.png) 134 | 135 | 接下来,通过 ** 编辑存储桶权限 ** 使存储桶公开。 136 | 137 | 编辑权限 138 | 139 | ![Edit Permissions](../images/edit-permissions.png) 140 | 141 | 插入此行 item 来 ** 公开存储 bucket**: 142 | 143 | 开放 Bucket 144 | 145 | ![Make Bucket Public](../images/make-bucket-public.png) 146 | 147 | 恭喜,现在你有一个空的 GCS bucket 准备好给 chart 提供服务! 148 | 149 | 可以使用 Google Cloud Storage 命令行工具或使用 GCS Web UI 上传 chart 库。这是官方 Kubernetes Charts 存储库托管其 chart 的技术,因此如果遇到困难,可能需要查看该项目 [peek at that project](https://github.com/helm/charts) 。 150 | 151 | ** 注意:** 可以通过此处的 HTTPS 地址方便的访问公开的 GCS 存储桶 `https://bucket-name.storage.googleapis.com/`。 152 | 153 | ### JFrog Artifactory 154 | 155 | 还可以使用 JFrog Artifactory 来设置 chart 库。在 [此处](https://www.jfrog.com/confluence/display/RTF/Helm+Chart+Repositories) 阅读更多关于 JFrog Artifactory 和 chart 库的信息 156 | 157 | ### Github Pages 示例 158 | 159 | 以类似的方式,可以使用 GitHub Pages 创建 chart 库。 160 | 161 | GitHub 允许两种不同的方式提供静态网页: 162 | 163 | - 通过配置一个项目来提供其 `docs/`` 目录的内容 164 | - 通过配置一个项目来为特定分支提供服务 165 | 166 | 我们会采取第二种方法,尽管第一种方法很简单。 167 | 168 | 第一步是创建你的 gh-pages 分支。可以在本地做到这一点。 169 | 170 | ```bash 171 | $ git checkout -b gh-pages 172 | ``` 173 | 174 | 或者通过使用网络浏览器在 Github 存储库上的分支按钮: 175 | 176 | ![Create Github Pages branch](../images/create-a-gh-page-button.png) 177 | 178 | 接下来,需要确保 gh-pages 分支设置为 Github Pages,点击 repo Settings 并向下滚动到 Github Pages 部分并按照以下设置: 179 | 180 | ![Create Github Pages branch](../images/set-a-gh-page.png) 181 | 182 | 183 | 默认情况下,源通常设置为 gh-pages 分支。如果这不是默认设置,那么请选择 gh-pages。 184 | 185 | 也可以在那里使用自定义域名。 186 | 187 | 并检查是否勾选了强制使用 HTTPS,以便在提供 chart 时使用 HTTPS。 188 | 189 | 这样的设置中,可以使用 master 分支来存储 chart 代码,并将 gh-pages 分支作为 chart 库,例如: `https://USERNAME.github.io/REPONAME`。演示 [TS Charts](https://github.com/technosophos/tscharts) 库可以通过 `https://technosophos.github.io/tscharts/` 访问。 190 | 191 | ### 普通的 web 服务器 192 | 193 | 要配置普通 Web 服务器来服务 Helm chart,只需执行以下操作: 194 | 195 | - 将索引和 chart 置于服务器目录中 196 | - 确保 `index.yaml` 可以在没有认证要求的情况下访问 197 | - 确保 `yaml` 文件的正确内容类型(`text/yaml` 或 `text/x-yaml`) 198 | 199 | 例如,如果想在 `$WEBROOT/charts` 以外的目录为 chart 提供服务,请确保 Web 根目录中有一个 `charts/` 目录,并将索引文件和 chart 放入该文件夹内。 200 | 201 | ## 管理 chart 库 202 | 现在已有一个 chart 存储库,本指南的最后一部分将介绍如何维护该库中的 chart。 203 | 204 | ### 将 chart 存储在 chart 库中 205 | 206 | 现在已有一个 chart 存储库,让我们上传一个 chart 和一个索引文件到存储库。chart 库中的 chart 必须正确打包(`helm package chart-name/`)和版本(遵循 [SemVer 2](https://semver.org/) 标准)。 207 | 208 | 接下来的这些步骤是一个示例工作流程,也可以用你喜欢的任何工作流程来存储和更新 chart 库中的 chart。 209 | 210 | 准备好打包 chart 后,创建一个新目录,并将打包 chart 移动到该目录。 211 | 212 | ```bash 213 | $ helm package docs/examples/alpine/ 214 | $ mkdir fantastic-charts 215 | $ mv alpine-0.1.0.tgz fantastic-charts/ 216 | $ helm repo index fantastic-charts --url https://fantastic-charts.storage.googleapis.com 217 | ``` 218 | 219 | 最后一条命令采用刚创建的本地目录的路径和远程 chart 库的 URL,并在给定的目录路径中生成 `index.yaml`。 220 | 221 | 现在可以使用同步工具或手动将 chart 和索引文件上传到 chart 库。如果使用 Google 云端存储,请使用 gsutil 客户端查看此示例工作流程。对于 GitHub,可以简单地将 chart 放入适当的目标分支中。 222 | 223 | ### 新添加 chart 添加到现有存储库 224 | 225 | 每次将新 chart 添加到存储库时,都必须重新生成索引。`helm repo index` 命令将 `index.yaml` 从头开始完全重建该文件,但仅包括它在本地找到的 chart。 226 | 227 | 可以使用 `--merge` 标志向现有 `index.yaml` 文件增量添加新 chart(在使用远程存储库(如 GCS)时,这是一个很好的选择)。运行 `helm repo index --help` 以了解更多信息, 228 | 229 | 确保上传修改后的 index.yaml 文件和 chart。如果生成了出处 provenance 文件,也要上传。 230 | 231 | ### 与他人分享 chart 232 | 233 | 准备好分享 chart 时,只需让别人知道存储库的 URL 是什么就可以了。 234 | 235 | 他们将通过 `helm repo add [NAME] [URL]` 命令将仓库添加到他们的 helm 客户端,并可以起一个带有任何想用来引用仓库的名字。 236 | 237 | ```bash 238 | $ helm repo add fantastic-charts https://fantastic-charts.storage.googleapis.com 239 | $ helm repo list 240 | fantastic-charts https://fantastic-charts.storage.googleapis.com 241 | ``` 242 | 243 | 如果 chart 由 HTTP 基本认证支持,也可以在此处提供用户名和密码: 244 | 245 | ```bash 246 | $ helm repo add fantastic-charts https://fantastic-charts.storage.googleapis.com --username my-username --password my-password 247 | $ helm repo list 248 | fantastic-charts https://fantastic-charts.storage.googleapis.com 249 | ``` 250 | 251 | ** 注意:** 如果存储库不包含有效信息库 `index.yaml` 文件,则添加不会成功。 252 | 253 | 之后,用户将能够搜索 chart。更新存储库后,他们可以使用该 helm repo update 命令获取最新的 chart 信息。 254 | 255 | 原理是`helm repo add`和`helm repo update`命令获取index.yaml文件并将它们存储在 `$HELM_HOME/repository/cache/`目录中。这是helm search 找到有关chart的信息的地方。 256 | -------------------------------------------------------------------------------- /chart/chart_repository_faq-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Chart 库:常见问题 2 | 3 | 本节跟踪使用 chart 库时的一些常遇到的问题。 4 | 5 | 我们很欢迎你的帮助来改进这个文档。要添加,更正或删除信息,提出问题[file an issue](https://github.com/helm/helm/issues)或向我们发送 PR。 6 | 7 | ## Fetching 8 | 9 | ** 问:当我试图从我的自定义 repo 中获取 chart 时,为什么会出现错误 `unsupported protocol scheme` ?** 10 | 11 | 答:(helm 版本小于 2.5.0)这很可能是由于创建 chart 索引而未指定 `--url` 参数。尝试使用类似命令 `helm repo index --url http://my-repo/charts` 重建 `index.yaml`,然后将其重新上传到自定义 chart repo 库。 12 | 13 | 这个问题在Helm 2.5.0中进行了更改。 14 | -------------------------------------------------------------------------------- /chart/chart_repository_sync_example-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 同步 chart 库 2 | 3 | ** 注意:** 这个样例适用于于提供 chart 库的 Google Cloud Storage(GCS)存储 bucket。 4 | 5 | ## 前提条件 6 | 7 | * 安装 [gsutil](https://cloud.google.com/storage/docs/gsutil) 工具。** 这个样例依赖于 gsutil rsync 功能。** 8 | * 确保有权访问 Helm 客户端文件 9 | * 可选:我们建议在 GCS 存储桶上设置对象版本控制,以防意外删除某些内容。 10 | 11 | ## 设置本地 chart 库目录 12 | 13 | 像我们在 [the chart repository guide](chart_repository-zh_cn.md) 中一样创建一个本地目录,并将打包的 chart 放入该目录中。 14 | 15 | 例如: 16 | ```bash 17 | $ mkdir fantastic-charts 18 | $ mv alpine-0.1.0.tgz fantastic-charts/ 19 | ``` 20 | 21 | ## 生成更新的 index.yaml 22 | 23 | 使用 Helm 通过将远程存储库的目录路径和 url 传递到 `helm repo index` 命令来生成更新的 index.yaml 文件,如下所示: 24 | 25 | ```bash 26 | $ helm repo index fantastic-charts/ --url https://fantastic-charts.storage.googleapis.com 27 | ``` 28 | 29 | 这将生成一个更新的 index.yaml 文件并放置在 `fantastic-charts/` 目录中。 30 | 31 | ## 同步本地和远程 chart 库 32 | 33 | 通过运行 `scripts/sync-repo.sh` 并传入本地目录名称和 GCS 存储桶名称, 将目录的内容上传到您的 GCS 存储桶。 34 | 35 | 例如: 36 | 37 | ```bash 38 | 39 | $ pwd 40 | /Users/funuser/go/src/github.com/kubernetes/helm 41 | $ scripts/sync-repo.sh fantastic-charts/ fantastic-charts 42 | Getting ready to sync your local directory (fantastic-charts/) to a remote repository at gs://fantastic-charts 43 | Verifying Prerequisites.... 44 | Thumbs up! Looks like you have gsutil. Let’s continue. 45 | Building synchronization state... 46 | Starting synchronization 47 | Would copy file://fantastic-charts/alpine-0.1.0.tgz to gs://fantastic-charts/alpine-0.1.0.tgz 48 | Would copy file://fantastic-charts/index.yaml to gs://fantastic-charts/index.yaml 49 | Are you sure you would like to continue with these changes?? [y/N]} y 50 | Building synchronization state... 51 | Starting synchronization 52 | Copying file://fantastic-charts/alpine-0.1.0.tgz [Content-Type=application/x-tar]... 53 | Uploading gs://fantastic-charts/alpine-0.1.0.tgz: 740 B/740 B 54 | Copying file://fantastic-charts/index.yaml [Content-Type=application/octet-stream]... 55 | Uploading gs://fantastic-charts/index.yaml: 347 B/347 B 56 | Congratulations your remote chart repository now matches the contents of fantastic-charts/ 57 | 58 | ``` 59 | 60 | 61 | ## 更新 chart 库 62 | 63 | 你可能需要保留 chart 库内容的本地副本,或者运行 gsutil rsync 将远程 chart 存储库的内容复制到本地目录。 64 | 65 | 例如: 66 | 67 | ```bash 68 | $ gsutil rsync -d -n gs://bucket-name local-dir/ # the -n flag does a dry run 69 | Building synchronization state... 70 | Starting synchronization 71 | Would copy gs://bucket-name/alpine-0.1.0.tgz to file://local-dir/alpine-0.1.0.tgz 72 | Would copy gs://bucket-name/index.yaml to file://local-dir/index.yaml 73 | 74 | $ gsutil rsync -d gs://bucket-name local-dir/ # performs the copy actions 75 | Building synchronization state... 76 | Starting synchronization 77 | Copying gs://bucket-name/alpine-0.1.0.tgz... 78 | Downloading file://local-dir/alpine-0.1.0.tgz: 740 B/740 B 79 | Copying gs://bucket-name/index.yaml... 80 | Downloading file://local-dir/index.yaml: 346 B/346 B 81 | ``` 82 | 83 | 有用的网址: 84 | 85 | * 文档 [gsutil rsync](https://cloud.google.com/storage/docs/gsutil/commands/rsync#description) 86 | * [Chart 库指南](chart_repository-zh_cn.md) 87 | * 文档[object versioning and concurrency control](https://cloud.google.com/storage/docs/gsutil/addlhelp/ObjectVersioningandConcurrencyControl#overview) 88 | -------------------------------------------------------------------------------- /chart/chart_tests-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Chart 测试 2 | 3 | 一个 chart 包含许多一起工作的 Kubernetes 资源和组件。作为 chart 作者,可能需要编写一些测试来验证 chart 在安装时是否按预期工作。这些测试还有助于 chart 消费者了解 chart 应该做什么。 4 | 5 | ** 测试 ** 在 Helm chart 中的 templates / 目录,是一个 pod 定义,指定一个给定的命令来运行容器。容器应该成功退出(exit 0),测试被认为是成功的。该 pod 定义必须包含 helm 测试 hook 注释之一:`helm.sh/hook: test-success` 或 `helm.sh/hook: test-failure`。 6 | 7 | 示例测试: 8 | 9 | - 验证来自 values.yaml 文件的配置是否正确注入。 10 | - 确保用户名和密码正常工作 11 | - 确保不正确的用户名和密码不起作用 12 | - 断言服务已启动并正确进行负载平衡 13 | - 等等 14 | 15 | 可以使用该 helm test 命令在 release 中运行 Helm 中的预定义测试。对于 chart 使用者来说,这是一种很好的方式来检查他们发布的 chart(或应用程序)是否按预期工作。 16 | 17 | ## Helm 测试 hook 的分解 18 | 19 | 在 Helm 中,有两个测试 hook:`test-success` 和 `test-failure`. 20 | 21 | `test-success` 表示测试 pod 应该成功完成。换句话说,容器中的容器应该 exit 0. `test-failure` 是一种断言测试容器不能成功完成的方式。如果 pod 中的容器未 exit 0,则表示成功。 22 | 23 | ## 示例测试 24 | 25 | 下面是一个示例 WordPress chart 中 helm 测试 pod 定义的示例。这个测试验证了 mariadb 的连接和登录: 26 | 27 | ``` 28 | wordpress/ 29 | Chart.yaml 30 | README.md 31 | values.yaml 32 | charts/ 33 | templates/ 34 | templates/tests/test-mariadb-connection.yaml 35 | ``` 36 | 37 | 在 `wordpress/templates/tests/test-mariadb-connection.yaml` 中: 38 | 39 | ``` 40 | apiVersion: v1 41 | kind: Pod 42 | metadata: 43 | name: "{{.Release.Name}}-credentials-test" 44 | annotations: 45 | "helm.sh/hook": test-success 46 | spec: 47 | containers: 48 | - name: {{.Release.Name}}-credentials-test 49 | image: {{.Values.image}} 50 | env: 51 | - name: MARIADB_HOST 52 | value: {{template "mariadb.fullname" .}} 53 | - name: MARIADB_PORT 54 | value: "3306" 55 | - name: WORDPRESS_DATABASE_NAME 56 | value: {{default "" .Values.mariadb.mariadbDatabase | quote}} 57 | - name: WORDPRESS_DATABASE_USER 58 | value: {{default "" .Values.mariadb.mariadbUser | quote}} 59 | - name: WORDPRESS_DATABASE_PASSWORD 60 | valueFrom: 61 | secretKeyRef: 62 | name: {{template "mariadb.fullname" .}} 63 | key: mariadb-password 64 | command: ["sh", "-c", "mysql --host=$MARIADB_HOST --port=$MARIADB_PORT --user=$WORDPRESS_DATABASE_USER --password=$WORDPRESS_DATABASE_PASSWORD"] 65 | restartPolicy: Never 66 | ``` 67 | 68 | ## 在 release 上运行测试套件的步骤 69 | 70 | 1. `$ helm install stable\wordpress` 71 | ``` 72 | NAME: quirky-walrus 73 | LAST DEPLOYED: Mon Feb 13 13:50:43 2017 74 | NAMESPACE: default 75 | STATUS: DEPLOYED 76 | ``` 77 | 78 | 2. `$ helm test quirky-walrus` 79 | ``` 80 | RUNNING: quirky-walrus-credentials-test 81 | SUCCESS: quirky-walrus-credentials-test 82 | ``` 83 | 84 | ## 注意 85 | - 可以在单个 yaml 文件中定义尽可能多的测试,也可以在 templates / 目录中的多个 yaml 文件中进行分布测试 86 | - 提倡将测试套件嵌入到一个`tests/`目录下,比如`/templates/tests/`以便实现更多隔离 87 | -------------------------------------------------------------------------------- /chart/charts_hooks-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Hooks 2 | 3 | Helm 提供了一个 hook 机制,允许 chart 开发人员在 release 的生命周期中的某些点进行干预。例如,可以使用 hooks 来: 4 | 5 | - 在加载任何其他 chart 之前,在安装过程中加载 ConfigMap 或 Secret。 6 | - 在安装新 chart 之前执行作业以备份数据库,然后在升级后执行第二个作业以恢复数据。 7 | - 在删除 release 之前运行作业,以便在删除 release 之前优雅地停止服务。 8 | 9 | Hooks 像常规模板一样工作,但它们具有特殊的注释,可以使 Helm 以不同的方式使用它们。在本节中,我们介绍 Hooks 的基本使用模式。 10 | 11 | ## 可用的 Hooks 12 | 13 | 定义了以下 hooks: 14 | 15 | - 预安装 pre-install::在模板渲染后执行,但在 Kubernetes 中创建任何资源之前执行。 16 | - 安装后 post-install:在所有资源加载到 Kubernetes 后执行 17 | - 预删除 pre-delete:在从 Kubernetes 删除任何资源之前执行删除请求。 18 | - 删除后 post-delete:删除所有 release 的资源后执行删除请求。 19 | - 升级前 pre-upgrade:在模板渲染后,但在任何资源加载到 Kubernetes 之前执行升级请求(例如,在 Kubernetes 应用操作之前)。 20 | - 升级后 post-upgrade:在所有资源升级后执行升级。 21 | - 预回滚 pre-rollback:在渲染模板之后,但在任何资源已回滚之前,在回滚请求上执行。 22 | - 回滚后 post-rollback:在修改所有资源后执行回滚请求。 23 | 24 | ## Hooks 和 release 的生命周期 25 | 26 | Hooks 让 chart 开发人员有机会在 release 的生命周期中的关键点执行操作。例如,考虑 a 的生命周期。默认情况下,生命周期如下所示: 27 | 28 | - 用户运行 `helm install foo` 29 | - chart 被加载到 Tiller 中 30 | - 经过一些验证后,Tiller 渲染 foo 模板 31 | - Tiller 将产生的资源加载到 Kubernetes 中 32 | - Tiller 将 release 名称(和其他数据)返回给客户端 33 | - 客户端退出 34 | 35 | Helm 为 install 生命周期定义了两个 hook:`pre-install` 和 `post-install`。如果 `foo` chart 的开发者实现了两个 hook,那么生命周期就像这样改变: 36 | 37 | - 用户运行 `helm install foo` 38 | - chart 被加载到 Tiller 中 39 | - 经过一些验证后,Tiller 渲染 `foo` 模板 40 | - Tiller 准备执行 `pre-install` hook(将 hook 资源加载到 Kubernetes 中) 41 | - Tiller 会根据权重对 hook 进行排序(默认分配权重 0),并按相同权重的 hook 按升序排序。 42 | - Tiller 然后装载最低权重的 hook(从负到正) 43 | - Tiller 等待,直到 hook“准备就绪” 44 | - Tiller 将产生的资源加载到 Kubernetes 中。请注意,如果设置 `--wait` 标志,Tiller 将等待,直到所有资源都处于就绪状态,并且在准备就绪之前不会运行 `post-install`hook。 45 | - Tiller 执行 `post-install` hook(加载 hook 资源) 46 | - Tiller 等待,直到 hook“准备就绪” 47 | - Tiller 将 release 名称(和其他数据)返回给客户端 48 | - 客户端退出 49 | 50 | 等到 hook 准备就绪是什么意思?这取决于在 hook 中声明的资源。如果资源是 Job 者一种资源,Tiller 将等到作业成功完成。如果作业失败,则发布失败。这是一个阻塞操作,所以 Helm 客户端会在 Job 运行时暂停。 51 | 52 | 对于所有其他类型,只要 Kubernetes 将资源标记为加载(添加或更新),资源就被视为 “就绪”。当一个 hook 声明了很多资源时,这些资源将被串行执行。如果他们有 hook 权重(见下文),他们按照加权顺序执行。否则,订购过程不能保证。(在 Helm 2.3.0 及之后的版本中,它们按字母顺序排列,但这种行为并未被视为具有约束力,将来可能会发生变化)。添加挂钩权重被认为是很好的做法,并将其设置为 0 如果权重不是重要。 53 | 54 | ### Hook 资源不与相应的 release 一起进行管理 55 | Hook 创建的资源不作为 release 的一部分进行跟踪或管理。一旦 Tiller 验证 hook 已经达到其就绪状态,它将 hook 资源放在一边。 56 | 57 | 实际上,这意味着如果在 hook 中创建资源,则不能依赖于 helm delete 删除资源。要销毁这些资源,需要编写代码在 `pre-delete` 或 `post-delete`hook 中执行此操作,或者将 `"helm.sh/hook-delete-policy"` 注释添加到 hook 模板文件。 58 | 59 | ## 写一个 hook 60 | Hook 只是 Kubernetes manifest 文件,在 metadata 部分有特殊的注释 。因为他们是模板文件,可以使用所有的 Normal 模板的功能,包括读取 `.Values`,`.Release` 和 `.Template`。 61 | 62 | 例如,在此模板中, 存储在 `templates/post-install-job.yaml` 的声明要在 `post-install` 阶段运行作业: 63 | 64 | ```yaml 65 | apiVersion: batch/v1 66 | kind: Job 67 | metadata: 68 | name: "{{ .Release.Name }}" 69 | labels: 70 | app.kubernetes.io/managed-by: {{ .Release.Service | quote }} 71 | app.kubernetes.io/instance: {{ .Release.Name | quote }} 72 | helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 73 | annotations: 74 | # This is what defines this resource as a hook. Without this line, the 75 | # job is considered part of the release. 76 | "helm.sh/hook": post-install 77 | "helm.sh/hook-weight": "-5" 78 | "helm.sh/hook-delete-policy": hook-succeeded 79 | spec: 80 | template: 81 | metadata: 82 | name: "{{ .Release.Name }}" 83 | labels: 84 | app.kubernetes.io/managed-by: {{ .Release.Service | quote }} 85 | app.kubernetes.io/instance: {{ .Release.Name | quote }} 86 | helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 87 | spec: 88 | restartPolicy: Never 89 | containers: 90 | - name: post-install-job 91 | image: "alpine:3.3" 92 | command: ["/bin/sleep","{{ default"10".Values.sleepyTime }}"] 93 | 94 | ``` 95 | 96 | 注释使这个模板成为 hook: 97 | 98 | 99 | ``` 100 | annotations: 101 | "helm.sh/hook": post-install 102 | ``` 103 | 104 | 一个资源可以部署多个 hook: 105 | 106 | ``` 107 | annotations: 108 | "helm.sh/hook": post-install,post-upgrade 109 | ``` 110 | 111 | 同样,实现一个给定的 hook 的不同种类资源数量没有限制。例如,我们可以将 secret 和 config map 声明为预安装 hook。 112 | 113 | 子 chart 声明 hook 时,也会评估这些 hook。顶级 chart 无法禁用子 chart 所声明的 hook。 114 | 115 | 可以为一个 hook 定义一个权重,这将有助于建立一个确定性的执行顺序。权重使用以下注释来定义: 116 | 117 | ``` 118 | annotations: 119 | "helm.sh/hook-weight": "5" 120 | ``` 121 | 122 | hook 权重可以是正数或负数,但必须表示为字符串。当 Tiller 开始执行一个特定类型的 hook (例: `pre-install` hooks `post-install` hooks, 等等) 执行周期时,它会按升序对这些 hook 进行排序。 123 | 124 | 还可以定义确定何时删除相应的 hook 资源的策略。hook 删除策略使用以下注释来定义: 125 | 126 | ``` 127 | annotations: 128 | "helm.sh/hook-delete-policy": hook-succeeded 129 | ``` 130 | 131 | 可以选择一个或多个定义的注释值: 132 | 133 | * "hook-succeeded" 指定 Tiller 应该在 hook 成功执行后删除 hook。 134 | * "hook-failed" 指定如果 hook 在执行期间失败,Tiller 应该删除 hook。 135 | * "before-hook-creation" 指定 Tiller 应在删除新 hook 之前删除以前的 hook。 136 | 137 | ### 自动删除以前版本的 hook 138 | 当 helm 的 release 更新, 如果这个 release 使用了 hook,有可能 hook 资源已经存在于群集中。默认情况下,helm 会尝试创建资源,并抛出错误 "... already exists"。 139 | 140 | Hook 资源可能已经存在的一个常见原因是,在以前的安装 / 升级中使用它之后它没有被删除。事实上,有充分理由说明为什么人们可能想要保留 hook:例如,在出现问题时帮助手动调试。在这种情况下,确保后续尝试创建 hook 的推​​荐方法不会失败是定义一个 `"hook-delete-policy"`,它可以处理这个:`"helm.sh/hook-delete-policy": "before-hook-creation"`。在安装新 hook 之前,此 hook 注释会导致删除任何现有挂钩。 141 | 142 | 如果偏好在每次使用后删除钩子(而不是在后续使用时处理它,如上所示) 143 | 我们可以选择使用 `"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"` : 144 | -------------------------------------------------------------------------------- /chart/charts_tips_and_tricks-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Chart 开发 Tips 和 Tricks 2 | 本指南涵盖了 Helm chart 开发人员在构建生产级质量的 chart 时学到的一些提示和技巧。 3 | 4 | ## 了解模板函数 5 | 6 | Helm 使用 Go 模板 [Go templates](https://godoc.org/text/template) 来模板化你的资源文件。虽然 Go 提供了几个内置函数,但我们添加了许多其他函数。 7 | 8 | 首先,我们在 Sprig 库 [Sprig library](https://godoc.org/github.com/Masterminds/sprig) 中添加了几乎所有的函数 。出于安全原因,我们删除了两个:`env` 和 `expandenv`(这会让 chart 作者访问 Tiller 的环境)。 9 | 10 | 我们还添加了两个特殊的模板函数:`include` 和 `required`。`include` 函数允许引入另一个模板,然后将结果传递给其他模板函数。 11 | 12 | 例如,该模板片段包含一个调用的模板 `mytpl`,然后将结果小写,然后用双引号将其包起来。 13 | 14 | ```yaml 15 | value: {{ include "mytpl" . | lower | quote }} 16 | ``` 17 | 18 | `required` 函数允许根据模板渲染的要求声明特定的值条目。如果该值为空,则模板渲染将失败并显示用户提交的错误消息。 19 | 20 | 下面的 `required` 函数示例声明了. Values.who 的条目是必需的,并且在缺少该条目时将显示错误消息: 21 | 22 | ```yaml 23 | value: {{ required "A valid .Values.who entry required!" .Values.who }} 24 | ``` 25 | 26 | 当使用 `include` 函数时,可以使用 `dict` 函数给它传递一个通过当前上下文自定义对象树。 27 | 28 | ```yaml 29 | {{- include "mytpl" (dict "key1" .Values.originalKey1 "key2" .Values.originalKey2) }} 30 | ``` 31 | 32 | 33 | ## 引用字符串,不要引用整数 34 | 35 | 当使用字符串数据时,引用字符串比把它们留为空白字符更安全: 36 | 37 | ```yaml 38 | name: {{ .Values.MyName | quote }} 39 | ``` 40 | 41 | 但是,使用整数时 _不要引用值_。在很多情况下,这可能会导致 Kubernetes 内部的解析错误。 42 | 43 | ```yaml 44 | port: {{ .Values.Port }} 45 | ``` 46 | 47 | 这种做法不适用于预期为字符串的 env 变量值,即使它们表示为整数: 48 | 49 | ```yaml 50 | env: 51 | -name: HOST 52 | value: "http://host" 53 | -name: PORT 54 | value: "1234" 55 | ``` 56 | 57 | ## 使用'include'函数 58 | 59 | Go 提供了一种使用内置 `template` 指令将一个模板包含在另一个模板中的方法 。但是,Go 模板管道中不能使用内置函数。 60 | 61 | 为了能够包含模板,然后对该模板的输出执行操作,Helm 有一个特殊的 `include` 函数: 62 | 63 | ``` 64 | {{- include "toYaml" $value | nindent 2 }} 65 | ``` 66 | 67 | 上面包含一个名为的模板 toYaml,传递它 $value 的值,然后将该模板的输出传递给该 indent 函数。 68 | 69 | 因为 YAML 的缩进级别和空白的很重要,所以这是包含代码片段的好方法,并在相关的上下文中处理缩进。 70 | 71 | ## 使用'required'函数 72 | 73 | Go 提供了一种设置模板选项以控制 map 使用 map 中不存在的键编制索引时的行为的方法。这通常使用 template.Options(“missingkey = option”)设置,其中 option 可以是默认值,零或错误。将此选项设置为错误将停止执行并出现错误,这应用于 map 中每个缺失的键。这适用于 chart 开发人员想要强制为 values.yml 文件选择值来实施此行为的情况。 74 | 75 | 该 `required` 函数使开发人员能够根据模板渲染的要求声明值条目。如果 values.yml 中的条目为空,模板将不会渲染,并会返回开发人员提供的错误消息。 76 | 77 | 例如: 78 | 79 | ``` 80 | {{ required "A valid foo is required!" .Values.foo }} 81 | ``` 82 | 83 | 上面将在定义. Values.foo 时渲染模板,但在未定义. Values.foo 时无法渲染并报错退出。 84 | ## 使用'tpl' 函数 85 | 86 | `tpl` 函数允许开发人员将字符串计算为模板内的模板。 87 | 这对于将模板字符串作为值传递给 chart 或渲染外部配置文件很有用。 88 | 89 | 语法: `{{ tpl TEMPLATE_STRING VALUES }}` 90 | 91 | 样例: 92 | 93 | ```yaml 94 | # values 95 | template: "{{ .Values.name }}" 96 | name: "Tom" 97 | 98 | # template 99 | {{ tpl .Values.template . }} 100 | 101 | # output 102 | Tom 103 | ``` 104 | 105 | 渲染一个外部配置文件: 106 | 107 | ```yaml 108 | # external configuration file conf/app.conf 109 | firstName={{ .Values.firstName }} 110 | lastName={{ .Values.lastName }} 111 | 112 | # values 113 | firstName: Peter 114 | lastName: Parker 115 | 116 | # template 117 | {{ tpl (.Files.Get "conf/app.conf") . }} 118 | 119 | # output 120 | firstName=Peter 121 | lastName=Parker 122 | ``` 123 | ## 创建镜像拉取的 Secrets 124 | 125 | 镜像拉的 secrets 实质上是注册,用户名和密码的组合。在正在部署的应用程序中可能需要它们,但要创建它们需要多次运行 base64。我们可以编写一个帮助程序模板来组合 Docker 配置文件,以用作 Secret 的有效载体。这里是一个例子: 126 | 127 | 首先,假设凭证在 `values.yaml` 文件中定义如下: 128 | 129 | ```yaml 130 | imageCredentials: 131 | registry: quay.io 132 | username: someone 133 | password: sillyness 134 | ``` 135 | 136 | 然后我们定义我们的帮助模板如下: 137 | ``` 138 | {{- define "imagePullSecret" }} 139 | {{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\" }}}" .Values.imageCredentials.registry (printf "%s:%s" .Values.imageCredentials.username .Values.imageCredentials.password | b64enc) | b64enc }} 140 | {{- end }} 141 | ``` 142 | 最后,我们在更大的模板中使用助手模板来创建 Secret manifest: 143 | 144 | ```yaml 145 | apiVersion: v1 146 | kind: Secret 147 | metadata: 148 | name: myregistrykey 149 | type: kubernetes.io/dockerconfigjson 150 | data: 151 | .dockerconfigjson: {{ template "imagePullSecret" . }} 152 | ``` 153 | 154 | ## ConfigMaps 或 Secrets 更改时自动 Roll Deployments 155 | 156 | 通常情况下,configmaps 或 secrets 被作为配置文件注入容器中。根据应用程序的不同,可能需要重新启动才能使用后续更新 `helm upgrade`,但如果 deployment spece 本身未更改,则应用程序会一直以旧配置运行,导致 deployment 不一致。 157 | 158 | 该 `sha256sum` 函数可用于确保在一个文件发生更改时更新 deployment 的注释部分: 159 | 160 | ```yaml 161 | kind: Deployment 162 | spec: 163 | template: 164 | metadata: 165 | annotations: 166 | checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} 167 | [...] 168 | ``` 169 | 170 | 另请参阅 h`elm upgrade --recreate-pods` 标志以解决此问题的稍微不同的方式。 171 | 172 | ## 告诉 Tiller 不要删除资源 173 | 174 | 有时候有一些资源在 Helm 运行 `helm delete` 时不应该被删除 。chart 开发人员可以将注释添加到资源以防止被删除。 175 | 176 | ```yaml 177 | kind: Secret 178 | metadata: 179 | annotations: 180 | "helm.sh/resource-policy": keep 181 | [...] 182 | ``` 183 | 184 | (需要双引号) 185 | 186 | 注释 `"helm.sh/resource-policy": keep` 指示 Tiller 在 helm delete 操作过程中跳过此资源。但是,此资源变成孤儿资源。Helm 将不再以任何方式管理它。如果 `helm install --replace` 在已被删除的 release 上使用,但保留了资源,则这可能会引发问题。 187 | 188 | 为了明确删除资源, 例如当覆盖一个 chart 的默认注释, 设置资源策略注释值为 `delete`. 189 | 190 | ## 使用 “Partials” 和 includes 模板 191 | 192 | 有时候你想在 chart 中创建一些可重用的部分,无论它们是块还是模板部分。通常,将这些文件保存在自己的文件中会更整洁。 193 | 194 | 在 `templates/` 目录中,任何以下划线 "-" 开头的文件都不会输出 Kubernetesmanifest 文件。另按照惯例,辅助模板和 partials 被放置在一个 `_helpers.tpl` 文件中。 195 | 196 | ## 具有许多依赖关系的复杂 chart 197 | 198 | 官方 chart repo 存储库 [official charts repository](https://github.com/helm/charts) 中的许多 chart 是用于创建更高级应用程序的 “构建块”。chart 可能用于创建大规模应用程序的实例。在这种情况下,一张伞形 chart 可能有多个子 chart,每个子 chart 都是整体的一部分。 199 | 200 | 当前最佳做法是:从各个子 chart 组成复杂应用程序,创建公开全局配置的顶层伞形 chart,然后使用 charts / 子目录嵌入每个组件 chart。 201 | 202 | 下面的项目说明了两种强大的设计模式: 203 | 204 | **SAP's [OpenStack chart](https://github.com/sapcc/openstack-helm):**:该 chart 在 Kubernetes 上安装完整的 SAP 云的 OpenStack IaaS。所有 chart 都收集在一个 GitHub 存储库中,除了一些子模块。 205 | 206 | **Deis's [Workflow](https://github.com/deis/workflow/tree/master/charts/workflow):**: 该 chart 显示了整个 Deis PaaS 系统的一个 chart。但与 SAP chart 不同的是,该伞形 chart 是从每个组件构建而来的,每个组件都在不同的 Git 存储库中进行跟踪。查看 `requirements.yaml` 文件以查看此 chart 是如何由其 CI/CD 流水线组成的。 207 | 208 | 这两个 chart 都说明了使用 Helm 建立复杂环境的成熟技术。 209 | 210 | ## YAML 是 JSON 的超级 Superset 211 | 212 | 根据 YAML 规范,YAML 是 JSON 的超集。这意味着任何有效的 JSON 结构都应该在 YAML 中有效。 213 | 214 | 这有一个优点:有时模板开发人员可能会发现使用类似 JSON 的语法来表示数据结构更容易,而不是处理 YAML 的空白敏感度。 215 | 216 | 作为最佳实践,模板应遵循类似 YAML 的语法,除非 JSON 语法大幅降低了格式问题的风险。 217 | 218 | ## 小心随机值生成 219 | Helm 中有一些函数允许生成随机数据,加密密钥等。这些都很好用。但请注意,在升级过程中,模板会被重新执行。当模板运行产生与上次运行不同的数据时,将触发该资源的更新。 220 | 221 | ## 升级一个 release 的 idempotently 222 | 为了在安装和升级发行版时使用相同的命令,请使用以下命令: 223 | 224 | ```bash 225 | helm upgrade --install --values 226 | ``` 227 | -------------------------------------------------------------------------------- /chart/provenance-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Helm 的出处与完整性验证 2 | 3 | Helm 拥有可帮助 chart 用户验证 chart 包完整性和出处的工具。使用基于 PKI,GnuPG 和备受尊敬的软件包管理器的行业标准工具,Helm 可以生成并验证签名文件。 4 | 5 | ## 概述 6 | 7 | 完整性通过将 chart 与其出处记录进行比较来确定。出处记录存储在出处文件 provenance 中,并与打包的 chart 一起存储。例如,如果 chart 包被命名 `myapp-1.2.3.tgz`,其出处文件将是 `myapp-1.2.3.tgz.prov`。 8 | 9 | 出处文件在打包时生成(`helm package --sign ...`),并且可以通过多个命令检查,比如 `helm install --verify`。 10 | 11 | ## 工作流程 12 | 13 | 本节描述了有效使用出处数据的可用的工作流程。 14 | 15 | 前提条件: 16 | 17 | - 二进制(非 ASCII)格式的有效 PGP 密钥对 18 | - helm 命令行工具 19 | - GnuPG >=2.1 命令行工具(可选) 20 | - Keybase 命令行工具(可选) 21 | - 22 | ** 注意:** 如果 PGP 私钥有密码,支持 `--sign` 选项的任何命令系统将提示输入密码。可以设置 HELM_KEY_PASSPHRASE 环境变量避免每次输入. 23 | 24 | ** 注意:** GnuPG 的密钥文件格式在 2.1 版中已更改。在该版本之前,没有必要从 GnuPG 中导出密钥,可以将 Helm 指向你的 `* .gpg` 文件。使用 2.1 时,引入了新的 `.kbx` 格式,Helm 不支持这种格式。 25 | 26 | 创建 chart: 27 | 28 | ``` 29 | $ helm create mychart 30 | Creating mychart 31 | ``` 32 | 33 | 准备打包后,将 `--sign` 参数加到 `helm package`。另外,指定已知签名密钥和包含相应私钥的密钥环 keyring: 34 | 35 | ``` 36 | $ helm package --sign --key 'helm signing key' --keyring path/to/keyring.secret mychart 37 | ``` 38 | 39 | ** 提示:** 对于 GnuPG 用户,密钥环已存在 `~/.gnupg/secring.kbx`。可以使用 gpg --list-secret-keys 列出拥有的密钥。 40 | 41 | ** 警告:** GnuPG v2.1 在默认位置在 `〜/ .gnupg / pubring.kbx`,使用新格式'kbx'存储密钥 keyring。请使用以下命令将钥匙 keyring 转换为传统的 gpg 格式: 42 | 43 | ``` 44 | $ gpg --export-secret-keys >~/.gnupg/secring.gpg 45 | ``` 46 | 47 | 到这里,应该可用看到 mychart-0.1.0.tgz 和 mychart-0.1.0.tgz.prov。这两个文件最终应该上传到想要的 chart 库。 48 | 49 | 可以使用 `helm verify` 以下方式验证 chart: 50 | 51 | ``` 52 | $ helm verify mychart-0.1.0.tgz 53 | ``` 54 | 55 | 验证失败如下所示样例: 56 | 57 | ``` 58 | $ helm verify topchart-0.1.0.tgz 59 | Error: sha256 sum does not match for topchart-0.1.0.tgz: "sha256:1939fbf7c1023d2f6b865d137bbb600e0c42061c3235528b1e8c82f4450c12a7" != "sha256:5a391a90de56778dd3274e47d789a2c84e0e106e1a37ef8cfa51fd60ac9e623a" 60 | ``` 61 | 62 | 要在安装过程中进行验证,请使用该 `--verify` 标志。 63 | 64 | ``` 65 | $ helm install --verify mychart-0.1.0.tgz 66 | ``` 67 | 如果密钥 keyring(包含与签名 chart 关联的公钥)不在默认位置,则可能需要 `--keyring PATH` 像 `helm package` 示例中那样指向密钥 keyring。 68 | 69 | 如果验证失败,在 chart 被推到 Tiller 之前中止安装终止。 70 | 71 | ### 使用 Keybase.io 凭据 72 | 该 Keybase.io 服务可以很容易建立信任链的密码身份。密钥库凭证可用于对 chart 进行签名。 73 | 74 | 前提条件: 75 | 76 | - 已配置的 Keybase.io 帐户 77 | - GnuPG 在本地安装 78 | - keybaseCLI 本地安装 79 | 80 | #### 签署软件包 81 | 82 | 第一步是将 keybase 密钥导入到本地 GnuPG 密钥 keyring 中: 83 | 84 | ``` 85 | $ keybase pgp export -s > secring.gpg 86 | ``` 87 | 88 | 这会将 Keybase 密钥转换为 OpenPGP 格式,然后将其本地导入到 secring.gpg 文件中。 89 | 90 | 可以通过运行 `gpg --list-secret-keys` 进行仔细检查。 91 | 92 | ``` 93 | $ gpg --list-secret-keys /Users/mattbutcher/.gnupg/secring.gpg 94 | ------------------------------------- 95 | sec 2048R/1FC18762 2016-07-25 96 | uid technosophos (keybase.io/technosophos) 97 | ssb 2048R/D125E546 2016-07-25 98 | ``` 99 | 100 | 提示: 如果你想添加一个 Keybase key 到已存在的 keyring, 你需要执行 `keybase pgp export -s | gpg --import && gpg --export-secret-keys --outfile secring.gpg` 101 | 102 | 你的密钥有一个标识符字符串: 103 | 104 | ``` 105 | technosophos (keybase.io/technosophos) 106 | ``` 107 | 108 | 这是钥匙的全名。 109 | 110 | 接下来,可以使用 `helm package` 打包和签名 chart。`--key` 确保至少使用该名称字符串的一部分。 111 | 112 | 113 | ``` 114 | $ helm package --sign --key technosophos --keyring ~/.gnupg/secring.gpg mychart 115 | ``` 116 | 117 | 结果,package 命令应该生成一个. tgz 文件和一个. tgz.prov 文件。 118 | 119 | #### 验证软件包 120 | 121 | 还可以使用类似的技术来验证由其他人的 Keybase 密钥签名的 chart。假设想验证签名的软件包 keybase.io/technosophos。请使用该 keybase 工具: 122 | 123 | ``` 124 | $ keybase follow technosophos 125 | $ keybase pgp pull 126 | ``` 127 | 128 | 上面的第一条命令跟踪用户 `technosophos`。接下来 `keybase pgp pull `,将关注的所有帐户的 OpenPGP 密钥下载到 GnuPG 密钥环(`~/.gnupg/pubring.gpg1`)中 129 | 130 | 到此,可以使用 `helm verify` 或带有 `--verify` 参数的任何命令: 131 | 132 | ``` 133 | $ helm verify somechart-1.2.3.tgz 134 | ``` 135 | 136 | ### 可能无法验证的原因 137 | 138 | 下面是失败的常见原因。 139 | 140 | - prov 文件丢失或损坏。这表明某些内容配置错误或原始维护人员未创建出处文件。 141 | - 用于签署文件的密钥不在钥匙 keyring 中。这表明签名 chart 的组织不是已经信任的人员。 142 | - prov 文件的验证失败。这表明 chart 或出处数据有问题。 143 | - prov 文件中的文件哈希与压缩包文件的哈希不匹配。这表明压缩包已被篡改。 144 | - 如果验证失败,则有理由怀疑该软件包有问题。 145 | 146 | ## Provenance 文件 147 | Provenance 文件包含 chart 的 YAML 文件以及几条验证信息。Provenance 文件被设计自动生成。 148 | 149 | 添加了以下几个出处数据: 150 | 151 | - 包含 chart 文件(Chart.yaml)可以让人员和工具轻松查看 chart 内容。 152 | - 包括 chart 包(.tgz 文件)的签名(SHA256,就像 Docker)一样,可用于验证 chart 包的完整性。 153 | - 整个文件使用 PGP 使用的算法进行签名(参见 [https://keybase.io],这是一种使加密签名和验证变得容易的新方法)。 154 | 155 | 这样的组合给了用户以下保证: 156 | 157 | - 包本身没有被篡改(校验和包 tgz)。 158 | - 已知发布此包的组织(通过 GnuPG / PGP 签名)。 159 | 160 | 该文件的格式如下所示: 161 | 162 | ``` 163 | -----BEGIN PGP SIGNED MESSAGE----- 164 | name: nginx 165 | description: The nginx web server as a replication controller and service pair. 166 | version: 0.5.1 167 | keywords: 168 | - https 169 | - http 170 | - web server 171 | - proxy 172 | source: 173 | - https://github.com/foo/bar 174 | home: https://nginx.com 175 | 176 | ... 177 | files: 178 | nginx-0.5.1.tgz: “sha256:9f5270f50fc842cfcb717f817e95178f” 179 | -----BEGIN PGP SIGNATURE----- 180 | Version: GnuPG v1.4.9 (GNU/Linux) 181 | 182 | iEYEARECAAYFAkjilUEACgQkB01zfu119ZnHuQCdGCcg2YxF3XFscJLS4lzHlvte 183 | WkQAmQGHuuoLEJuKhRNo+Wy7mhE7u1YG 184 | =eifq 185 | -----END PGP SIGNATURE----- 186 | ``` 187 | 188 | 注意,YAML 部分包含两个文档(由分隔 `...\n`)。首先是 Chart.yaml。第二个是校验和,一个文件名到 SHA-256 摘要的映射(上显示的值是假的 / 被截断的) 189 | 190 | 签名块是一个标准的 PGP 签名,它提供了 [防篡改](https://www.rossde.com/PGP/pgp_signatures.html) 功能。 191 | 192 | ## Chart 库 193 | 194 | Chart 库用作 Helm chart 的集中场所。 195 | 196 | Chart 存储库必须能够通过特定的请求通过 HTTP 为 provenance 文件提供服务,并且必须使它们在与 chart 相同的 URI 路径下可用。 197 | 198 | 例如,如果软件包的基本 URL 是 `https://example.com/charts/mychart-1.2.3.tgz`, provenance 文件(如果存在)必须可以通过 `https://example.com/charts/mychart-1.2.3.tgz.prov` 访问。 199 | 200 | 从最终用户的角度来看,`helm install --verify myrepo/mychart-1.2.3 ` 应该无需额外的配置或操作即可下载 chart 和 provenance 文件。 201 | 202 | ## 确认认证和鉴权 203 | 204 | 在处理信任链系统时,能够确认签名者的认证很重要。或者,简单地说,上述系统取决于相信签名人员的事实。这反过来又意味着你需要信任签名者的公钥。 205 | 206 | Kubernetes Helm 的设计决策之一是 Helm 项目不会将自己插入信任链中作为必要的组分。我们不希望成为所有 chart 签名者的 “证书颁发机构”。相反,我们强烈支持分散模式,这是我们选择 OpenPGP 作为基础技术的原因之一。所以说到确认认证时,我们在 Helm 2.0.0 中对这个步骤或多或少未明确定义。 207 | 208 | 但是,对于那些有兴趣使用 povenance 系统的人,我们有一些建议: 209 | 210 | - [Keybase](https://keybase.io) 平台提供了可靠信息的公开集中存放。 211 | - 可以使用 Keybase 存储密钥或获取其他公钥。 212 | - Keybase 也有很多可用的文档 213 | - 虽然我们还没有对它进行测试,但 Keybase 的 “安全网站” 功能可用于服务 Helm chart。 214 | - Kubernetes chart 项目 正在设法解决这个管方 chart 库 [official Kubernetes Charts project](https://github.com/kubernetes/charts) 问题。 215 | - 这里有一个 [很长的 issue](https://github.com/kubernetes/charts/issues/23),详细介绍了当前的想法。 216 | - 基本思想原则是官方的 “chart reviewer” 用她或他的钥匙签名 chart,然后将得到的 Provence 文件上传到 chart 存储库。 217 | - 关于 ` 有效签名密钥列表可包含在 index.yaml 存储库文件中 ` 的想法已经有了一些工作进展。 218 | 219 | 最后,信任链是Helm的一个发展特征,一些社区成员已经提出了将OSI模型的一部分用于签名。这是Helm团队的一个开放性调查。如果你有兴趣,请参与其中。 220 | -------------------------------------------------------------------------------- /chart_best_practices/README-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Chart 最佳实践指南 2 | 3 | 本指南涵盖了 Helm Team 创建 chart 的最佳实践。它着重于如何构建 chart。 4 | 5 | 我们主要关注有可能公开部署的 chart 的最佳实践。我们知道许多 chart 仅供内部使用,这些 chart 的作者可能会由于为了其内部利益,可能不拘泥于我们的建议。 6 | 7 | ## 目录 8 | - [一般约定](conventions-zh_cn.md):了解 chart 一般约定。 9 | - [values 文件](values-zh_cn.md):查看结构化 `values.yaml` 的最佳实践。 10 | - [Template](templates-zh_cn.md)::学习一些编写模板的最佳技巧。 11 | - [Requirement](requirements-zh_cn.md):遵循 `requirements.yaml` 文件的最佳做法。 12 | - [标签和注释](labels-zh_cn.md)::helm 具有标签和注释的传统。 13 | - Kubernetes 资源: 14 | - [Pod 及其规格](pods-zh_cn.md):查看使用 pod 规格的最佳做法。 15 | - [基于角色的访问控制](rbac-zh_cn.md):有关创建和使用服务帐户,角色和角色绑定的指导。 16 | - [自定义资源](custom_resource_definitions-zh_cn.md):自定义资源(CRDs)有其自己的相关最佳实践。 17 | -------------------------------------------------------------------------------- /chart_best_practices/conventions-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 一般约定 2 | 3 | 最佳实践指南的这一部分介绍了一般约定。 4 | 5 | ## Chart 名称 6 | 7 | Chart 名称应该是小写字母和数字组成,字母开头: 8 | 9 | 举例: 10 | 可以使用破折号 `-`, 但在 Helm templates 中使用需要一些小技巧 (查看 [issue #2192](https://github.com/helm/helm/issues/2192) 获取更多信息). 11 | + 12 | 这里有一些好例子 [Helm Community Charts](https://github.com/helm/charts): 13 | 14 | ``` 15 | drupal 16 | cert-manager 17 | oauth2-proxy 18 | ``` 19 | 20 | Chart 名称中不能使用大写字母和下划线。Chart 名称不应使用点。 21 | 22 | 包含 chart 的目录必须与 chart 具有相同的名称。因此,chart `cert-manager` 必须在名为 `cert-manager/` 的目录中创建。这不仅仅是一种风格的细节,而是 Helm Chart 格式的要求。 23 | 24 | ## 版本号 25 | 26 | 只要有可能,Helm 使用 [SemVer 2](https://semver.org) 来表示版本号。(请注意,Docker 镜像 tag 不一定遵循 SemVer,因此被视为该规则的一个例外。) 27 | 28 | 当 SemVer 版本存储在 Kubernetes 标签中时,我们通常会将该 `+` 字符更改为一个 `_` 字符,因为标签不允许 `+` 标志作为值。 29 | 30 | ## 格式化 YAML 31 | 32 | YAML 文件应该使用两个空格缩进(而不是制表符)。 33 | 34 | ## 单词 Helm,Tiller 和 Chart 的用法 35 | 使用 Helm,helm,Tiller 和 tiller 这两个词有一些小的惯例。 36 | 37 | - Helm 是指该项目,通常用作总括术语 38 | - `helm ` 指的是客户端命令 39 | - Tiller 是后端的专有名称 40 | - `tiller` 是后端二进制运行的名称 41 | - 术语 “chart” 不需要大写,因为它不是专有名词。 42 | 43 | 如有疑问,请使用 Helm(大写'H')。 44 | 45 | ## 通过版本限制 Tiller 46 | 47 | 一个 `Chart.yaml` 文件可以指定一个 `tillerVersion` SemVer 约束: 48 | 49 | ```yaml 50 | name: mychart 51 | version: 0.2.0 52 | tillerVersion: ">=2.4.0" 53 | ``` 54 | 55 | 当模板使用 Helm 旧版本不支持的新功能时,应该设置此限制。虽然此参数将接受复杂的 SemVer 规则,但最佳做法是默认为格式 >=2.4.0,其中 2.4.0 引入了 chart 中使用的新功能的版本。 56 | 57 | 此功能是在Helm 2.4.0中引入的,因此任何2.4.0版本以下的Tiller都会忽略此字段。 58 | -------------------------------------------------------------------------------- /chart_best_practices/custom_resource_definitions-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 自定义资源定义 2 | 3 | 最佳实践指南的这一部分涉及创建和使用自定义资源定义对象。 4 | 5 | 使用自定义资源定义(CRD)时,区分两个不同的部分很重要: 6 | 7 | - 有一个 CRD 的声明。这是一个 YAML 文件,kind 类型为 `CustomResourceDefinition` 8 | - 然后有资源使用 CRD。CRD 定义 `foo.example.com/v1`。任何拥有 `apiVersion: example.com/v1` 和种类 `Foo` 的资源都是使用 CRD 的资源。 9 | 10 | ## 在使用资源之前安装 CRD 声明 11 | 12 | Helm 优化为尽可能快地将尽可能多的资源加载到 Kubernetes 中。通过设计,Kubernetes 可以采取一整套 manifests,并将它们全部启动在线(这称为 reconciliation 循环)。 13 | 14 | 但是与 CRD 有所不同。 15 | 16 | 对于 CRD,声明必须在该 CRDs 种类的任何资源可以使用之前进行注册。注册过程有时需要几秒钟。 17 | 18 | ### 方法 1:独立的 chart 19 | 20 | 一种方法是将 CRD 定义放在一个 chart 中,然后将所有使用该 CRD 的资源放入另一个 chart 中。 21 | 22 | 在这种方法中,每个 chart 必须单独安装。 23 | 24 | ### 方法 2:预安装 hook 25 | 26 | 要将这两者打包在一起,在 CRD 定义中添加一个 `crd-install` 钩子,以便在执行 chart 的其余部分之前完全安装它。 27 | 28 | 请注意,如果使用`crd-install` hook创建CRD ,则该CRD定义在`helm delete`运行时不会被删除。 29 | -------------------------------------------------------------------------------- /chart_best_practices/labels-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 标签和注释 2 | 最佳实践指南的这一部分讨论了在 chart 中使用标签和注释的最佳做法。 3 | 4 | ## 它是一个标签还是一个注释? 5 | 在下列条件下,元数据项应该是标签: 6 | 7 | - Kubernetes 使用它来识别此资源 8 | - 为了查询系统目的,向操作员暴露是非常有用的。 9 | 10 | 例如,我们建议使用 `helm.sh/chart: NAME-VERSION` 标签作为标签,以便操作员可以方便地查找要使用的特定 chart 的所有实例。 11 | 12 | 如果元数据项不用于查询,则应将其设置为注释。 13 | 14 | Helm hook 总是注释。 15 | 16 | ## 标准标签 17 | 下表定义了 Helm chart 使用的通用标签。Helm 本身从不要求特定的标签。标记为 REC 的标签是表示推荐的,应放置在 chart 上以保持全局一致性。那些标记 OPT 是表示可选的。这些都是惯用的或通常使用的,但不是经常用于运维目的。 18 | 19 | 名称 | 状态 | 描述 20 | -----|------|---------- 21 | `app.kubernetes.io/name` | REC | This should be the app name, reflecting the entire app. Usually {{ template "name" . }} is used for this. This is used by many Kubernetes manifests, and is not Helm-specific. 22 | `helm.sh/chart` | REC | This should be the chart name and version: `{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}` 23 | `app.kubernetes.io/managed-by` | REC | This should always be set to `{{ .Release.Service }}`. It is for finding all things managed by Tiller. 24 | `app.kubernetes.io/instance` | REC | This should be the `{{ .Release.Name }}`. It aid in differentiating between different instances of the same application. 25 | `app.kubernetes.io/version` | OPT | The version of the app and can be set to `{{ .Chart.AppVersion }}`. 26 | `app.kubernetes.io/component` | OPT | This is a common label for marking the different roles that pieces may play in an application. For example, `app.kubernetes.io/component: frontend`. 27 | `app.kubernetes.io/part-of` | OPT | When multiple charts or pieces of software are used together to make one application. For example, application software and a database to produce a website. This can be set to the top level application being supported. 28 | 29 | 获取更多关于 `app.kubernetes.io`前缀的 Kubernetes labels 的信息 [Kubernetes documentation](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/) 30 | -------------------------------------------------------------------------------- /chart_best_practices/pods-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Pod 和 Pod 模板 2 | 3 | 最佳实践指南的这一部分讨论了如何格式化 chart 清单中的 Pod 和 PodTemplate 部分。 4 | 5 | 以下(非详尽)资源列表使用 PodTemplates: 6 | 7 | - Deployment 8 | - ReplicationController 9 | - ReplicaSet 10 | - DaemonSet 11 | - StatefulSet 12 | 13 | ## 镜像 14 | 15 | 容器镜像应该使用固定标签或镜像的 SHA。它不应该使用的标签 `latest`,`head`,`canary`,或其他设计为 “浮动” 的标签。 16 | 17 | 镜像可以在 `values.yaml` 文件中定义,可以很容易地换为镜像地址。 18 | 19 | ``` 20 | image: {{ .Values.redisImage | quote }} 21 | ``` 22 | 23 | 镜像和标签可以在 `values.yaml` 中定义为两个单独的字段: 24 | 25 | ``` 26 | image: "{{ .Values.redisImage }}:{{ .Values.redisTag }}" 27 | ``` 28 | 29 | ## ImagePullPolicy 30 | 31 | `helm create` 设置 `imagePullPolicy` 为 `IfNotPresent`, 在 `deployment.yaml` 中: 32 | 33 | ```yaml 34 | imagePullPolicy: {{ .Values.image.pullPolicy }} 35 | ``` 36 | 37 | 和 values.yaml 中: 38 | 39 | ```yaml 40 | pullPolicy: IfNotPresent 41 | ``` 42 | 43 | 同样,Kubernetes 默认 `imagePullPolicy` 为 `IfNotPresent`,如果它根本没有被定义。如果想要的值不是 IfNotPresent,只需将 `values.yaml` 中的值更新为所需的值即可。 44 | 45 | ## PodTemplates 应声明选择器 46 | 47 | 所有的 PodTemplate 部分都应该指定一个选择器。例如: 48 | 49 | ```yaml 50 | selector: 51 | matchLabels: 52 | app.kubernetes.io/name: MyName 53 | template: 54 | metadata: 55 | labels: 56 | app.kubernetes.io/name: MyName 57 | ``` 58 | 59 | 这是一个很好的做法,因为它可以使 set 和 pod 之间保持关系。 60 | 61 | 但对于像Deployment这样的集合来说,这更为重要。如果没有这一点,整套标签将用于选择匹配的pod,如果使用的标签(如版本或发布日期)变化了,则将会导致app中断。 62 | -------------------------------------------------------------------------------- /chart_best_practices/rbac-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 基于角色的访问控制 2 | 3 | 最佳实践指南的这一部分讨论了 chart 清单中 RBAC 资源的创建和格式化。 4 | 5 | RBAC 资源是: 6 | 7 | - ServiceAccount (namespaced) 8 | - Role (namespaced) 9 | - ClusterRole 10 | - RoleBinding (namespaced) 11 | - ClusterRoleBinding 12 | 13 | ## YAML 配置 14 | RBAC 和 ServiceAccount 配置应该在单独的密钥下进行。他们是不同的东西。将 YAML 中的这两个概念拆分出来可以消除混淆并使其更清晰。 15 | 16 | 17 | ```yaml 18 | rbac: 19 | # Specifies whether RBAC resources should be created 20 | create: true 21 | 22 | serviceAccount: 23 | # Specifies whether a ServiceAccount should be created 24 | create: true 25 | # The name of the ServiceAccount to use. 26 | # If not set and create is true, a name is generated using the fullname template 27 | name 28 | ``` 29 | 30 | 此结构可以扩展到需要多个 ServiceAccounts 的更复杂的 chart。 31 | 32 | ```yaml 33 | serviceAccounts: 34 | client: 35 | create: true 36 | name: 37 | server: 38 | create: true 39 | name: 40 | ``` 41 | 42 | ## RBAC 资源应该默认创建 43 | 44 | `rbac.create` 应该是一个布尔值,控制是否创建 RBAC 资源。默认应该是 `true`。想要管理 RBAC 访问控制的用户可以将此值设置为 `false`(在这种情况下请参阅下文)。 45 | 46 | ## 使用 RBAC 资源 47 | `serviceAccount.name` 应设置为由 chart 创建的访问控制资源使用的 S`erviceAccount` 的名称。如果 `serviceAccount.create` 为 true,则应该创建一个带有该名称的 S`erviceAccount`。如果名称未设置,则使用该 `fullname` 模板生成名称,如果 `serviceAccount.create` 为 false,则不应创建该名称,但它仍应与相同的资源相关联,以便稍后通过手动创建的 RBAC 资源将引用它从而功能正常。如果 `serviceAccount.create` 为 false 且名称未指定,则使用默认的 ServiceAccount。 48 | 49 | 为 ServiceAccount 使用以下 helper 模板。 50 | 51 | ```yaml 52 | {{/* 53 | Create the name of the service account to use 54 | */}} 55 | {{- define "mychart.serviceAccountName" -}} 56 | {{- if .Values.serviceAccount.create -}} 57 | {{ default (include "mychart.fullname" .) .Values.serviceAccount.name }} 58 | {{- else -}} 59 | {{ default "default" .Values.serviceAccount.name }} 60 | {{- end -}} 61 | {{- end -}} 62 | ``` 63 | -------------------------------------------------------------------------------- /chart_best_practices/requirements-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Requirements 文件 2 | 3 | 本指南的这一部分介绍了 `requirements.yaml` 文件的最佳实践。 4 | 5 | ## 版本 6 | 在可能的情况下,使用版本范围,而不是固定到确切版本。建议的默认值是使用补丁级别的版本匹配: 7 | 8 | ```yaml 9 | version: ~1.2.3 10 | ``` 11 | 12 | 这将匹配版本 `1.2.3` 和该版本的任何补丁。换句话说,`~1.2.3` 相当于 `>= 1.2.3, < 1.3.0` 13 | 14 | 有关完整的版本匹配语法,请参阅 [semver documentation](https://github.com/Masterminds/semver#checking-version-constraints) 15 | 16 | ### 存储库 URL 17 | 18 | 如有可能,请使用 `https:// 存 ` 储库 URL,然后使用 `http://URL`。 19 | 20 | 如果存储库已添加到存储库索引文件,则存储库名称可用作 URL 的别名。使用 `alias:` 或 `@` 跟随存储库名称。 21 | 22 | 文件 URL(`file://...`)被视为对于由固定部署管道组装的 chart“特殊情况”。正式 Helm 库中是不允许在一个 r`equirements.yaml` 使用 `file://` 的。 23 | 24 | ## 条件和标签 25 | 26 | 条件或标签应添加到任何可选的依赖项中。 27 | 28 | 条件的优选形式是: 29 | 30 | 31 | ```yaml 32 | condition: somechart.enabled 33 | ``` 34 | 35 | `somechart` 是依赖的 chart 名称 36 | 37 | 当多个子 chart(依赖关系)一起提供可选或可交换功能时,这些图应共享相同的标签。 38 | 39 | 例如,如果 nginx 和 memcached 在一起,共同提供性能优化,给 chart 中的主应用程序,并要求已启用该功能时两者都存在,那么他们可能有这样的标记: 40 | 41 | ``` 42 | tags: 43 | - webaccelerator 44 | ``` 45 | 46 | 这允许用户使用一个标签打开和关闭该功能。 47 | -------------------------------------------------------------------------------- /chart_best_practices/templates-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 模板 2 | 最佳实践指南的这一部分重点介绍模板。 3 | 4 | ## templates 目录结构 5 | 6 | templates 目目录的结构应如下所示: 7 | 8 | - 如果他们产生 YAML 输出,模板文件应该有扩展名 `.yaml`。扩展名. tpl 可用于产生不需要格式化内容的模板文件。 9 | - 模板文件名应该使用横线符号(`my-example-configmap.yaml`),而不是 camelcase。 10 | - 每个资源定义应该在它自己的模板文件中。 11 | - 模板文件名应该反映名称中的资源种类。例如 `foo-pod.yaml`, `bar-svc.yaml` 12 | 13 | ## 定义模板的名称 14 | 15 | 定义的模板(在 `{{ define }}` 指令内创建的模板)可以全局访问。这意味着 chart 及其所有子 chart 都可以访问所有使用 `{{ define }}` 创建的模板。 16 | 17 | 出于这个原因,所有定义的模板名称应该是带有某个 namespace。 18 | 19 | 正确: 20 | 21 | ```yaml 22 | {{- define "nginx.fullname" }} 23 | {{ /* ... */ }} 24 | {{ end -}} 25 | ``` 26 | 27 | 不正确: 28 | 29 | ```yaml 30 | {{- define "fullname" -}} 31 | {{/* ... */}} 32 | {{ end -}} 33 | ``` 34 | 35 | 强烈建议通过 `helm create` 命令创建新 chart,因为根据此最佳做法自动定义模板名称。 36 | 37 | ## 格式化模板 38 | 39 | 模板应该使用两个空格缩进(不是制表符)。 40 | 41 | 模板指令在大括号之后和大括号之前应该有空格: 42 | 43 | 正确: 44 | 45 | ``` 46 | {{ .foo }} 47 | {{ print "foo" }} 48 | {{- print "bar" -}} 49 | ``` 50 | 51 | 不正确: 52 | 53 | ``` 54 | {{ .foo }} 55 | {{ print "foo" }} 56 | {{-print "bar"-}} 57 | ``` 58 | 59 | 模板应尽可能地填充空格: 60 | 61 | ``` 62 | foo: 63 | {{- range .Values.items }} 64 | {{ . }} 65 | {{ end -}} 66 | ``` 67 | 68 | 块(如控制结构)可以缩进以指示模板代码的流向。 69 | 70 | ``` 71 | {{ if $foo -}} 72 | {{- with .Bar}}Hello{{ end -}} 73 | {{- end -}} 74 | ``` 75 | 76 | 但是,由于 YAML 是一种面向空格的语言,因此代码缩进有时经常不能遵循该约定。 77 | 78 | ## 生成模板中的空格 79 | 80 | 最好将生成的模板中的空格保持最小。特别是,许多空行不应该彼此相邻。但偶尔空行(特别是逻辑段之间)很好。 81 | 82 | 这是最好的: 83 | 84 | ```yaml 85 | apiVersion: batch/v1 86 | kind: Job 87 | metadata: 88 | name: example 89 | labels: 90 | first: first 91 | second: second 92 | ``` 93 | 94 | 这没关系: 95 | 96 | ```yaml 97 | apiVersion: batch/v1 98 | kind: Job 99 | 100 | metadata: 101 | name: example 102 | 103 | labels: 104 | first: first 105 | second: second 106 | 107 | ``` 108 | 109 | 但这应该避免: 110 | 111 | ```yaml 112 | apiVersion: batch/v1 113 | kind: Job 114 | 115 | metadata: 116 | name: example 117 | 118 | 119 | 120 | 121 | 122 | labels: 123 | first: first 124 | 125 | second: second 126 | 127 | ``` 128 | ## Resource Naming in Templates 129 | 130 | 将 `name:` 硬编码到资源中通常被认为是不好的做法。名称对于 release 应该是唯一的。因此,我们可能希望通过插入 release 名称来生成 name 字段,例如: 131 | 132 | ```yaml 133 | apiVersion: v1 134 | kind: Service 135 | metadata: 136 | name: {{ .Release.Name }}-myservice 137 | ``` 138 | 139 | Or if there is only one resource of this kind then we could use .Release.Name or the template fullname function defined in \_helpers.tpl (which uses release name): 140 | 141 | 或者,如果只有一个此类资源,那么可以使用 .Release.Name 或 \_helpers.tpl(使用 release 名称)中定义的模板 fullname 函数: 142 | 143 | ```yaml 144 | apiVersion: v1 145 | kind: Service 146 | metadata: 147 | name: {{ template "fullname" . }} 148 | ``` 149 | 尽快如此,可能还存在不会来自固定名称的命名冲突的情况。在这些情况下,固定名称可能使应用程序更容易找到诸如服务之类的资源。如果需要固定名称,那么一种可能的管理方法是通过使用 values.yaml 中的 service.name 值来显式设置名称(如果提供的话): 150 | 151 | ```yaml 152 | apiVersion: v1 153 | kind: Service 154 | metadata: 155 | {{- if .Values.service.name }} 156 | name: {{ .Values.service.name }} 157 | {{- else }} 158 | name: {{ template "fullname" . }} 159 | {{- end }} 160 | ``` 161 | 162 | ## 注释(YAML 注释与模板注释) 163 | YAML 和头盔模板都有注释标记。 164 | 165 | YAML 注释: 166 | 167 | ```yaml 168 | # This is a comment 169 | type: sprocket 170 | ``` 171 | 172 | 模板注释: 173 | 174 | ```yaml 175 | {{- /* 176 | This is a comment. 177 | */ -}} 178 | type: frobnitz 179 | ``` 180 | 181 | 记录模板功能时应使用模板注释,如解释定义的模板: 182 | 183 | ```yaml 184 | {{- /* 185 | mychart.shortname provides a 6 char truncated version of the release name. 186 | */ -}} 187 | {{ define "mychart.shortname" -}} 188 | {{ .Release.Name | trunc 6 }} 189 | {{- end -}} 190 | 191 | ``` 192 | 193 | 在模板内部,当 Helm 用户可能(有可能)在调试过程中看到注释时,可以使用 YAML 注释。 194 | 195 | ``` 196 | # This may cause problems if the value is more than 100Gi 197 | memory: {{ .Values.maxMem | quote }} 198 | ``` 199 | 200 | 上面的注释在用户运行 `helm install --debug` 时可见,而在 `{{- /* */ -}}` 部分中指定的注释不是。 201 | 202 | ## 在模板和模板输出中使用 JSON 203 | 204 | YAML 是 JSON 的超集。在某些情况下,使用 JSON 语法可以比其他 YAML 表示更具可读性。 205 | 206 | 例如,这个 YAML 更接近表达列表的正常 YAML 方法: 207 | 208 | ```yaml 209 | arguments: 210 | - "--dirname" 211 | - "/foo" 212 | ``` 213 | 214 | 215 | 但是,当折叠为 JSON 列表样式时,它更容易阅读: 216 | 217 | ```yaml 218 | arguments: ["--dirname", "/foo"] 219 | ``` 220 | 221 | 使用 JSON 增加易读性是很好的。但是,不应该使用 JSON 语法来表示更复杂的构造。 222 | 223 | 在处理嵌入到YAML中的纯JSON时(例如init容器配置),使用JSON格式当然是合适的。 224 | -------------------------------------------------------------------------------- /chart_best_practices/values-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Values 2 | 这部分最佳实践指南涵盖了 values 的使用。在指南的这一部分,我们提供关于如何构建和使用 values 的建议,重点在于设计 chart 的 `values.yaml` 文件。 3 | 4 | ## 命名约定 5 | 变量名称应该以小写字母开头,单词应该用 camelcase 分隔: 6 | 7 | 正确写法: 8 | ```yaml 9 | chicken: true 10 | chickenNoodleSoup: true 11 | ``` 12 | 13 | 不正确写法: 14 | 15 | 16 | ```yaml 17 | Chicken: true # initial caps may conflict with built-ins 18 | chicken-noodle-soup: true # do not use hyphens in the name 19 | ``` 20 | 21 | 请注意,Helm 的所有内置变量都以大写字母开头,以便将它们与用户定义的 value 区分开来,如:`.Release.Name`, `.Capabilities.KubeVersion`。 22 | 23 | ## 展平或嵌套值 24 | 25 | YAML 是一种灵活的格式,并且值可以嵌套或扁平化。 26 | 27 | 嵌套: 28 | 29 | ```yaml 30 | server: 31 | name: nginx 32 | port: 80 33 | ``` 34 | 35 | 展平: 36 | 37 | ```yaml 38 | serverName: nginx 39 | serverPort: 80 40 | ``` 41 | 42 | 在大多数情况下,展平应该比嵌套更受青睐。原因是对模板开发人员和用户来说更简单。 43 | 44 | 为了获得最佳安全性,必须在每个级别检查嵌套值: 45 | 46 | ``` 47 | {{ if .Values.server }} 48 | {{ default "none" .Values.server.name }} 49 | {{ end }} 50 | ``` 51 | 52 | 对于每一层嵌套,都必须进行存在检查。但对于展平配置,可以跳过这些检查,使模板更易于阅读和使用。 53 | 54 | ``` 55 | {{ default "none" .Values.serverName }} 56 | ``` 57 | 58 | 当有大量相关变量时,且至少有一个是非可选的,可以使用嵌套值来提高可读性。 59 | 60 | ## 使类型清晰 61 | 62 | YAML 的类型强制规则有时是违反直觉的。例如, `foo: false` 与 `foo: "false"` 不一样。`foo: 12345678` 在某些情况下,大整数将被转换为科学记数法。 63 | 64 | 避免类型转换错误的最简单方法是明确地表示字符串,并隐含其他所有内容。或者,简而言之,引用所有字符串。 65 | 66 | 通常,为了避免整型转换问题,最好将整型存储为字符串,并在模板中使用 `{{ int $value }}` 将字符串转换为整数。 67 | 68 | 在大多数情况下,显式类型标签受到重视,所以 `foo: !!string 1234` 应该将 `1234 视 ` 为一个字符串。但是,YAML 解析器消费标签,因此类型数据在解析后会丢失。 69 | 70 | ## 考虑用户如何使用你的 values 71 | 72 | 有几种潜在的 values 来源: 73 | 74 | - chart 的 `values.yaml` 文件 75 | - 由 `helm install -f` 或 `helm upgrade -f` 提供的 value 文件 76 | - 传递给 `--set` 或的 `--set-string` 标志 `helm install` 或 `helm upgrade` 命令 77 | - 通过 `--set-file` 将 文件内容传递给 `helm install` or `helm upgrade` 78 | 79 | 在设计 value 的结构时,请记住 chart 的用户可能希望通过 `-f` 标志或 `--set ` 选项覆盖它们。 80 | 81 | 由于 `--set` 在表现力方面比较有限,编写 `values.yaml` 文件的第一个指导原则可以轻松使用 `--set` 覆盖。 82 | 83 | 出于这个原因,使用 map 来构建 value 文件通常会更好。 84 | 85 | 难以配合 `--set` 使用: 86 | 87 | ```yaml 88 | servers: 89 | - name: foo 90 | port: 80 91 | - name: bar 92 | port: 81 93 | ``` 94 | 95 | Helm `<=2.4` 时,以上不能用 `--set ` 来表示。在 Helm 2.5 中,访问 foo 上的端口是 `--set servers[0].port=80`。用户不仅难以弄清楚,而且如果稍后 servers 改变顺序,则容易出错。 96 | 97 | 使用方便: 98 | 99 | ```yaml 100 | servers: 101 | foo: 102 | port: 80 103 | bar: 104 | port: 81 105 | ``` 106 | 107 | 访问 foo 的端口更为方便:`--set servers.foo.port=80`。 108 | 109 | ## 文档'values.yaml' 110 | 111 | 应该记录'values.yaml'中的每个定义的属性。文档字符串应该以它描述的属性的名称开始,然后至少给出一个单句描述。 112 | 113 | 不正确: 114 | 115 | ``` 116 | # the host name for the webserver 117 | serverHost = example 118 | serverPort = 9191 119 | ``` 120 | 121 | 正确: 122 | 123 | ``` 124 | # serverHost is the host name for the webserver 125 | serverHost = example 126 | # serverPort is the HTTP listener port for the webserver 127 | serverPort = 9191 128 | ``` 129 | 130 | 使用参数名称开始每个注释,它使文档易于grep,并使文档工具能够可靠地将文档字符串与其描述的参数关联起来。 131 | -------------------------------------------------------------------------------- /chart_template_guide/accessing_files-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 模板内访问文件 2 | 3 | 在上一节中,我们介绍了几种创建和访问命名模板的方法。这可以很容易地从另一个模板中导入一个模板。但有时需要导入不是模板的文件,并注入其内容而不通过模板渲染器发送内容。 4 | 5 | Helm 通过 `.Files` 对象提供对文件的访问。在我们开始使用模板示例之前,需要注意一些关于它如何工作的内容: 6 | 7 | - 向 Helm chart 添加额外的文件是可以的。这些文件将被捆绑并发送给 Tiller。不过要注意,由于 Kubernetes 对象的存储限制,chart 必须小于 1M。 8 | - 通常出于安全原因,某些文件不能通过 `.Files` 对象访问。 9 | - templates / 无法访问文件。 10 | - 使用 `.helmignore` 排除的文件不能被访问。 11 | - chart 不保留 UNIX 模式信息,因此文件级权限在涉及 `.Files` 对象时不会影响文件的可用性。 12 | 13 | 14 | 15 | 16 | 17 | - [基本示例](# 基本示例) 18 | - [路径助手](# 路径助手) 19 | - [Glob 模式](#Glob 模式) 20 | - [ConfigMap 和 Secrets 工具函数](#ConfigMap 和 Secrets 工具函数) 21 | - [编码](# 编码) 22 | - [行](# 行) 23 | 24 | # 基本示例 25 | 26 | 留意这些注意事项,我们编写一个模板,从三个文件读入我们的 ConfigMap。首先,我们将三个文件添加到 chart 中,将所有三个文件直接放在 mychart / 目录中。 27 | 28 | `config1.toml`: 29 | 30 | ``` 31 | message = Hello from config 1 32 | ``` 33 | 34 | `config2.toml`: 35 | 36 | ``` 37 | message = This is config 2 38 | ``` 39 | 40 | `config3.toml`: 41 | 42 | ``` 43 | message = Goodbye from config 3 44 | ``` 45 | 46 | 这些都是一个简单的 TOML 文件(想想老派的 Windows INI 文件)。我们知道这些文件的名称,所以我们可以使用一个 range 函数来遍历它们并将它们的内容注入到我们的 ConfigMap 中。 47 | 48 | ```yaml 49 | apiVersion: v1 50 | kind: ConfigMap 51 | metadata: 52 | name: {{ .Release.Name }}-configmap 53 | data: 54 | {{- $files := .Files }} 55 | {{- range tuple "config1.toml" "config2.toml" "config3.toml" }} 56 | {{ . }}: |- 57 | {{ $files.Get . }} 58 | {{- end }} 59 | ``` 60 | 61 | 这个配置映射使用了前几节讨论的几种技术。例如,我们创建一个 `$files` 变量来保存 `.Files` 对象的引用。我们还使用该 `tuple` 函数来创建我们循环访问的文件列表。然后我们打印每个文件名(`{{.}}: |-`),然后打印文件的内容 `{{ $files.Get . }}`。 62 | 63 | 运行这个模板将产生一个包含所有三个文件内容的 ConfigMap: 64 | 65 | ```yaml 66 | # Source: mychart/templates/configmap.yaml 67 | apiVersion: v1 68 | kind: ConfigMap 69 | metadata: 70 | name: quieting-giraf-configmap 71 | data: 72 | config1.toml: |- 73 | message = Hello from config 1 74 | 75 | config2.toml: |- 76 | message = This is config 2 77 | 78 | config3.toml: |- 79 | message = Goodbye from config 3 80 | ``` 81 | 82 | ## 路径助手 83 | 84 | 在处理文件时,对文件路径本身执行一些标准操作会非常有用。为了协助这个能力,Helm 从 Go 的 [path](https://golang.org/pkg/path/) 包中导入了许多函数供使用。它们都可以使用 Go 包中的相同名称访问,但使用时小写第一个字母,例如,`Base` 变成 `base`,等等 85 | 86 | 导入的功能是: 87 | 88 | - Base 89 | - Dir 90 | - Ext 91 | - IsAbs 92 | - Clean 93 | 94 | ## Glob 模式 95 | 96 | 随着 chart 的增长,可能会发现需要组织更多地文件,因此我们提供了一种 `Files.Glob(pattern string)` 方法通过具有灵活性的模式 [glob patterns](https://godoc.org/github.com/gobwas/glob) 协助提取文件。 97 | 98 | `.Glob` 返回一个 `Files` 类型,所以可以调用 `Files` 返回对象的任何方法。 99 | 100 | 例如,想象一下目录结构: 101 | 102 | 103 | ``` 104 | foo/: 105 | foo.txt foo.yaml 106 | 107 | bar/: 108 | bar.go bar.conf baz.yaml 109 | ``` 110 | 111 | Globs 有多个方法可选择: 112 | 113 | ```yaml 114 | {{ $root := . }} 115 | {{ range $path, $bytes := .Files.Glob "**.yaml" }} 116 | {{ $path }}: |- 117 | {{ $root.Files.Get $path }} 118 | {{ end }} 119 | ``` 120 | 121 | 或 122 | 123 | ```yaml 124 | {{ range $path, $bytes := .Files.Glob "foo/*" }} 125 | {{ $path.base }}: '{{ $root.Files.Get $path | b64enc }}' 126 | {{ end }} 127 | ``` 128 | 129 | ## ConfigMap 和 Secrets 工具函数 130 | 131 | (不存在于 2.0.2 或更早的版本中) 132 | 133 | 想要将文件内容放置到 configmap 和 secret 中非常常见,以便在运行时安装到 pod 中。为了解决这个问题,我们在这个 `Files` 类型上提供了一些实用的方法。 134 | 135 | 为了进一步组织文件,将这些方法与 `Glob` 方法结合使用尤其有用。 136 | 137 | 根据上面的 [Glob](#Glob 模式) 示例中的目录结构: 138 | 139 | ```yaml 140 | apiVersion: v1 141 | kind: ConfigMap 142 | metadata: 143 | name: conf 144 | data: 145 | {{- (.Files.Glob "foo/*").AsConfig | nindent 2 }} 146 | --- 147 | apiVersion: v1 148 | kind: Secret 149 | metadata: 150 | name: very-secret 151 | type: Opaque 152 | data: 153 | {{(.Files.Glob "bar/*").AsSecrets | nindent 2 }} 154 | ``` 155 | 156 | ## 编码 157 | 158 | 我们可以导入一个文件,并使用 base64 对模板进行编码以确保成功传输: 159 | 160 | 161 | ```yaml 162 | apiVersion: v1 163 | kind: Secret 164 | metadata: 165 | name: {{ .Release.Name }}-secret 166 | type: Opaque 167 | data: 168 | token: |- 169 | {{ .Files.Get "config1.toml" | b64enc }} 170 | ``` 171 | 172 | 以上例子将采用 `config1.toml` 文件,我们之前使用的相同文件并对其进行编码: 173 | 174 | ```yaml 175 | # Source: mychart/templates/secret.yaml 176 | apiVersion: v1 177 | kind: Secret 178 | metadata: 179 | name: lucky-turkey-secret 180 | type: Opaque 181 | data: 182 | token: |- 183 | bWVzc2FnZSA9IEhlbGxvIGZyb20gY29uZmlnIDEK 184 | ``` 185 | 186 | ## 行 187 | 188 | 有时需要访问模板中文件的每一行。`Lines` 为此提供了一种方便的方法。 189 | 190 | ```yaml 191 | data: 192 | some-file.txt: {{ range .Files.Lines "foo/bar.txt" }} 193 | {{ . }}{{ end }} 194 | ``` 195 | 196 | 目前,无法将 `helm install` 期间将外部文件传递给 chart。因此,如果要求用户提供数据,则必须使用 `helm install -f` 或进行加载 `helm install --set`。 197 | 198 | 这个讨论将我们深入到写作Helm模板的工具和技术中。在下一节中,我们将看到如何使用一个特殊文件`templates/NOTES.txt`,向chart的用户发送安装后指导。 199 | -------------------------------------------------------------------------------- /chart_template_guide/builtin_objects-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 内置对象 2 | 对象从模板引擎传递到模板中。你的代码可以传递对象(我们将在说明 `with` 和 `range` 语句时看到示例)。甚至有几种方法在模板中创建新对象,就像我们稍后会看的 `tuple` 函数一样。 3 | 4 | 对象可以很简单,只有一个值。或者他们可以包含其他对象或函数。例如,`Release` 对象包含多个对象(如 `Release.Name`)并且 `Files` 对象具有一些函数。 5 | 6 | 在上一节中,我们使用 `{{ .Release.Name }}` 将 release 的名称插入到模板中。`Release` 是可以在模板中访问的顶级对象之一。 7 | 8 | - `Release`:这个对象描述了 release 本身。它里面有几个对象: 9 | - `Release.Name`:release 名称 10 | - `Release.Time`:release 的时间 11 | - `Release.Namespace`:release 的 namespace(如果清单未覆盖) 12 | - `Release.Service`:release 服务的名称(始终是 `Tiller`)。 13 | - `Release.Revision`:此 release 的修订版本号。它从 1 开始,每 `helm upgrade` 一次增加一个。 14 | - `Release.IsUpgrade`:如果当前操作是升级或回滚,则将其设置为 `true`。 15 | - `Release.IsInstall`:如果当前操作是安装,则设置为 `true`。 16 | - `Values`:从 `values.yaml` 文件和用户提供的文件传入模板的值。默认情况下,Values 是空的。 17 | - `Chart`:`Chart.yaml` 文件的内容。任何数据 Chart.yaml 将在这里访问。例如 \{\{.Chart.Name\}\}-\{\{.Chart.Version\}\} 将打印出来 mychart-0.1.0。chart 指南中 [Charts Guide](https://github.com/kubernetes/helm/blob/master/docs/charts.md#the-chartyaml-file) 列出了可用字段 18 | - `Files`:这提供对 chart 中所有非特殊文件的访问。虽然无法使用它来访问模板,但可以使用它来访问 chart 中的其他文件。请参阅 "访问文件" 部分。 19 | - `Files.Get` 是一个按名称获取文件的函数(`.Files.Get config.ini`) 20 | - `Files.GetBytes` 是将文件内容作为字节数组而不是字符串获取的函数。这对于像图片这样的东西很有用。 21 | - `Capabilities`:这提供了关于 Kubernetes 集群支持的功能的信息。 22 | - `Capabilities.APIVersions` 是一组版本信息。 23 | - `Capabilities.APIVersions.Has $version` 指示是否在群集上启用版本(`batch/v1`)。 24 | - `Capabilities.KubeVersion` 提供了查找 Kubernetes 版本的方法。它具有以下值:Major,Minor,GitVersion,GitCommit,GitTreeState,BuildDate,GoVersion,Compiler,和 Platform。 25 | - `Capabilities.TillerVersion` 提供了查找 Tiller 版本的方法。它具有以下值:SemVer,GitCommit,和 GitTreeState。 26 | - `Template`:包含有关正在执行的当前模板的信息 27 | - `Name`:到当前模板的 namespace 文件路径(例如 `mychart/templates/mytemplate.yaml`) 28 | - `BasePath`:当前 chart 模板目录的 namespace 路径(例如 mychart/templates)。 29 | 30 | 这些值可用于任何顶级模板。我们稍后会看到,这并不意味着它们将在任何地方都要有。 31 | 32 | 内置值始终以大写字母开头。这符合Go的命名约定。当你创建自己的名字时,你可以自由地使用适合你的团队的惯例。一些团队,如Kubernetes chart团队,选择仅使用首字母小写字母来区分本地名称与内置名称。在本指南中,我们遵循该约定。 33 | -------------------------------------------------------------------------------- /chart_template_guide/control_structures-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 流程控制 2 | 控制结构(模板说法中称为 “动作”)为模板作者提供了控制模板生成流程的能力。Helm 的模板语言提供了以下控制结构: 3 | 4 | - `if/else` 用于创建条件块 5 | - `with` 指定范围 6 | - `range`,它提供了一个 “for each” 风格的循环 7 | 8 | 除此之外,它还提供了一些声明和使用命名模板段的操作: 9 | 10 | - `define` 在模板中声明一个新的命名模板 11 | - `template` 导入一个命名模板 12 | - `block` 声明了一种特殊的可填写模板区域 13 | 14 | 在本节中,我们将谈论 `if`,`with` 和 `range`。其他内容在本指南后面的 “命名模板” 一节中介绍。 15 | 16 | ## if/else 17 | 18 | 我们要看的第一个控制结构是用于在模板中有条件地包含文本块。这就是 if/else 块。 19 | 20 | 条件的基本结构如下所示: 21 | 22 | ``` 23 | {{ if PIPELINE }} 24 | # Do something 25 | {{ else if OTHER PIPELINE }} 26 | # Do something else 27 | {{ else }} 28 | # Default case 29 | {{ end }} 30 | ``` 31 | 32 | 注意,我们现在讨论的是管道而不是值。其原因是要明确控制结构可以执行整个管道,而不仅仅是评估一个值。 33 | 34 | 如果值为如下情况,则管道评估为 false。 35 | 36 | - 一个布尔型的假 37 | - 一个数字零 38 | - 一个空的字符串 39 | - 一个 `nil`(空或 null) 40 | - 一个空的集合(`map`,`slice`,`tuple`,`dict`,`array`) 41 | 42 | 在其他情况下, 条件值为 _true_ 此管道被执行。 43 | 44 | 我们为 ConfigMap 添加一个简单的条件。如果饮料被设置为咖啡,我们将添加另一个设置: 45 | 46 | ```yaml 47 | apiVersion: v1 48 | kind: ConfigMap 49 | metadata: 50 | name: {{ .Release.Name }}-configmap 51 | data: 52 | myvalue: "Hello World" 53 | drink: {{ .Values.favorite.drink | default "tea" | quote }} 54 | food: {{ .Values.favorite.food | upper | quote }} 55 | {{ if and .Values.favorite.drink (eq .Values.favorite.drink "coffee") }}mug: true{{ end }} 56 | 57 | ``` 58 | 注意 `.Values.favorite.drink` 必须已定义,否则在将它与 “coffee” 进行比较时会抛出错误。由于我们在上一个例子中注释掉了 `drink:coffee`,因此输出不应该包含 `mug:true` 标志。但是如果我们将该行添加回 `values.yaml` 文件中,输出应该如下所示: 59 | 60 | ```yaml 61 | # Source: mychart/templates/configmap.yaml 62 | apiVersion: v1 63 | kind: ConfigMap 64 | metadata: 65 | name: eyewitness-elk-configmap 66 | data: 67 | myvalue: "Hello World" 68 | drink: "coffee" 69 | food: "PIZZA" 70 | mug: true 71 | ``` 72 | 73 | ## 控制空格 74 | 75 | 在查看条件时,我们应该快速查看模板中的空格控制方式。让我们看一下前面的例子,并将其格式化为更容易阅读的格式: 76 | 77 | ```yaml 78 | apiVersion: v1 79 | kind: ConfigMap 80 | metadata: 81 | name: {{ .Release.Name }}-configmap 82 | data: 83 | myvalue: "Hello World" 84 | drink: {{ .Values.favorite.drink | default "tea" | quote }} 85 | food: {{ .Values.favorite.food | upper | quote }} 86 | {{ if eq .Values.favorite.drink "coffee" }} 87 | mug: true 88 | {{ end }} 89 | ``` 90 | 91 | 最初,这看起来不错。但是如果我们通过模板引擎运行它,我们会得到一个错误的结果: 92 | 93 | ```bash 94 | $ helm install --dry-run --debug ./mychart 95 | SERVER: "localhost:44134" 96 | CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart 97 | Error: YAML parse error on mychart/templates/configmap.yaml: error converting YAML to JSON: yaml: line 9: did not find expected key 98 | ``` 99 | 100 | 发生了什么?由于上面的空格,我们生成了不正确的 YAML。 101 | 102 | ```yaml 103 | # Source: mychart/templates/configmap.yaml 104 | apiVersion: v1 105 | kind: ConfigMap 106 | metadata: 107 | name: eyewitness-elk-configmap 108 | data: 109 | myvalue: "Hello World" 110 | drink: "coffee" 111 | food: "PIZZA" 112 | mug: true 113 | ``` 114 | 115 | mug 不正确地缩进。让我们简单地缩进那行,然后重新运行: 116 | 117 | ```yaml 118 | apiVersion: v1 119 | kind: ConfigMap 120 | metadata: 121 | name: {{ .Release.Name }}-configmap 122 | data: 123 | myvalue: "Hello World" 124 | drink: {{ .Values.favorite.drink | default "tea" | quote }} 125 | food: {{ .Values.favorite.food | upper | quote }} 126 | {{ if eq .Values.favorite.drink "coffee" }} 127 | mug: true 128 | {{ end }} 129 | ``` 130 | 131 | 当我们发送该信息时,我们会得到有效的 YAML,但仍然看起来有点意思: 132 | 133 | ```yaml 134 | # Source: mychart/templates/configmap.yaml 135 | apiVersion: v1 136 | kind: ConfigMap 137 | metadata: 138 | name: telling-chimp-configmap 139 | data: 140 | myvalue: "Hello World" 141 | drink: "coffee" 142 | food: "PIZZA" 143 | 144 | mug: true 145 | 146 | ``` 147 | 148 | 请注意,我们在 YAML 中收到了一些空行。为什么?当模板引擎运行时,它将删除 `{{` 和 `}}` 中的空白内容,但是按原样保留剩余的空白。 149 | 150 | YAML 中的缩进空格是严格的,因此管理空格变得非常重要。幸运的是,Helm 模板有几个工具可以帮助我们。 151 | 152 | 首先,可以使用特殊字符修改模板声明的大括号语法,以告诉模板引擎填充空白。`{{- `(添加了破折号和空格)表示应该将格左移,而 ` -}}` 意味着应该删除右空格。注意!换行符也是空格! 153 | 154 | > 确保 `-` 和其他指令之间有空格。`{{- 3}}` 意思是 “删除左空格并打印 3”,而 `{{-3}}` 意思是 “打印 -3”。 155 | 156 | 使用这个语法,我们可以修改我们的模板来摆脱这些新行: 157 | 158 | ```yaml 159 | apiVersion: v1 160 | kind: ConfigMap 161 | metadata: 162 | name: {{ .Release.Name }}-configmap 163 | data: 164 | myvalue: "Hello World" 165 | drink: {{ .Values.favorite.drink | default "tea" | quote }} 166 | food: {{ .Values.favorite.food | upper | quote }} 167 | {{- if eq .Values.favorite.drink "coffee" }} 168 | mug: true 169 | {{- end }} 170 | ``` 171 | 172 | 为了清楚说明这一点,让我们调整上面的内容,将空格替换为 `*`, 按照此规则将每个空格将被删除。一个在该行的末尾的 `*` 指示换行符将被移除 173 | 174 | 175 | ```yaml 176 | apiVersion: v1 177 | kind: ConfigMap 178 | metadata: 179 | name: {{ .Release.Name }}-configmap 180 | data: 181 | myvalue: "Hello World" 182 | drink: {{ .Values.favorite.drink | default "tea" | quote }} 183 | food: {{ .Values.favorite.food | upper | quote }}* 184 | **{{- if eq .Values.favorite.drink "coffee"}} 185 | mug: true* 186 | **{{- end }} 187 | 188 | ``` 189 | 190 | 牢记这一点,我们可以通过 Helm 运行我们的模板并查看结果: 191 | 192 | ```yaml 193 | # Source: mychart/templates/configmap.yaml 194 | apiVersion: v1 195 | kind: ConfigMap 196 | metadata: 197 | name: clunky-cat-configmap 198 | data: 199 | myvalue: "Hello World" 200 | drink: "coffee" 201 | food: "PIZZA" 202 | mug: true 203 | ``` 204 | 205 | 小心使用 chomping 修饰符。这样很容易引起意外: 206 | 207 | 208 | ```yaml 209 | food: {{ .Values.favorite.food | upper | quote }} 210 | {{- if eq .Values.favorite.drink "coffee" -}} 211 | mug: true 212 | {{- end -}} 213 | 214 | ``` 215 | 216 | 这将会产生 food: "PIZZA"mug:true,因为删除了双方的换行符。 217 | 218 | > 有关模板中空格控制的详细信息,请参阅官方 Go 模板文档 [Official Go template documentation](https://godoc.org/text/template) 219 | 220 | 最后,有时候告诉模板系统如何缩进更容易,而不是试图掌握模板指令的间距。因此,有时可能会发现使用 `indent` 函数(`{{ indent 2 "mug:true" }}`)会很有用。 221 | 222 | ## 使用 with 修改范围 223 | 224 | 下一个要看的控制结构是 `with`。它控制着变量作用域。回想一下,`.` 是对当前范围的引用。因此,`.Values` 告诉模板在当前范围中查找 `Values` 对象。 225 | 226 | 其语法 with 类似于一个简单的 if 语句: 227 | 228 | ``` 229 | {{ with PIPELINE }} 230 | # restricted scope 231 | {{ end }} 232 | ``` 233 | 范围可以改变。with 可以允许将当前范围(`.`)设置为特定的对象。例如,我们一直在使用的 `.Values.favorites`。让我们重写我们的 ConfigMap 来改变 `.` 范围来指向 `.Values.favorites`: 234 | 235 | ```yaml 236 | apiVersion: v1 237 | kind: ConfigMap 238 | metadata: 239 | name: {{ .Release.Name }}-configmap 240 | data: 241 | myvalue: "Hello World" 242 | {{- with .Values.favorite }} 243 | drink: {{ .drink | default "tea" | quote }} 244 | food: {{ .food | upper | quote }} 245 | {{- end }} 246 | ``` 247 | 248 | 249 | 注意,现在我们可以引用 `.drink` 和 `.food` 无需对其进行限定。这是因为该 `with` 声明设置 `.` 为指向 `.Values.favorite`。在 `{{ end }}` 后 `.` 复位其先前的范围。 250 | 251 | 但是请注意!在受限范围内,此时将无法从父范围访问其他对象。例如,下面会报错: 252 | 253 | ```yaml 254 | {{- with .Values.favorite }} 255 | drink: {{ .drink | default "tea" | quote }} 256 | food: {{ .food | upper | quote }} 257 | release: {{ .Release.Name }} 258 | {{- end }} 259 | ``` 260 | 261 | 它会产生一个错误,因为 Release.Name 它不在 `.` 限制范围内。但是,如果我们交换最后两行,所有将按预期工作,因为范围在 `{{ end }}` 之后被重置。 262 | 263 | ```yaml 264 | {{- with .Values.favorite }} 265 | drink: {{ .drink | default "tea" | quote }} 266 | food: {{ .food | upper | quote }} 267 | {{- end }} 268 | release: {{ .Release.Name }} 269 | ``` 270 | 271 | 看下 `range`,我们看看模板变量,它提供了一个解决上述范围问题的方法。 272 | 273 | ## 循环 `range` 动作 274 | 275 | 许多编程语言都支持使用 `for` 循环,`foreach` 循环或类似的功能机制进行循环。在 Helm 的模板语言中,遍历集合的方式是使用 `range` 操作子。 276 | 277 | 首先,让我们在我们的 `values.yaml` 文件中添加一份披萨配料列表: 278 | 279 | ```yaml 280 | favorite: 281 | drink: coffee 282 | food: pizza 283 | pizzaToppings: 284 | - mushrooms 285 | - cheese 286 | - peppers 287 | - onions 288 | ``` 289 | 290 | 现在我们有一个列表(模板中称为 slice)pizzaToppings。我们可以修改我们的模板,将这个列表打印到我们的 ConfigMap 中: 291 | 292 | ```yaml 293 | apiVersion: v1 294 | kind: ConfigMap 295 | metadata: 296 | name: {{ .Release.Name }}-configmap 297 | data: 298 | myvalue: "Hello World" 299 | {{- with .Values.favorite }} 300 | drink: {{ .drink | default "tea" | quote }} 301 | food: {{ .food | upper | quote }} 302 | {{- end }} 303 | toppings: |- 304 | {{- range .Values.pizzaToppings }} 305 | - {{ . | title | quote }} 306 | {{- end }} 307 | 308 | ``` 309 | 让我们仔细看看 `toppings`:list。该 range 函数将遍历 pizzaToppings 列表。但现在发生了一些有趣的事. 就像 `with`sets 的范围 `.`,`range` 操作子也是一样。每次通过循环时,`.` 都设置为当前比萨饼顶部。也就是第一次 `.` 设定 mushrooms。第二个迭代它设置为 `cheese`,依此类推。 310 | 311 | 我们可以直接向管道发送 `.` 的值,所以当我们这样做时 `{{ . | title | quote }}`,它会发送 `.` 到 title(标题 case 函数),然后发送到 `quote`。如果我们运行这个模板,输出将是: 312 | 313 | ```yaml 314 | # Source: mychart/templates/configmap.yaml 315 | apiVersion: v1 316 | kind: ConfigMap 317 | metadata: 318 | name: edgy-dragonfly-configmap 319 | data: 320 | myvalue: "Hello World" 321 | drink: "coffee" 322 | food: "PIZZA" 323 | toppings: |- 324 | - "Mushrooms" 325 | - "Cheese" 326 | - "Peppers" 327 | - "Onions" 328 | ``` 329 | 330 | 现在,在这个例子中,我们碰到了一些棘手的事情。该 `toppings: |-` 行声明了一个多行字符串。所以我们的 toppings list 实际上不是 YAML 清单。这是一个很大的字符串。我们为什么要这样做?因为 ConfigMaps 中的数据 `data` 由键 / 值对组成,其中键和值都是简单的字符串。要理解这种情况,请查看 [Kubernetes ConfigMap 文档](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/).。但对我们来说,这个细节并不重要。 331 | 332 | > YAML 中的 `|-` 标记表示一个多行字符串。这可以是一种有用的技术,用于在清单中嵌入大块数据,如此处所示。 333 | 334 | 有时能快速在模板中创建一个列表,然后遍历该列表是很有用的。Helm 模板有一个功能可以使这个变得简单:`tuple`。在计算机科学中,元组是类固定大小的列表类集合,但是具有任意数据类型。这粗略地表达了 tuple 的使用方式。 335 | 336 | ```yaml 337 | sizes: |- 338 | {{- range tuple "small" "medium" "large" }} 339 | - {{ . }} 340 | {{- end }} 341 | ``` 342 | 343 | ```yaml 344 | sizes: |- 345 | - small 346 | - medium 347 | - large 348 | ``` 349 | 除了list和tuple之外,`range`还可以用于遍历具有键和值的集合(如`map` 或 `dict`)。当在下一节我们介绍模板变量时,将看到如何做到这一点。 350 | -------------------------------------------------------------------------------- /chart_template_guide/data_types-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 附录 2:Go 数据类型和模板 2 | 3 | Helm 模板语言是用强类型的 Go 编程语言实现的。出于这个原因,模板中的变量是强类型的。大多数情况下,变量为以下类型之一: 4 | 5 | - 字符串:一串文本 6 | - 布尔:`true` 或 `false` 7 | - 整数:整数值(也有 8,16,32 和 64 位有符号和无符号变体) 8 | - float64:一个 64 位浮点值(也有 8,16 和 32 位的变体) 9 | - 一个字节 slice(`[]byte`),通常用于保存(可能)二进制数据 10 | - 结构体:具有属性和方法的对象 11 | - 一个上面类型的片段(索引列表) 12 | - 一个字符串键映射(`map[string]interface{}`),其中的值是上面的类型之一 13 | 14 | Go中还有很多其他类型,有时需要在模板中进行转换。调试对象类型的最简单方法是用`printf "%t"`在模板中传递它,该模板将打印类型。另请参阅`typeOf`和`kindOf`函数。 15 | -------------------------------------------------------------------------------- /chart_template_guide/debugging-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 调试模板 2 | 3 | 调试模板可能会很棘手,因为模板在 Tiller 服务器而不是 Helm 客户端上渲染。然后渲染的模板被发送到 Kubernetes API 服务器,可能由于格式以外的原因,服务器可能会拒绝接收这些 YAML 文件。 4 | 5 | 有几个命令可以帮助您进行调试。 6 | 7 | - `helm lint` 是验证 chart 是否遵循最佳实践的首选工具 8 | - `helm install --dry-run --debug`:我们已经知道了这个窍门。这是让服务器渲染你的模板,然后返回结果清单文件的好方法。 9 | - `helm get manifest`:这是查看服务器上安装的模板的好方法。 10 | 11 | 当你的 YAML 没有解析,但想看看生成了什么时,检索 YAML 的一个简单方法是注释模板中的问题部分,然后重新运行 `helm install --dry-run --debug`: 12 | 13 | 14 | ```yaml 15 | apiVersion: v1 16 | # some: problem section 17 | # {{ .Values.foo | quote }} 18 | ``` 19 | 20 | 以上内容将被完整渲染并返回。 21 | 22 | ```yaml 23 | apiVersion: v1 24 | # some: problem section 25 | # "bar" 26 | ``` 27 | 28 | 这提供了一种快速查看生成的容的方式,而不会由于YAML分析错误而被阻止。 29 | -------------------------------------------------------------------------------- /chart_template_guide/functions_and_pipelines-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 模板函数和管道 2 | 3 | 目前为止,我们已经知道如何将信息放入模板中。但是这些信息未经修改就被放入模板中。有时我们想要转换这些数据,使得他们对我们来说更有用。 4 | 5 | 让我们从一个最佳实践开始:当从. Values 对象注入字符串到模板中时,我们引用这些字符串。我们可以通过调用 quote 模板指令中的函数来实现: 6 | 7 | ```yaml 8 | apiVersion: v1 9 | kind: ConfigMap 10 | metadata: 11 | name: {{ .Release.Name }}-configmap 12 | data: 13 | myvalue: "Hello World" 14 | drink: {{ quote .Values.favorite.drink }} 15 | food: {{ quote .Values.favorite.food }} 16 | ``` 17 | 18 | 模板函数遵循语法 `functionName arg1 arg2...`。在上面的代码片段中,`quote .Values.favorite.drink` 调用 quote 函数并将一个参数传递给它。 19 | 20 | Helm 拥有超过 60 种可用函数。其中一些是由 Go 模板语言 [Go template language](https://godoc.org/text/template) 本身定义的。其他大多数都是 Sprig 模板库 [Sprig template library](https://godoc.org/github.com/Masterminds/sprig) 的一部分。在我们讲解例子进行的过程中,我们会看到很多。 21 | 22 | > 虽然我们将 Helm 模板语言视为 Helm 特有的,但它实际上是 Go 模板语言,一些额外函数和各种包装器的组合,以将某些对象暴露给模板。Go 模板上的许多资源在了解模板时可能会有所帮助。 23 | 24 | ## 管道 25 | 26 | 模板语言的强大功能之一是其管道概念。利用 UNIX 的一个概念,管道是一个链接在一起的一系列模板命令的工具,以紧凑地表达一系列转换。换句话说,管道是按顺序完成几件事情的有效方式。我们用管道重写上面的例子。 27 | 28 | ```yaml 29 | apiVersion: v1 30 | kind: ConfigMap 31 | metadata: 32 | name: {{ .Release.Name }}-configmap 33 | data: 34 | myvalue: "Hello World" 35 | drink: {{ .Values.favorite.drink | quote }} 36 | food: {{ .Values.favorite.food | quote }} 37 | ``` 38 | 39 | 在这个例子中,没有调用 `quote ARGUMENT`,我们调换了顺序。我们使用管道(|)将 “参数” 发送给函数:`.Values.favorite.drink | quote`。使用管道,我们可以将几个功能链接在一起: 40 | 41 | ```yaml 42 | apiVersion: v1 43 | kind: ConfigMap 44 | metadata: 45 | name: {{ .Release.Name }}-configmap 46 | data: 47 | myvalue: "Hello World" 48 | drink: {{ .Values.favorite.drink | quote }} 49 | food: {{ .Values.favorite.food | upper | quote }} 50 | ``` 51 | > 反转顺序是模板中的常见做法。你会看到.`val | quote` 比 `quote .val` 更常见。练习也是。 52 | 53 | 当评估时,该模板将产生如下结果: 54 | 55 | ```yaml 56 | # Source: mychart/templates/configmap.yaml 57 | apiVersion: v1 58 | kind: ConfigMap 59 | metadata: 60 | name: trendsetting-p-configmap 61 | data: 62 | myvalue: "Hello World" 63 | drink: "coffee" 64 | food: "PIZZA" 65 | ``` 66 | 67 | 请注意,我们的原来 `pizza` 现在已经转换为 `"PIZZA"`。 68 | 69 | 当有像这样管道参数时,第一个评估(`.Values.favorite.drink`)的结果将作为函数的最后一个参数发送。我们可以修改上面的饮料示例来说明一个带有两个参数的函数 `repeat COUNT STRING`: 70 | 71 | 72 | ```yaml 73 | apiVersion: v1 74 | kind: ConfigMap 75 | metadata: 76 | name: {{ .Release.Name }}-configmap 77 | data: 78 | myvalue: "Hello World" 79 | drink: {{ .Values.favorite.drink | repeat 5 | quote }} 80 | food: {{ .Values.favorite.food | upper | quote }} 81 | ``` 82 | 83 | 该 repeat 函数将回送给定的字符串和给定的次数,所以我们将得到这个输出: 84 | 85 | ```yaml 86 | # Source: mychart/templates/configmap.yaml 87 | apiVersion: v1 88 | kind: ConfigMap 89 | metadata: 90 | name: melting-porcup-configmap 91 | data: 92 | myvalue: "Hello World" 93 | drink: "coffeecoffeecoffeecoffeecoffee" 94 | food: "PIZZA" 95 | ``` 96 | 97 | ## 使用 default 函数 98 | 99 | 经常使用的一个函数是 `default`:`default DEFAULT_VALUE GIVEN_VALUE`。该功能允许在模板内部指定默认值,以防该值被省略。让我们用它来修改上面的饮料示例: 100 | 101 | ```yaml 102 | drink: {{ .Values.favorite.drink | default "tea" | quote }} 103 | ``` 104 | 105 | 如果我们像往常一样运行,我们会得到我们的 coffee: 106 | 107 | 108 | ```yaml 109 | # Source: mychart/templates/configmap.yaml 110 | apiVersion: v1 111 | kind: ConfigMap 112 | metadata: 113 | name: virtuous-mink-configmap 114 | data: 115 | myvalue: "Hello World" 116 | drink: "coffee" 117 | food: "PIZZA" 118 | ``` 119 | 120 | 现在,我们将从以下位置删除喜欢的饮料设置 values.yaml: 121 | 122 | ```yaml 123 | favorite: 124 | #drink: coffee 125 | food: pizza 126 | ``` 127 | 128 | 现在重新运行 `helm install --dry-run --debug ./mychart` 会产生这个 YAML: 129 | 130 | ```yaml 131 | # Source: mychart/templates/configmap.yaml 132 | apiVersion: v1 133 | kind: ConfigMap 134 | metadata: 135 | name: fair-worm-configmap 136 | data: 137 | myvalue: "Hello World" 138 | drink: "tea" 139 | food: "PIZZA" 140 | ``` 141 | 142 | 在实际的 chart 中,所有静态默认值应该存在于 values.yaml 中,不应该使用该 default 命令重复(否则它们将是重复多余的)。但是,default 命令对于计算的值是合适的,因为计算值不能在 values.yaml 中声明。例如: 143 | 144 | ```yaml 145 | drink: {{ .Values.favorite.drink | default (printf "%s-tea" (include "fullname" .)) }} 146 | ``` 147 | 148 | 在一些地方,一个 `if` 条件可能比这 `default` 更适合。我们将在下一节中看到这些。 149 | 150 | 模板函数和管道是转换信息并将其插入到 YAML 中的强大方法。但有时候需要添加一些比插入字符串更复杂一些的模板逻辑。在下一节中,我们将看看模板语言提供的控制结构。 151 | 152 | ## 运算符函数 153 | 154 | 对于模板,运算符(eq,ne,lt,gt,and,or 等等)都是已实现的功能。在管道中,运算符可以用圆括号(`(` 和 `)`)分组。 155 | 156 | 将运算符放到声明的前面,后面跟着它的参数,就像使用函数一样。要多个运算符一起使用,将每个函数通过圆括号分隔。 157 | 158 | ```yaml 159 | {{/* include the body of this if statement when the variable .Values.fooString xists and is set to "foo" */}} 160 | {{ if and .Values.fooString (eq .Values.fooString "foo") }} 161 | {{ ... }} 162 | {{ end }} 163 | 164 | 165 | {{/* do not include the body of this if statement because unset variables evaluate o false and .Values.setVariable was negated with the not function. */}} 166 | {{ if or .Values.anUnsetVariable (not .Values.aSetVariable) }} 167 | {{ ... }} 168 | {{ end }} 169 | ``` 170 | 171 | 现在我们可以从函数和管道转向流控制,条件,循环和范围修饰符。 172 | -------------------------------------------------------------------------------- /chart_template_guide/getting_started-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 开始使用 chart 模板 2 | 3 | 在本指南的这部分,我们将创建一个 chart,然后添加第一个模板。我们在这里创建的 chart 将在指南的其他部分使用。 4 | 5 | 开始,我们来看一下 Helm chart。 6 | 7 | ## Charts 8 | 9 | 如 chart 指南中所述,Helm chart 的结构如下所示: 10 | 11 | ``` 12 | mychart/ 13 | Chart.yaml 14 | values.yaml 15 | charts/ 16 | templates/ 17 | ... 18 | ``` 19 | 20 | `templates/` 目录用于放置模板文件。当 Tiller 评估 chart 时,它将 `templates/` 通过模板渲染引擎发送目录中的所有文件。然后,Tiller 收集这些模板的结果并将它们发送给 Kubernetes。 21 | 22 | `values.yaml` 文件对模板也很重要。该文件包含 chart 默认值。这些值可能在用户在 `helm install` 或 `helm upgrade` 期间被覆盖。 23 | 24 | `Chart.yaml` 文件包含 chart 的说明。可以从模板中查看访问它。该 `charts/` 目录可能包含其他 chart(我们称之为子 chart)。在本指南的后面,我们将看到它们在模板渲染方面如何起作用。 25 | 26 | ## 初始 chart 27 | 28 | 对于本指南,我们将创建一个名为 mychart 的简单 chart,然后我们将在 chart 内部创建一些模板。 29 | 30 | ```bash 31 | $ helm create mychart 32 | Creating mychart 33 | ``` 34 | 35 | 从这里开始,我们将在 `mychart` 目录中工作。 36 | 37 | ### 快速看一下目录 `mychart/templates/` 38 | 39 | 看一下 `mychart/templates/` 目录,发现如下几个文件已经存在。 40 | 41 | - NOTES.txt:chart 的 “帮助文本”。这会在用户运行 `helm install` 时显示给用户。 42 | - deployment.yaml:创建 Kubernetes [deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) 的基本 manifest 43 | - service.yaml:为 deployment 创建 service 端点 [service endpoint](https://kubernetes.io/docs/concepts/services-networking/service/) 的基本 manifest 44 | - `_helpers.tpl`:放置模板助手的地方,可以在整个 chart 中重复使用 45 | 46 | 而我们要做的就是...... 全部删除它们!这样我们就可以从头开始学习我们的教程。实际上,我们将创建自己的 NOTES.txt 和_helpers.tpl。 47 | 48 | 49 | ```bash 50 | $ rm -rf mychart/templates/*.* 51 | ``` 52 | 53 | 在编写生产级 chart 时,使用这些 chart 的基本版本可能非常有用。所以在你的日常 chart 制作中,可以不删除它们。 54 | 55 | ## 第一个模板 56 | 57 | 58 | 我们要创建的第一个模板将是一个 ConfigMap。在 Kubernetes 中,ConfigMap 只是存储配置数据的地方。其他的东西,比如 Pod,可以访问 ConfigMap 中的数据。 59 | 60 | 由于 ConfigMaps 是基础资源,它们为我们提供了一个很好的起点。 61 | 62 | 我们首先创建一个名为 mychart/templates/configmap.yaml: 63 | 64 | ```yaml 65 | apiVersion: v1 66 | kind: ConfigMap 67 | metadata: 68 | name: mychart-configmap 69 | data: 70 | myvalue: "Hello World" 71 | ``` 72 | 73 | ** 提示:** 模板名称不遵循严格的命名模式。但是,我们建议 `.yaml` 为 YAML 文件后缀,`.tpl` 为模板助手后缀。 74 | 75 | 上面的 YAML 文件是一个简单的 ConfigMap,具有最少的必要字段。由于该文件位于 `templates/` 目录中,因此将通过模板引擎发送。 76 | 77 | 在 `templates/` 目录中放置一个像这样的纯 YAML 文件。当 Tiller 读取这个模板时,它会直接发送给 Kubernetes。 78 | 79 | 有了这个简单的模板,我们现在有一个可安装的 chart。我们可以像这样安装它: 80 | 81 | ```bash 82 | $ helm install ./mychart 83 | NAME: full-coral 84 | LAST DEPLOYED: Tue Nov 1 17:36:01 2016 85 | NAMESPACE: default 86 | STATUS: DEPLOYED 87 | 88 | RESOURCES: 89 | ==> v1/ConfigMap 90 | NAME DATA AGE 91 | mychart-configmap 1 1m 92 | ``` 93 | 94 | 在上面的输出中,我们可以看到我们的 ConfigMap 已经创建。使用 Helm,我们可以检索版本并查看加载的实际模板。 95 | 96 | ```bash 97 | $ helm get manifest full-coral 98 | 99 | --- 100 | # Source: mychart/templates/configmap.yaml 101 | apiVersion: v1 102 | kind: ConfigMap 103 | metadata: 104 | name: mychart-configmap 105 | data: 106 | myvalue: "Hello World" 107 | ``` 108 | 109 | 该 `helm get manifest` 命令获取 release 名称(full-coral)并打印出上传到服务器的所有 Kubernetes 资源。每个文件都以 `---` 开始作为 YAML 文档的开始,然后是一个自动生成的注释行,告诉我们该模板文件生成的这个 YAML 文档。 110 | 111 | 从那里开始,我们可以看到 YAML 数据正是我们在我们的 `configmap.yaml` 文件中所设计的 。 112 | 113 | 现在我们可以删除我们的 release:`helm delete full-coral`。 114 | 115 | ### 添加一个简单的模板调用 116 | 117 | 硬编码 `name:` 成资源通常被认为是不好的做法。名称应该是唯一的一个版本。所以我们可能希望通过插入 release 名称来生成一个名称字段。 118 | 119 | ** 提示:** name: 由于 DNS 系统的限制,该字段限制为 63 个字符。因此,release 名称限制为 53 个字符。Kubernetes 1.3 及更早版本仅限于 24 个字符(即 14 个字符名称)。 120 | 121 | 让我们改一下 `configmap.yaml`。 122 | 123 | ```yaml 124 | apiVersion: v1 125 | kind: ConfigMap 126 | metadata: 127 | name: {{ .Release.Name }}-configmap 128 | data: 129 | myvalue: "Hello World" 130 | ``` 131 | 132 | `name:` 现在这个值发生了变化成了 `{{ .Release.Name }}-configmap`。 133 | 134 | 模板指令包含在 `{{` 和 `}}` 块中。 135 | 136 | 模板指令 `{{ .Release.Name }}` 将 release 名称注入模板。传递给模板的值可以认为是 namespace 对象,其中 dot(.)分隔每个 namespace 元素。 137 | 138 | Release 前面的前一个小圆点表示我们从这个范围的最上面的 namespace 开始(我们将稍微谈一下 scope)。所以我们可以这样理解 `.Release.Name:`"从顶层命名空间开始,找到 Release 对象,然后在里面查找名为 `Name` 的对象"。 139 | 140 | 该 Release 对象是 Helm 的内置对象之一,稍后我们将更深入地介绍它。但就目前而言,这足以说明这会显示 Tiller 分配给我们发布的 release 名称。 141 | 142 | 现在,当我们安装我们的资源时,我们会立即看到使用这个模板指令的结果: 143 | 144 | ```bash 145 | $ helm install ./mychart 146 | NAME: clunky-serval 147 | LAST DEPLOYED: Tue Nov 1 17:45:37 2016 148 | NAMESPACE: default 149 | STATUS: DEPLOYED 150 | 151 | RESOURCES: 152 | ==> v1/ConfigMap 153 | NAME DATA AGE 154 | clunky-serval-configmap 1 1m 155 | ``` 156 | 157 | 注意,在该 RESOURCES 部分中,我们看到的名称 clunky-serval-configmap 不是 mychart-configmap。 158 | 159 | 可以运行 helm get manifest clunky-serval 以查看整个生成的 YAML。 160 | 161 | 现在,我们看过了基础的模板:YAML 文件嵌入了模板指令,通过 {{和}}。在下一部分中,我们将深入研究模板。但在继续之前,有一个快速技巧可以使构建模板更快:当您想测试模板渲染,但实际上没有安装任何东西时,可以使用 `helm install --debug --dry-run ./mychart`。这会将 chart 发送到 Tiller 服务器,它将渲染模板。但不是安装 chart,它会将渲染模板返回,以便可以看到输出: 162 | 163 | ```bash 164 | $ helm install --debug --dry-run ./mychart 165 | SERVER: "localhost:44134" 166 | CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart 167 | NAME: goodly-guppy 168 | TARGET NAMESPACE: default 169 | CHART: mychart 0.1.0 170 | MANIFEST: 171 | --- 172 | # Source: mychart/templates/configmap.yaml 173 | apiVersion: v1 174 | kind: ConfigMap 175 | metadata: 176 | name: goodly-guppy-configmap 177 | data: 178 | myvalue: "Hello World" 179 | 180 | ``` 181 | 182 | 使用 `--dry-run` 可以更容易地测试代码,但不能确保 Kubernetes 本身会接受生成的模板。最好不要假定你的 chart 只要 `--dry-run` 成功而被安装。 183 | 184 | 在接下来的几节中,我们将采用我们在这里定义的基本chart,并详细探索Helm模板语言。我们将开始使用内置对象。 185 | -------------------------------------------------------------------------------- /chart_template_guide/helm_ignore_file-zh_cn.md: -------------------------------------------------------------------------------- 1 | #.helmignore 文件 2 | 3 | `.helmignore` 文件用于指定不想包含在 helm chart 中的文件。 4 | 5 | 如果此文件存在,`helm package` 命令将在打包应用程序时忽略在 `.helmignore` 文件中指定的模式匹配的所有文件。 6 | 7 | 这有助于避免在 helmchart 中添加不需要或敏感的文件或目录。 8 | 9 | `.helmignore` 文件支持 Unix shell glob 匹配,相对路径匹配和否定(以!为前缀)。每行只考虑一种模式。 10 | 11 | 这是一个示例 `.helmignore` 文件: 12 | 13 | ``` 14 | # comment 15 | .git 16 | */temp* 17 | */*/temp* 18 | temp? 19 | ``` 20 | 21 | ** 我们非常欢迎你的帮助 ** 改进本文档。添加,更正或删除信息,[提出问题](https://github.com/helm/helm/issues) 或向我们发送 PR。 22 | **如果对中文版的文档有错误,或者想改进优化** 请[访问此链接](https://github.com/whmzsu/helm-doc-zh-cn/issues)。 23 | -------------------------------------------------------------------------------- /chart_template_guide/index-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Chart 模板开发人员指南 2 | 3 | 本指南介绍了 Helm 的 chart 模板,重点介绍模板语言。 4 | 5 | 模板生成 manifest 文件,它们是 Kubernetes 可以识别的 YAML 格式的资源描述。我们将了解模板的结构,如何使用,如何编写 Go 模板以及如何调试。 6 | 7 | 本指南着重介绍以下概念: 8 | 9 | - Helm 模板语言 10 | - 使用 values 11 | - 使用模板的技巧 12 | 13 | 本指南面向学习Helm模板语言的细节的人。其他指南提供介绍性材料,示例和最佳实践。 14 | -------------------------------------------------------------------------------- /chart_template_guide/named_templates-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 命名模板 2 | 3 | 现在是开始创建超过一个模板的时候了。在本节中,我们将看到如何在一个文件中定义命名模板,然后在别处使用它们。命名模板(有时称为部分或子模板)是限定在一个文件内部的模板,并起一个名称。我们有两种创建方法,以及几种不同的使用方法。 4 | 5 | 在 “流量控制” 部分中,我们介绍了声明和管理模板三个动作:`define`,`template`,和 `block`。在本节中,我们将介绍这三个动作,并介绍一个 `include` 函数,与 `template` 类似功能。 6 | 7 | 在命名模板时要注意一个重要的细节:模板名称是全局的。如果声明两个具有相同名称的模板,则最后加载一个模板是起作用的模板。由于子 chart 中的模板与顶级模板一起编译,因此注意小心地使用特定 chart 的名称来命名模板。 8 | 9 | 通用的命名约定是为每个定义的模板添加 chart 名称:`{{ define "mychart.labels" }}`。通过使用特定 chart 名称作为前缀,我们可以避免由于同名模板的两个不同 chart 而可能出现的任何冲突。 10 | 11 | ## partials 和 `_` 文件 12 | 13 | 到目前为止,我们已经使用了一个文件,一个文件包含一个模板。但 Helm 的模板语言允许创建指定的嵌入模板,可以通过名称访问。 14 | 15 | 在我们开始编写这些模板之前,有一些文件命名约定值得一提: 16 | 17 | * 大多数文件 `templates/` 被视为包含 Kubernetes manifests 18 | * `NOTES.txt` 是一个例外 19 | * 名称以下划线(`_`)开头的文件被假定为没有内部 manifest。这些文件不会渲染 Kubernetes 对象定义,而是在其他 chart 模板中随处可用以供调用。 20 | 21 | 这些文件用于存储 partials 和辅助程序。事实上,当我们第一次创建时 mychart,我们看到一个叫做文件 `_helpers.tpl`。该文件是模板 partials 的默认位置。 22 | 23 | ## 用 `define` 和 `template` 声明和使用模板 24 | 25 | 该 define 操作允许我们在模板文件内创建一个命名模板。它的语法如下所示: 26 | 27 | ```yaml 28 | {{ define "MY.NAME" }} 29 | # body of template here 30 | {{ end }} 31 | ``` 32 | 33 | 例如,我们可以定义一个模板来封装一个 Kubernetes 标签块: 34 | 35 | ```yaml 36 | {{- define "mychart.labels" }} 37 | labels: 38 | generator: helm 39 | date: {{ now | htmlDate }} 40 | {{- end }} 41 | ``` 42 | 43 | 44 | 现在我们可以将此模板嵌入到现有的 ConfigMap 中,然后将其包含在 template 操作中: 45 | 46 | ```yaml 47 | {{- define "mychart.labels" }} 48 | labels: 49 | generator: helm 50 | date: {{ now | htmlDate }} 51 | {{- end }} 52 | apiVersion: v1 53 | kind: ConfigMap 54 | metadata: 55 | name: {{ .Release.Name }}-configmap 56 | {{- template "mychart.labels" }} 57 | data: 58 | myvalue: "Hello World" 59 | {{- range $key, $val := .Values.favorite }} 60 | {{ $key }}: {{ $val | quote }} 61 | {{- end }} 62 | ``` 63 | 64 | 当模板引擎读取该文件时,它将存储引用 mychart.labels 直到 template "mychart.labels" 被调用。然后它将在文件内渲染该模板。所以结果如下所示: 65 | 66 | 67 | ```yaml 68 | # Source: mychart/templates/configmap.yaml 69 | apiVersion: v1 70 | kind: ConfigMap 71 | metadata: 72 | name: running-panda-configmap 73 | labels: 74 | generator: helm 75 | date: 2016-11-02 76 | data: 77 | myvalue: "Hello World" 78 | drink: "coffee" 79 | food: "pizza" 80 | ``` 81 | 82 | 通常,Helm chart 通常将这些模板放入 partials 文件中,通常是 `_helpers.tpl`。让我们在这里移动这个功能: 83 | 84 | ```yaml 85 | {{/* Generate basic labels */}} 86 | {{- define "mychart.labels" }} 87 | labels: 88 | generator: helm 89 | date: {{ now | htmlDate }} 90 | {{- end }} 91 | ``` 92 | 93 | 按照惯例,define 函数应该有一个简单的文档块(`{{/* ... */}}`)来描述他们所做的事情。 94 | 95 | 即使这个定义在 `_helpers.tpl`,它仍然可以在 configmap.yaml 以下位置访问: 96 | 97 | ```yaml 98 | apiVersion: v1 99 | kind: ConfigMap 100 | metadata: 101 | name: {{ .Release.Name }}-configmap 102 | {{- template "mychart.labels" }} 103 | data: 104 | myvalue: "Hello World" 105 | {{- range $key, $val := .Values.favorite }} 106 | {{ $key }}: {{ $val | quote }} 107 | {{- end }} 108 | ``` 109 | 110 | 如上所述,** 模板名称是全局的 ** 。因此,如果两个模板被命名为相同的名称,则最后一次使用的模板将被使用。由于子 chart 中的模板与顶级模板一起编译,因此最好使用 chart 专用名称命名模板。一个流行的命名约定是为每个定义的模板添加 chart 名称:`{{ define "mychart.labels" }}`。 111 | 112 | ## 设置模板的范围 113 | 114 | 在我们上面定义的模板中,我们没有使用任何对象。我们只是使用函数。让我们修改我们定义的模板以包含 chart 名称和 chart 版本: 115 | 116 | ```yaml 117 | {{/* Generate basic labels */}} 118 | {{- define "mychart.labels" }} 119 | labels: 120 | generator: helm 121 | date: {{ now | htmlDate }} 122 | chart: {{ .Chart.Name }} 123 | version: {{ .Chart.Version }} 124 | {{- end }} 125 | ``` 126 | 127 | 如果我们这样做,将不会得到我们所期望的结果: 128 | 129 | ```yaml 130 | # Source: mychart/templates/configmap.yaml 131 | apiVersion: v1 132 | kind: ConfigMap 133 | metadata: 134 | name: moldy-jaguar-configmap 135 | labels: 136 | generator: helm 137 | date: 2016-11-02 138 | chart: 139 | version: 140 | ``` 141 | 142 | 名称和版本发生了什么变化?他们不在我们定义的模板的范围内。当一个已命名的模板(用于创建 define)被渲染时,它将接收由该 template 调用传入的作用域。在我们的例子中,我们包含了这样的模板: 143 | 144 | 145 | ```yaml 146 | {{- template "mychart.labels" }} 147 | ``` 148 | 149 | 没有范围被传入,因此在模板中我们无法访问任何内容.。虽然这很容易解决。我们只需将范围传递给模板: 150 | 151 | ```yaml 152 | apiVersion: v1 153 | kind: ConfigMap 154 | metadata: 155 | name: {{ .Release.Name }}-configmap 156 | {{- template "mychart.labels" . }} 157 | ``` 158 | 159 | 请注意,我们在调用 template 时末尾传递了 `.`。我们可以很容易地通过 `.Values` 或者 `.Values.favorite` 或者我们想要的任何范围。但是我们想要的是顶级范围。 160 | 161 | 现在,当我们用 `helm install --dry-run --debug ./mychart` 执行这个模板,我们得到这个: 162 | 163 | ```yaml 164 | # Source: mychart/templates/configmap.yaml 165 | apiVersion: v1 166 | kind: ConfigMap 167 | metadata: 168 | name: plinking-anaco-configmap 169 | labels: 170 | generator: helm 171 | date: 2016-11-02 172 | chart: mychart 173 | version: 0.1.0 174 | ``` 175 | 176 | 现在 `{{ .Chart.Name }}` 解析为 `mychart`,`{{ .Chart.Version }}` 解析为 `0.1.0`。 177 | 178 | ## include 函数 179 | 180 | 假设我们已经定义了一个如下所示的简单模板: 181 | 182 | ```yaml 183 | {{- define "mychart.app" -}} 184 | app_name: {{ .Chart.Name }} 185 | app_version: "{{ .Chart.Version }}+{{ .Release.Time.Seconds }}" 186 | {{- end -}} 187 | ``` 188 | 189 | 现在我想插入到我的模板的 `labels:` 部分和 `data:` 部分: 190 | 191 | ```yaml 192 | apiVersion: v1 193 | kind: ConfigMap 194 | metadata: 195 | name: {{ .Release.Name }}-configmap 196 | labels: 197 | {{ template "mychart.app" .}} 198 | data: 199 | myvalue: "Hello World" 200 | {{- range $key, $val := .Values.favorite }} 201 | {{ $key }}: {{ $val | quote }} 202 | {{- end }} 203 | {{ template "mychart.app" . }} 204 | ``` 205 | 206 | 输出不是我们所期望的: 207 | 208 | ```yaml 209 | # Source: mychart/templates/configmap.yaml 210 | apiVersion: v1 211 | kind: ConfigMap 212 | metadata: 213 | name: measly-whippet-configmap 214 | labels: 215 | app_name: mychart 216 | app_version: "0.1.0+1478129847" 217 | data: 218 | myvalue: "Hello World" 219 | drink: "coffee" 220 | food: "pizza" 221 | app_name: mychart 222 | app_version: "0.1.0+1478129847" 223 | ``` 224 | 225 | 注意,app_version 缩进在两个地方都是错误的。为什么?因为被替换的模板具有与右侧对齐的文本。因为 `template` 是一个动作,而不是一个函数,所以没有办法将 template 调用的输出传递给其他函数; 数据只是内嵌插入。 226 | 227 | 为了解决这个问题,Helm 提供了一个替代 `template` 方案,将模板的内容导入到当前管道中,并将其传递到管道中的其函数。 228 | 229 | 这里是上面的例子,用 `indent` 纠正正确缩进 `mychart_app` 模板: 230 | 231 | ```yaml 232 | apiVersion: v1 233 | kind: ConfigMap 234 | metadata: 235 | name: {{ .Release.Name }}-configmap 236 | labels: 237 | {{ include "mychart.app" . | indent 4 }} 238 | data: 239 | myvalue: "Hello World" 240 | {{- range $key, $val := .Values.favorite }} 241 | {{ $key }}: {{ $val | quote }} 242 | {{- end }} 243 | {{ include "mychart.app" . | indent 2 }} 244 | ``` 245 | 246 | 现在生成的 YAML 每个部分都正确缩进: 247 | 248 | ```yaml 249 | # Source: mychart/templates/configmap.yaml 250 | apiVersion: v1 251 | kind: ConfigMap 252 | metadata: 253 | name: edgy-mole-configmap 254 | labels: 255 | app_name: mychart 256 | app_version: "0.1.0+1478129987" 257 | data: 258 | myvalue: "Hello World" 259 | drink: "coffee" 260 | food: "pizza" 261 | app_name: mychart 262 | app_version: "0.1.0+1478129987" 263 | ``` 264 | 265 | > 在 Helm 模板中使用 `include` 比 `template` 会更好,可以更好地为 YAML 处理输出格式。 266 | 267 | 有时我们想要导入内容,但不是作为模板。也就是说,我们要逐字输入文件。我们下一节中描述可以通过访问`.Files`的对象来读取文件。 268 | -------------------------------------------------------------------------------- /chart_template_guide/notes_files-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 创建一个 NOTES.txt 文件 2 | 在本节中,我们将看看 Helm 工具如何向你的 chart 用户提供说明。在 `helm install` 或 `helm upgrade` 结束时,Helm 可以为用户打印出一大堆有用的信息。这些信息是使用模板高度定制的。 3 | 4 | 要将安装说明添加到 chart,只需创建一个 `templates/NOTES.txt` 文件即可。这个文件是纯文本的,但是它像一个模板一样处理,并且具有所有可用的普通模板函数和对象。 5 | 6 | 我们来创建一个简单的 `NOTES.txt` 文件: 7 | 8 | ``` 9 | Thank you for installing {{ .Chart.Name }}. 10 | 11 | Your release is named {{ .Release.Name }}. 12 | 13 | To learn more about the release, try: 14 | 15 | $ helm status {{ .Release.Name }} 16 | $ helm get {{ .Release.Name }} 17 | 18 | ``` 19 | 20 | 21 | 现在,如果我们运行 `helm install ./mychart` 我们会在底部看到这条消息: 22 | 23 | ``` 24 | RESOURCES: 25 | ==> v1/Secret 26 | NAME TYPE DATA AGE 27 | rude-cardinal-secret Opaque 1 0s 28 | 29 | ==> v1/ConfigMap 30 | NAME DATA AGE 31 | rude-cardinal-configmap 3 0s 32 | 33 | 34 | NOTES: 35 | Thank you for installing mychart. 36 | 37 | Your release is named rude-cardinal. 38 | 39 | To learn more about the release, try: 40 | 41 | $ helm status rude-cardinal 42 | $ helm get rude-cardinal 43 | ``` 44 | 45 | 使用`NOTES.txt`这种方式是一种很好的方式,可以为用户提供有关如何使用新安装chart的详细信息。强烈建议创建一个文件`NOTES.txt`,尽管这不是必需的。 46 | -------------------------------------------------------------------------------- /chart_template_guide/subcharts_and_globals-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 子 chart 和全局值 2 | 3 | 到目前为止,我们只用一个 chart。但是 chart 可以有称为子 chart 的依赖关系,它们也有自己的值和模板。在本节中,我们将创建一个子 chart,并查看我们可以从模板中访问值的不同方式。 4 | 5 | 在我们深入了解代码之前,需要了解一些有关子 chart 的重要细节。 6 | 7 | - 子 chart 被认为是 “独立的”,这意味着子 chart 不能明确依赖于其父 chart。 8 | - 因此,子 chart 无法访问其父项的值。 9 | - 父 chart 可以覆盖子 chart 的值。 10 | - Helm 有全局值的概念,可以被所有 chart 访问。 11 | 12 | 当我们在本节中通过示例时,其中许多概念将变得更加清晰。 13 | 14 | ## 创建一个子 chart 15 | 16 | 对于这些练习,我们将从本指南开始时创建的 chart`mychart/` 开始,并在其中添加一个新 chart。 17 | 18 | ```bash 19 | $ cd mychart/charts 20 | $ helm create mysubchart 21 | Creating mysubchart 22 | $ rm -rf mysubchart/templates/*.* 23 | ``` 24 | 25 | 注意,和以前一样,我们删除了所有的基本模板,以便我们可以从头开始。在本指南中,我们专注于模板如何工作,而不是管理依赖关系。但 chart 指南有更多关于子 chart 工作的信息。 26 | 27 | 28 | 29 | 30 | ## 将值和模板添加到子 chart 31 | 32 | 接下来,我们为 `mysubchart`chart 创建一个简单的模板和 values 文件。应该已经有一个 values.yaml 在文件夹 mychart/charts/mysubchart 中了。我们将这样设置: 33 | 34 | ```yaml 35 | dessert: cake 36 | ``` 37 | 38 | 接下来,我们将在下面创建一个新的 ConfigMap 模板 `mychart/charts/mysubchart/templates/configmap.yaml`: 39 | 40 | ``` 41 | apiVersion: v1 42 | kind: ConfigMap 43 | metadata: 44 | name: {{ .Release.Name }}-cfgmap2 45 | data: 46 | dessert: {{ .Values.dessert }} 47 | ``` 48 | 49 | 由于每个子 chart 都是独立的 chart,因此我们可以给 mysubchart 自行测试: 50 | 51 | ```bash 52 | $ helm install --dry-run --debug mychart/charts/mysubchart 53 | SERVER: "localhost:44134" 54 | CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart/charts/mysubchart 55 | NAME: newbie-elk 56 | TARGET NAMESPACE: default 57 | CHART: mysubchart 0.1.0 58 | MANIFEST: 59 | --- 60 | # Source: mysubchart/templates/configmap.yaml 61 | apiVersion: v1 62 | kind: ConfigMap 63 | metadata: 64 | name: newbie-elk-cfgmap2 65 | data: 66 | dessert: cake 67 | ``` 68 | 69 | ## 覆盖子 chart 中的值 70 | 71 | 我们原来的 chart,`mychart` 现在是其 `mysubchart` 的父 chart,。这种关系完全是因为 mysubchart 内在 mychart/charts 目录中。 72 | 73 | 由于 mychart 是父级,我们可以指定配置 mychart 并将配置推入 mysubchart。例如,我们可以 mychart/values.yaml 像这样修改: 74 | 75 | ```yaml 76 | favorite: 77 | drink: coffee 78 | food: pizza 79 | pizzaToppings: 80 | - mushrooms 81 | - cheese 82 | - peppers 83 | - onions 84 | 85 | mysubchart: 86 | dessert: ice cream 87 | ``` 88 | 89 | 请注意最后两行。该 mysubchart 部分内的任何指令都将发送到 mysubchart chart。所以如果我们运行 helm install --dry-run --debug mychart,我们将看到的一个是 mysubchartConfigMap: 90 | 91 | ```yaml 92 | # Source: mychart/charts/mysubchart/templates/configmap.yaml 93 | apiVersion: v1 94 | kind: ConfigMap 95 | metadata: 96 | name: unhinged-bee-cfgmap2 97 | data: 98 | dessert: ice cream 99 | ``` 100 | 101 | 顶层的值现在已经覆盖了子 chart 的值。 102 | 103 | 这里有一个重要的细节需要注意。我们没有改变 mychart/charts/mysubchart/templates/configmap.yaml 模板指向 `.Values.mysubchart.dessert`。从该模板的角度来看,该值仍位于 `.Values.dessert`。随着模板引擎一起传递值,它会设置范围。所以对于 mysubchart 模板,只有指定给 mysubchart 的值才会在 `.Values` 里。 104 | 105 | 但有时候,确实希望某些值可用于所有模板。这是使用全局 chart 值完成的。 106 | 107 | ## 全局 chart 值 108 | 109 | 全局值是可以从任何 chart 或子 chart 用完全相同的名称访问的值。全局值需要明确声明。不能像使用现有的非全局值一样来使用全局值。 110 | 111 | values 数据类型有一个保留部分,称为 `Values.global`, 可以设置全局值。让我们在我们的 mychart/values.yaml 文件中设置一个。 112 | 113 | ```yaml 114 | favorite: 115 | drink: coffee 116 | food: pizza 117 | pizzaToppings: 118 | - mushrooms 119 | - cheese 120 | - peppers 121 | - onions 122 | 123 | mysubchart: 124 | dessert: ice cream 125 | 126 | global: 127 | salad: caesar 128 | ``` 129 | 130 | 因为这样全局值的使用方法,`mychart/templates/configmap.yaml` 和 `mychart/charts/mysubchart/templates/configmap.yaml` 都能够访问该值 `{{ .Values.global.salad }}`。 131 | 132 | `mychart/templates/configmap.yaml`: 133 | 134 | ```yaml 135 | apiVersion: v1 136 | kind: ConfigMap 137 | metadata: 138 | name: {{ .Release.Name }}-configmap 139 | data: 140 | salad: {{ .Values.global.salad }} 141 | ``` 142 | 143 | `mysubchart/templates/configmap.yaml`: 144 | 145 | ```yaml 146 | apiVersion: v1 147 | kind: ConfigMap 148 | metadata: 149 | name: {{ .Release.Name }}-cfgmap2 150 | data: 151 | dessert: {{ .Values.dessert }} 152 | salad: {{ .Values.global.salad }} 153 | ``` 154 | 155 | 现在,如果我们运行 dry run,我们会在两个输出中看到相同的值: 156 | 157 | ```yaml 158 | # Source: mychart/templates/configmap.yaml 159 | apiVersion: v1 160 | kind: ConfigMap 161 | metadata: 162 | name: silly-snake-configmap 163 | data: 164 | salad: caesar 165 | 166 | --- 167 | # Source: mychart/charts/mysubchart/templates/configmap.yaml 168 | apiVersion: v1 169 | kind: ConfigMap 170 | metadata: 171 | name: silly-snake-cfgmap2 172 | data: 173 | dessert: ice cream 174 | salad: caesar 175 | ``` 176 | 177 | 全局变量对于传递这样的信息非常有用,但它确实需要一些计划来确保将正确的模板配置为使用全局变量。 178 | 179 | ## 与子 chart 共享模板 180 | 181 | 父 chart 和子 chart 可以共享模板。任何 chart 中的任何定义块都可用于其他 chart。 182 | 183 | 例如,我们可以像这样定义一个简单的模板: 184 | 185 | 186 | ```yaml 187 | {{ - define "labels" }}from: mychart{{ end }} 188 | ``` 189 | 190 | 回想一下模板上的标签是如何全局共享的。因此,`labels` chart 可以包含在其他 chart 中。 191 | 192 | 尽管 chart 开发人员可以选择 `include` 和 `template`, 使用 `include` 的一个优点是,include 可以动态地引用模板: 193 | 194 | ```yaml 195 | {{ include $mytemplate }} 196 | ``` 197 | 198 | 以上例子不会引用 $mytemplate。`template` 相反,将只接受一个字符串。 199 | 200 | ## 避免使用块 201 | Go 模板语言提供了一个 `block` 关键字,允许开发人员提供一个默认的实现,后续将被覆盖。在 Helm chart 中,块不是重写的最佳工具,因为如果提供了同一个块的多个实现,那么所选哪个是不可预知的。 202 | 203 | 建议是改为使用`include`。 204 | -------------------------------------------------------------------------------- /chart_template_guide/values_files-zh_cn.md: -------------------------------------------------------------------------------- 1 | # values 文件 2 | 在上一节中,我们看了 Helm 模板提供的内置对象。四个内置对象之一是 Values。该对象提供对传入 chart 的值的访问。其内容来自四个来源: 3 | 4 | - chart 中的 `values.yaml` 文件 5 | - 如果这是一个子 chart,来自父 chart 的 `values.yaml` 文件 6 | - value 文件通过 helm install 或 helm upgrade 的 - f 标志传入文件(`helm install -f myvals.yaml ./mychart`) 7 | - 通过 `--set`(例如 `helm install --set foo=bar ./mychart`) 8 | 9 | 上面的列表按照特定的顺序排列:values.yaml 在默认情况下,父级 chart 的可以覆盖该默认级别,而该 chart values.yaml 又可以被用户提供的 values 文件覆盖,而该文件又可以被 --set 参数覆盖。 10 | 11 | 值文件是纯 YAML 文件。我们编辑 `mychart/values.yaml`,然后来编辑我们的 `ConfigMap` 模板。 12 | 13 | 删除默认带的 values.yaml,我们只设置一个参数: 14 | 15 | ```yaml 16 | favoriteDrink: coffee 17 | ``` 18 | 19 | 现在我们可以在模板中使用这个: 20 | 21 | ```yaml 22 | apiVersion: v1 23 | kind: ConfigMap 24 | metadata: 25 | name: {{ .Release.Name }}-configmap 26 | data: 27 | myvalue: "Hello World" 28 | drink: {{ .Values.favoriteDrink }} 29 | ``` 30 | 31 | 注意我们在最后一行 32 | ```yaml 33 | {{ .Values.favoriteDrink }} 34 | ``` 35 | 获取 `favoriteDrink` 的值。 36 | 37 | 让我们看看这是如何渲染的。 38 | 39 | ```bash 40 | $ helm install --dry-run --debug ./mychart 41 | SERVER: "localhost:44134" 42 | CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart 43 | NAME: geared-marsupi 44 | TARGET NAMESPACE: default 45 | CHART: mychart 0.1.0 46 | MANIFEST: 47 | --- 48 | # Source: mychart/templates/configmap.yaml 49 | apiVersion: v1 50 | kind: ConfigMap 51 | metadata: 52 | name: geared-marsupi-configmap 53 | data: 54 | myvalue: "Hello World" 55 | drink: coffee 56 | ``` 57 | 58 | 由于 `favoriteDrink` 在默认 `values.yaml` 文件中设置为 `coffee`,这就是模板中显示的值。我们可以轻松地在我们的 helm install 命令中通过加一个 `--set` 添标志来覆盖: 59 | 60 | ```bash 61 | helm install --dry-run --debug --set favoriteDrink=slurm ./mychart 62 | SERVER: "localhost:44134" 63 | CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart 64 | NAME: solid-vulture 65 | TARGET NAMESPACE: default 66 | CHART: mychart 0.1.0 67 | MANIFEST: 68 | --- 69 | # Source: mychart/templates/configmap.yaml 70 | apiVersion: v1 71 | kind: ConfigMap 72 | metadata: 73 | name: solid-vulture-configmap 74 | data: 75 | myvalue: "Hello World" 76 | drink: slurm 77 | ``` 78 | 79 | 由于 `--set` 比默认 `values.yaml` 文件具有更高的优先级,我们的模板生成 `drink: slurm`。 80 | 81 | values 文件也可以包含更多结构化内容。例如,我们在 values.yaml 文件中可以创建 `favorite` 部分,然后在其中添加几个键: 82 | 83 | ```yaml 84 | favorite: 85 | drink: coffee 86 | food: pizza 87 | ``` 88 | 89 | 现在我们稍微修改模板: 90 | 91 | ```yaml 92 | apiVersion: v1 93 | kind: ConfigMap 94 | metadata: 95 | name: {{ .Release.Name }}-configmap 96 | data: 97 | myvalue: "Hello World" 98 | drink: {{ .Values.favorite.drink }} 99 | food: {{ .Values.favorite.food }} 100 | ``` 101 | 102 | 虽然以这种方式构建数据是可以的,但建议保持 value 树浅一些,平一些。当我们看看为子 chart 分配值时,我们将看到如何使用树结构来命名值。 103 | 104 | ## 删除默认 key 105 | 106 | 如果您需要从默认值中删除一个键,可以覆盖该键的值为 null,在这种情况下,Helm 将从覆盖值合并中删除该键。 107 | 108 | 例如,stable 版本的 Drupal chart 允许配置 liveness 探测器,如果你配置自定义的 image。以下是默认值: 109 | 110 | ```yaml 111 | livenessProbe: 112 | httpGet: 113 | path: /user/login 114 | port: http 115 | initialDelaySeconds: 120 116 | ``` 117 | 118 | 如果尝试覆盖 liveness Probe 处理程序 `exec` 而不是 `httpGet`,使用 `--set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt]`,Helm 会将默认和重写的键合并在一起,从而产生以下 YAML: 119 | 120 | ```yaml 121 | livenessProbe: 122 | httpGet: 123 | path: /user/login 124 | port: http 125 | exec: 126 | command: 127 | - cat 128 | - docroot/CHANGELOG.txt 129 | initialDelaySeconds: 120 130 | ``` 131 | 132 | 但是,Kubernetes 会报错,因为无法声明多个 liveness Probe 处理程序。为了克服这个问题,你可以指示 Helm 过将 livenessProbe.httpGet 通设置为空来删除它: 133 | 134 | ```bash 135 | helm install stable/drupal --set image=my-registry/drupal:0.1.0 --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] --set livenessProbe.httpGet=null 136 | ``` 137 | 138 | 到这里,我们已经看到了几个内置对象,并用它们将信息注入到模板中。现在我们来看看模板引擎的另外内容:函数和管道。 139 | -------------------------------------------------------------------------------- /chart_template_guide/variables-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 变量 2 | 我们已经了解了函数,管道,对象和控制结构,我们可以在许多编程语言中找到更基本的用法之一:变量。在模板中,它们使用的频率较低。我们将看到如何使用它们来简化代码,并更好地使用 `with` 和 `range`。 3 | 4 | 在前面的例子中,我们看到这段代码会失败: 5 | 6 | 7 | ```yaml 8 | {{- with .Values.favorite}} 9 | drink: {{ .drink | default "tea" | quote }} 10 | food: {{ .food | upper | quote }} 11 | release: {{ .Release.Name }} 12 | {{- end }} 13 | ``` 14 | 15 | `Release.Name` 不在该 `with` 块中限制的范围内。解决范围问题的一种方法是将对象分配给可以在不考虑当前范围的情况下访问的变量。 16 | 17 | 在 Helm 模板中,变量是对另一个对象的命名引用。它遵循这个形式 `$name`。变量被赋予一个特殊的赋值操作符:`:=`。我们可以使用变量重写上面的 Release.Name。 18 | 19 | ```yaml 20 | apiVersion: v1 21 | kind: ConfigMap 22 | metadata: 23 | name: {{.Release.Name}}-configmap 24 | data: 25 | myvalue: "Hello World" 26 | {{- $relname := .Release.Name -}} 27 | {{- with .Values.favorite }} 28 | drink: {{ .drink | default "tea" | quote }} 29 | food: {{ .food | upper | quote }} 30 | release: {{ $relname }} 31 | {{- end }} 32 | ``` 33 | 34 | 注意,在我们开始 `with` 块之前,我们赋值 `$relname := `.Release.Name。现在在 `with` 块内部,`$relname` 变量仍然指向发布名称。 35 | 36 | 会产生这样的结果: 37 | 38 | ```yaml 39 | # Source: mychart/templates/configmap.yaml 40 | apiVersion: v1 41 | kind: ConfigMap 42 | metadata: 43 | name: viable-badger-configmap 44 | data: 45 | myvalue: "Hello World" 46 | drink: "coffee" 47 | food: "PIZZA" 48 | release: viable-badger 49 | ``` 50 | 51 | 变量在 `range` 循环中特别有用。它们可以用于类似列表的对象以同时捕获索引和值: 52 | 53 | 54 | ```yaml 55 | toppings: |- 56 | {{- range $index, $topping := .Values.pizzaToppings }} 57 | {{ $index }}: {{ $topping }} 58 | {{- end }} 59 | 60 | ``` 61 | 62 | 注意,`range` 首先是变量,然后是赋值运算符,然后是列表。这将分配整数索引(从零开始)给 `$index`,值给 `$topping`。运行它将产生: 63 | 64 | ```yaml 65 | toppings: |- 66 | 0: mushrooms 67 | 1: cheese 68 | 2: peppers 69 | 3: onions 70 | ``` 71 | 72 | 对于同时具有键和值的数据结构,我们可以使用 `range` 来获得两者。例如,我们可以对 `.Values.favorite` 像这样循环: 73 | 74 | ```yaml 75 | apiVersion: v1 76 | kind: ConfigMap 77 | metadata: 78 | name: {{ .Release.Name }}-configmap 79 | data: 80 | myvalue: "Hello World" 81 | {{- range $key, $val := .Values.favorite}} 82 | {{ $key }}: {{ $val | quote }} 83 | {{- end }} 84 | ``` 85 | 86 | 现在在第一次迭代中,`$key` 是 `drink`,`$val` 是 `coffee`,第二次,`$key` 是 food,`$val` 会 pizza。运行上面的代码会生成下面这个: 87 | 88 | ```yaml 89 | # Source: mychart/templates/configmap.yaml 90 | apiVersion: v1 91 | kind: ConfigMap 92 | metadata: 93 | name: eager-rabbit-configmap 94 | data: 95 | myvalue: "Hello World" 96 | drink: "coffee" 97 | food: "pizza" 98 | ``` 99 | 100 | 变量通常不是 “全局” 的。它们的范围是它们所在的块。之前,我们在模板的顶层赋值 `$relname`。该变量将在整个模板的范围内起作用。但在我们的最后一个例子中,`$key` 和 `$val` 只会在该 `{{ range... }}{{ end }}` 块的范围内起作用。 101 | 102 | 然而,总有一个变量是全局 `$` 变量 - 这个变量总是指向根上下文。当你在需要知道 chart 发行名称的范围内循环时,这非常有用。 103 | 104 | 举例说明: 105 | 106 | ```yaml 107 | {{- range .Values.tlsSecrets }} 108 | apiVersion: v1 109 | kind: Secret 110 | metadata: 111 | name: {{ .name }} 112 | labels: 113 | # Many helm templates would use `.` below, but that will not work, 114 | # however `$` will work here 115 | app.kubernetes.io/name: {{ template "fullname" $ }} 116 | # I cannot reference .Chart.Name, but I can do $.Chart.Name 117 | helm.sh/chart: "{{ $.Chart.Name }}-{{ $.Chart.Version }}" 118 | app.kubernetes.io/instance: "{{ $.Release.Name }}" 119 | # Value from appVersion in Chart.yaml 120 | app.kubernetes.io/version: "{{ $.Chart.AppVersion }}" 121 | app.kubernetes.io/managed-by: "{{ $.Release.Service }}" 122 | type: kubernetes.io/tls 123 | data: 124 | tls.crt: {{ .certificate }} 125 | tls.key: {{ .key }} 126 | --- 127 | {{- end }} 128 | ``` 129 | 130 | 到目前为止,我们只查看了一个文件中声明的一个模板。但是Helm模板语言的强大功能之一是它能够声明多个模板并将它们一起使用。我们将在下一节中讨论。 131 | -------------------------------------------------------------------------------- /chart_template_guide/wrapping_up-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 总结 2 | 本指南旨在为你提供 chart 开发人员对如何使用 Helm 模板语言的深入了解。本指南着重介绍模板开发的技术方面。 3 | 4 | 但是当谈到 chart 的实际日常开发时,本指南还没有涉及很多事情。以下是一些有用的指向其他文档的指南,这些指南将帮助您创建新 chart: 5 | 6 | - Kubernetes chart 项目 [Helm Charts project](https://github.com/helm/charts) 是 chart 不可缺少的来源。该项目也是 chart 开发中最佳实践的标准。 7 | - Kubernetes [Documentation](https://kubernetes.io/docs/home/) 提供了可以使用的各种资源类型的详细示例,从 ConfigMaps 和 Secrets 到 DaemonSetkubernetes 和 Deployments。 8 | - Helm chart 指南 [Charts Guide](../chart/charts-zh_cn.md) 介绍了使用 chart 的工作流程。 9 | - Helm Chart Hooks 指南 [Chart Hooks Guide](../chart/charts_hooks-zh_cn.md) 解释了如何创建生命周期 hook。 10 | - Helm chart 技巧和窍门文章 [Chart Hooks Guide](../chart/charts_hooks-zh_cn.md) 提供了一些写 chart 的有用技巧。 11 | - [Sprig documentation](https://github.com/Masterminds/sprig) 文档介绍了提供了六十余的模板功能。 12 | - 在 Go 模板 [Go template docs](https://godoc.org/text/template) 文档详细解释模板语法。 13 | - Schelm 工具 [Schelm tool](https://github.com/databus23/schelm) 是用于调试 chart 一个很好的帮手工具。 14 | 15 | 有时候,问几个问题, 并从经验丰富的开发人员那里获得答案会更容易。最好的地方是在 [Kubernetes Slack](https://kubernetes.slack.com) Helm 频道: 16 | 17 | - [#helm-users](https://kubernetes.slack.com/messages/helm-users) 18 | - [#helm-dev](https://kubernetes.slack.com/messages/helm-dev) 19 | - [#charts](https://kubernetes.slack.com/messages/charts) 20 | 21 | 最后,如果在本文中发现错误或遗漏,想要推荐一些新内容或希望参与,请访问Helm项目[The Helm Project](https://github.com/helm)。 22 | -------------------------------------------------------------------------------- /chart_template_guide/yaml_techniques-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 附录1:YAML技巧 2 | 3 | 本指南的大部分内容都集中在编写模板语言。在这里,我们将看看YAML格式。YAML具有一些有用的特性,可以让我们作为模板的作者,可以使我们的模板更少出错并更易于阅读。 4 | 5 | ## 标量和集合 6 | 7 | 根据YAML规范[YAML spec](http://yaml.org/spec/1.2/spec.html),有两种类型的集合,以及许多标量类型。 8 | 9 | 这两种类型的集合是maps和sequence: 10 | 11 | ```yaml 12 | map: 13 | one: 1 14 | two: 2 15 | three: 3 16 | 17 | sequence: 18 | - one 19 | - two 20 | - three 21 | ``` 22 | 23 | 标量值是单个值(与集合相对) 24 | 25 | ### YAML中的标量类型 26 | 27 | 在Helm的YAML语言中,值的标量数据类型由一组复杂的规则确定,包括用于资源定义的Kubernetes schema。但是,在推断类型时,以下规则成立。 28 | 29 | 如果一个整数或浮点数是不加引号的单词,它通常被视为一个数字类型: 30 | 31 | ```yaml 32 | count: 1 33 | size: 2.34 34 | ``` 35 | 36 | 但如果他们被引号括起来,他们被视为字符串: 37 | 38 | ```yaml 39 | count: "1" # <-- string, not int 40 | size: '2.34' # <-- string, not float 41 | ``` 42 | 43 | 44 | 布尔值也是如此: 45 | 46 | ```yaml 47 | isGood: true # bool 48 | answer: "true" # string 49 | ``` 50 | 51 | 空值的词是null(not nil)。 52 | 53 | 请注意,这`port: "80"`是有效的YAML,并且将通过模板引擎和YAML分析器,但如果Kubernetes预期port为整数,则会失败。 54 | 55 | 在某些情况下,您可以使用YAML节点标签强制进行特定的类型推断: 56 | 57 | ```yaml 58 | coffee: "yes, please" 59 | age: !!str 21 60 | port: !!int "80" 61 | ``` 62 | 63 | 在上面,`!!str`告诉解析器`age`是一个字符串,即使它看起来像一个int。而`port`被视为一个int,即使它被引号括起来。 64 | 65 | ## YAML中的字符串 66 | 67 | 我们放在YAML文档中的大部分数据都是字符串。YAML有多种表示字符串的方式。本节将介绍这些方法并演示如何使用其中的一些方法。 68 | 69 | 有三种内置方式来声明一个字符串: 70 | 71 | ```yaml 72 | way1: bare words 73 | way2: "double-quoted strings" 74 | way3: 'single-quoted strings' 75 | ``` 76 | 77 | 所有内置样式必须位于同一行上。 78 | 79 | - 单词没有被引用,并且没有escape。出于这个原因,你必须小心你使用什么字符。 80 | - 双引号的字符串可以使用特定的字符`\`进行转义。例如`"\"Hello\", she said"`。你也可以用换行符换行`\n`。 81 | - 单引号字符串是“文字”字符串,并且不使用`\`转义字符。唯一的转义序列是`''`,它被解码为一个单独的`'`。 82 | 83 | 除了单行字符串外,还可以声明多行字符串: 84 | 85 | ```yaml 86 | coffee: | 87 | Latte 88 | Cappuccino 89 | Espresso 90 | ``` 91 | 92 | 以上将把`coffee`的值视为等价于单独字符串`Latte\nCappuccino\nEspresso\n`。 93 | 94 | 请注意,|必须后的第一行正确缩进。所以我们可以通过这样做来破坏上面的例子: 95 | 96 | ```yaml 97 | coffee: | 98 | Latte 99 | Cappuccino 100 | Espresso 101 | 102 | ``` 103 | 104 | 由于Latte不正确缩进,我们会得到如下错误: 105 | 106 | ``` 107 | Error parsing file: error converting YAML to JSON: yaml: line 7: did not find expected key 108 | ``` 109 | 110 | 在模板中,为了防止出现上述错误,在多行文档中放置假“第一行”内容有时更安全: 111 | 112 | ```yaml 113 | coffee: | 114 | # Commented first line 115 | Latte 116 | Cappuccino 117 | Espresso 118 | 119 | ``` 120 | 121 | 请注意,无论第一行是什么,它都将保留在字符串的输出中。因此,例如,如果使用这种技术将文件内容注入到ConfigMap中,那么该注释应该是任何正在读取该条目的预期类型。 122 | 123 | ### 控制多行字符串中的空格 124 | 125 | 在上面的例子中,我们用来`|`表示一个多行字符串。但请注意,我们的字符串的内容后跟着`\n`。如果我们希望YAML处理器去掉尾随的换行符,我们可以在`|`后添加`-`: 126 | 127 | ```yaml 128 | coffee: |- 129 | Latte 130 | Cappuccino 131 | Espresso 132 | ``` 133 | 134 | 现在的`coffee`值将是:`Latte\nCappuccino\nEspresso`(没有尾随 `\n`)。 135 | 136 | 其他时候,我们可能希望保留所有尾随空格。我们可以用`|+`符号来做到这一点: 137 | 138 | ```yaml 139 | coffee: |+ 140 | Latte 141 | Cappuccino 142 | Espresso 143 | 144 | 145 | another: value 146 | ``` 147 | 148 | 现在的值`coffee`将会是`Latte\nCappuccino\nEspresso\n\n\n`。 149 | 150 | 文本块内部的缩进被保留,并保留换行符: 151 | 152 | ``` 153 | coffee: |- 154 | Latte 155 | 12 oz 156 | 16 oz 157 | Cappuccino 158 | Espresso 159 | ``` 160 | 161 | 在上述情况下,`coffee`将是`Latte\n 12 oz\n 16 oz\nCappuccino\nEspresso`。 162 | 163 | ### 缩进和模板 164 | 165 | 在编写模板时,可能会发现自己希望将文件内容注入模板。正如我们在前几章中看到的,有两种方法可以做到这一点: 166 | 167 | - 使用{\{ .Files.Get "FILENAME" }\}得到chart中的文件的内容。 168 | - 使用{\{ include "TEMPLATE" . \}}渲染模板,然后其内容放入chart。 169 | 170 | 将文件插入YAML时,最好理解上面的多行规则。通常情况下,插入静态文件的最简单方法是做这样的事情: 171 | 172 | ```yaml 173 | myfile: | 174 | {{ .Files.Get "myfile.txt" | indent 2 }} 175 | ``` 176 | 177 | 请注意我们如何执行上面的缩进:`indent 2`告诉模板引擎使用两个空格缩进“myfile.txt”中的每一行。请注意,我们不缩进该模板行。那是因为如果我们做了,第一行的文件内容会缩进两次。 178 | 179 | ### 折叠多行字符串 180 | 181 | 有时候你想在你的YAML中用多行代表一个字符串,但是当它被解释时,要把它当作一个长行。这被称为“折叠”。要声明一个折叠块,使用`>`代替`|`: 182 | 183 | ```yaml 184 | coffee: > 185 | Latte 186 | Cappuccino 187 | Espresso 188 | 189 | 190 | ``` 191 | 192 | `coffee`的值将会是`Latte Cappuccino Espresso\n`。请注意,除最后一个换行符之外的所有内容都将转换为空格。您可以将空格控件与折叠文本标记组合起来,因此·将替换或去掉所有换行符。 193 | 194 | 请注意,在折叠语法中,缩进文本将导致行被保留。 195 | 196 | ```yaml 197 | coffee: >- 198 | Latte 199 | 12 oz 200 | 16 oz 201 | Cappuccino 202 | Espresso 203 | ``` 204 | 205 | 以上将产生`Latte\n 12 oz\n 16 oz\nCappuccino Espresso`。请注意,空格和换行符都还在那里。 206 | 207 | ## 将多个文档嵌入到一个文件中 208 | 209 | 可以将多个YAML文档放入单个文件中。这是通过在一个新文档前加`---`,在文档结束加`...`来完成的 210 | 211 | 212 | ```yaml 213 | 214 | --- 215 | document:1 216 | ... 217 | --- 218 | document: 2 219 | ... 220 | ``` 221 | 222 | 在许多情况下,无论是`---`或`...`可被省略。 223 | 224 | Helm中的某些文件不能包含多个文档。例如,如果文件内部提供了多个`values.yaml`文档,则只会使用第一个文档。 225 | 226 | 但是,模板文件可能有多个文档。发生这种情况时,文件(及其所有文档)在模板渲染期间被视为一个对象。但是,最终的YAML在被送到Kubernetes之前被分成多个文件。 227 | 228 | 我们建议每个文件在绝对必要时才使用多个文档。在一个文件中有多个文件可能很难调试。 229 | 230 | ## YAML是JSON的Superset 231 | 232 | 因为YAML是JSON的超集,所以任何有效的JSON文档都应该是有效的YAML。 233 | 234 | ```json 235 | { 236 | "coffee": "yes, please", 237 | "coffees": [ 238 | "Latte", "Cappuccino", "Espresso" 239 | ] 240 | } 241 | ``` 242 | 243 | 以上是下面另一种表达方式: 244 | 245 | ```yaml 246 | coffee: yes, please 247 | coffees: 248 | - Latte 249 | - Cappuccino 250 | - Espresso 251 | ``` 252 | 253 | 这两者可以混合使用(小心使用): 254 | 255 | ```yaml 256 | coffee: "yes, please" 257 | coffees: [ "Latte", "Cappuccino", "Espresso"] 258 | ``` 259 | 260 | 所有这三个都应该解析为相同的内部表示。 261 | 262 | 虽然这意味着诸如`values.yaml`可能包含JSON数据的文件,但Helm不会将文件扩展名`.json`视为有效的后缀。 263 | 264 | ## YAML锚 265 | 266 | YAML规范提供了一种方法来存储对某个值的引用,并稍后通过引用来引用该值。YAML将此称为“锚定”: 267 | 268 | ```yaml 269 | coffee: "yes, please" 270 | favorite: &favoriteCoffee "Cappucino" 271 | coffees: 272 | - Latte 273 | - *favoriteCoffee 274 | - Espresso 275 | ``` 276 | 277 | 在上面,`&favoriteCoffee`设置一个引用到`Cappuccino`。之后,该引用被用作`*favoriteCoffee`。所以coffees变成了 `Latte, Cappuccino, Espresso`。 278 | 279 | 虽然在少数情况下锚点是有用的,但它们的一个方面可能导致细微的错误:第一次使用YAML时,引用被扩展,然后被丢弃。 280 | 281 | 所以如果我们要解码然后重新编码上面的例子,那么产生的YAML将是: 282 | 283 | ```yaml 284 | coffee: yes, please 285 | favorite: Cappucino 286 | coffees: 287 | - Latte 288 | - Cappucino 289 | - Espresso 290 | ``` 291 | 292 | 因为Helm和Kubernetes经常读取,修改并重写YAML文件,锚将会丢失。 293 | -------------------------------------------------------------------------------- /content.md: -------------------------------------------------------------------------------- 1 | - 用户指南 2 | - [快速入门](quickstart/quickstart-zh_cn.md) 3 | - [安装](quickstart/install-zh_cn.md) 4 | - [Kubernetes发行版](quickstart/kubernetes_distros-zh_cn.md) 5 | - [安装FAQ](quickstart/install_faq-zh_cn.md) 6 | - [使用Helm](quickstart/using_helm-zh_cn.md) 7 | - [插件](quickstart/plugins-zh_cn.md) 8 | - [RBAC](quickstart/rbac-zh_cn.md) 9 | - [安全安装](quickstart/securing_installation-zh_cn.md) 10 | - Helm命令参考 11 | - Charts 12 | - charts.md 13 | - charts_hooks.md 14 | - charts_tips_and_tricks.md 15 | - charts_repository.md 16 | - 开发模板 17 | - 最佳实践 18 | - 相关项目和文档 19 | - Kubernetes Helm 架构 20 | - 开发指南 21 | - 项目历史 22 | - 术语表 23 | - 何处寻找Charts 24 | -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whmzsu/helm-doc-zh-cn/9af4e23d9267374845d8eadcc1f49862cf4ba926/cover.jpg -------------------------------------------------------------------------------- /developers-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 开发者指南 2 | 3 | 本指南解释了如何设置环境来开发 Helm 和 Tiller。 4 | 5 | ## 前提条件 6 | - Go 的最新版本 7 | - 最新版本的 Glide 8 | - Kubernetes 集群和 kubectl(可选) 9 | - gRPC 工具链 10 | - Git 11 | 12 | ## 构建 Helm/tiller 13 | 14 | 我们使用 Make 来构建我们的程序。最简单的入门方法是: 15 | 16 | ```bash 17 | $ make bootstrap build 18 | ``` 19 | 20 | 21 | 22 | 注意:如果不从路径 `$GOPATH/src/k8s.io/helm` 运行,命令将会失败。目录 k8s.io 不应该是符号链接,否则 build 找不到相关的包。 23 | 24 | 这将构建 Helm 和 Tiller。`make bootstrap` 将尝试安装某些工具,如果它们不存在的话。 25 | 26 | 要运行所有测试(无需运行测试 `vendor/`),请运行 `make test`。在容器环境运行所有测试,请运行 `make docker-test` 27 | 28 | 要在本地运行 Helm 和 Tiller,可以运行 `bin/helm` 或 `bin/tiller`。 29 | 30 | - 已知 Helm 和 Tiller 可在 macOS 和大多数 Linux 发行版,包括 Alpine 上运行。 31 | - Tiller 必须能够访问 Kubernetes 群集。它通过检查使用 kubectl 的 Kube 配置文件来了解群集信息。 32 | 33 | ### 手册页 34 | 35 | 手册页和 Markdown 文档已经在 `docs/` 预先建好。可以使用重新生成文档 make docs。 36 | 37 | 要将 Helm 手册页公开给 `man` 客户端,您可以将这些文件放入 `$MANPATH`: 38 | 39 | ``` 40 | $ export MANPATH=$GOPATH/src/k8s.io/helm/docs/man:$MANPATH 41 | $ man helm 42 | ``` 43 | 44 | ## gRPC 和 Protobuf 45 | 46 | Helm 和 Tiller 使用 gRPC 进行通信。要开始使用 gRPC,需要如下准备 47 | 48 | - 安装 protoc 编译 protobuf 文件。发布在 [这里](https://github.com/google/protobuf/releases) 49 | - 运行 Helm 的 `make bootstrap` 来生成 p`rotoc-gen-go` 插件并将其放入 `bin/`。 50 | 51 | 请注意,需要使用 protobuf 3.2.0(`protoc --version`)的版本。protoc-gen-go 版本与 Kubernetes 使用 GRPC 的版本绑定。所以这个插件是在本地维护的。 52 | 53 | 虽然 gRPC 和 ProtoBuf 规范缩进时没有规定,但我们要求缩进样式与 Go 格式规范相匹配。也就是说,协议缓冲区应该使用基于标签的缩进,并且 rpc 声明应该遵循 Go 函数声明的风格。 54 | 55 | ### Helm API(HAPI) 56 | 57 | 我们使用 gRPC 作为 API 层。请参阅 `pkg/proto/hapi` 生成的 Go 代码以及 `_proto` 协议缓冲区定义。 58 | 59 | 要从 protobuf 源重新生成 Go 文件,使用 `make protoc`。 60 | 61 | ## Docker 镜像 62 | 63 | 要构建 Docker 镜像,请使用 `make docker-build`。 64 | 65 | 预构建的镜像已经在官方 Kubernetes Helm GCR registry 中提供。 66 | 67 | ## 运行本地群集 68 | 69 | 对于开发,我们强烈建议使用 [Kubernetes Minikube](https://github.com/kubernetes/minikube) 这个面向开发人员的发行版。安装完成后,可以使用 helm init 安装到群集中。请注意,用于开发的 Tiller 版本可能无法在 Google Cloud Container Registry 中使用。如果遇到镜像 Pull 错误,可以覆盖 Tiller 的版本。例: 70 | 71 | ```bash 72 | helm init --tiller-image=gcr.io/kubernetes-helm/tiller:2.7.2 73 | ``` 74 | 75 | 或使用最新版本: 76 | 77 | ```bash 78 | helm init --canary-image 79 | ``` 80 | 81 | 为了在 Tiller 上进行开发,在本地运行 Tiller 有时更方便,而不是将其打包到镜像中并在群集中运行。你可以通过告诉 Helm 客户端使用一个本地实例来做到这一点。 82 | 83 | ```bash 84 | $ make build 85 | $ bin/tiller 86 | ``` 87 | 88 | 要配置 Helm 客户端,请使用 `--host` 标志或导出 `HELM_HOST` 环境变量: 89 | 90 | ```bash 91 | $ export HELM_HOST=localhost:44134 92 | $ helm install foo 93 | ``` 94 | 95 | (请注意,直接运行 Tiller 时不需要使用 `helm init`) 96 | 97 | Tiller 应该在 >= 1.3 Kubernetes 群集上运行。 98 | 99 | ## 贡献指南 100 | 101 | 我们欢迎捐款。这个项目已经制定了一些指导方针,以确保(a)代码质量仍然很高,(b)项目保持一致,(c)贡献遵循开源法律要求。我们的目的不是为了给贡献者带来负担,而是为了构建优雅和高质量的开源代码,让我们的用户受益。 102 | 103 | 确保你已经阅读并理解了贡献指南: 104 | 105 | https://github.com/helm/blob/master/CONTRIBUTING.md 106 | 107 | ### 代码的结构 108 | 109 | Helm 项目的代码组织如下: 110 | 111 | - 单独的程序位于 `cmd/`。`cmd/` 里面的代码 不是为库的重复使用而设计的。 112 | - 共享库存储在 `pkg/`。 113 | - 原始 ProtoBuf 文件存储在 `_proto/hapi`(hapi 表示 Helm 应用程序编程接口)。 114 | - 从 proto 定义生成的 Go 文件存储在 `pkg/proto`。 115 | - `scripts/` 目录包含许多实用程序脚本。其中大部分由 CI/CD 管道使用。 116 | - `rootfs/` 文件夹用于 Docker 特定的文件。 117 | - `docs/` 文件夹用于文档和示例。 118 | 119 | Go 依赖关系由 Glide 管理 并存储在 `vendor/` 目录中。 120 | 121 | ### Git 约定 122 | 123 | 我们将 Git 用于版本控制系统。Master 分支是当前发展候选目录。发布版本有标记。 124 | 125 | 我们通过 GitHub Pull Requests(PR)接受对代码的更改。执行此操作的一个工作流程如下所示: 126 | 127 | 1. 转到 `$GOPATH/src/k8s.io` 目录,`git clone` `github.com/helm` 存储库。 128 | 2. 将该存储库 fork 到你自己的 GitHub 帐户 129 | 3. 将你的存储库添加为远程服务器 `$GOPATH/src/k8s.io/helm` 130 | 4. 创建一个新的工作分支(`git checkout -b feat/my-feature`)并在该分支上完成工作。 131 | 5. 当准备好让我们 review 时,将你的分支推送到 GitHub,然后给我们提交一个新的 PR 请求。 132 | 133 | 对于 Git 提交消息,我们遵循语义提交消息 [Semantic Commit Messages](https://karma-runner.github.io/0.13/dev/git-commit-msg.html): 134 | 135 | ``` 136 | fix(helm): add --foo flag to 'helm install' 137 | 138 | When 'helm install --foo bar' is run, this will print "foo" in the 139 | output regardless of the outcome of the installation. 140 | 141 | Closes #1234 142 | ``` 143 | 144 | 常见提交类型: 145 | 146 | - fix: 修复一个 bug 或错误 147 | - feat: 添加一项新功能 148 | - docs: 更改文档 149 | - test: 改进测试 150 | - ref: 重构现有的代码 151 | 152 | 常见范围: 153 | 154 | - helm:Helm CLI 155 | - tiller:Tiller 服务器 156 | - proto:Protobuf 定义 157 | - pkg/lint:lint 包。对于任何软件包遵循类似的约定 158 | - `*`:两个或更多范围 159 | 160 | 161 | 更多内容: 162 | 163 | - DEIS 准则 [Deis Guidelines](https://github.com/deis/workflow/blob/master/src/contributing/submitting-a-pull-request.md) 是这一部分的灵感启发。 164 | - Karma Runner [定义](https://karma-runner.github.io/0.13/dev/git-commit-msg.html) 了语义提交消息的主意。 165 | 166 | ### Go 语言约定 167 | 168 | 我们非常密切地遵循 Go 编码风格标准。通常,运行 `go fmt` 会让你的代码更加漂亮。 169 | 170 | 我们通常也遵循由 `go lint` 和 `gometalinter` 推荐的约定。运行 `make test-style` 以测试样式一致性。 171 | 172 | 如果你不想将 `gometalinter` 中的所有 linters 安装到你的全局 Go 环境中,你可以运行 `make docker-test-style`,它将运行相同的测试,但是在 docker 容器中是隔离的。 173 | 174 | 更多阅读: 175 | 176 | - Effective Go [introduces formatting](https://golang.org/doc/effective_go.html#formatting)。 177 | - Go Wiki 有一个关于格式化的非常好的文章 [formatting](https://github.com/golang/go/wiki/CodeReviewComments).。 178 | 179 | ### Protobuf 约定 180 | 181 | 由于项目主要是 Go 代码,因此我们尽可能将 Protobuf 文件格式化为 Go。目前 Protobuf 没有真正的格式规则或准则,但随着它们的出现,我们可能会选择遵循这些规则或准则。 182 | 183 | 标准: 184 | 185 | - Tab 缩进,而不是空格。 186 | - 间距规则遵循 Go 约定(线条末端的花括号,运算符周围的空格)。 187 | 188 | 约定: 189 | 190 | - 文件应该用 `option go_package = "...";` 来指定它们的包 191 | - 注释应该转化为良好的 Go 代码注释(因为 `protoc ` 会拷贝注释到目标源代码文件中)。 192 | - RPC 功能在它们的请求 / 响应消息的同一文件中定义。 193 | - 不推荐使用的RPC,消息和字段在注释中不推荐使用(// UpdateFoo DEPRECATED updates a foo.)。 194 | -------------------------------------------------------------------------------- /glossary-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Helm 词汇表 2 | 3 | Helm 使用一些特殊术语来描述体系结构的组件。 4 | 5 | ## Chart 6 | 7 | 包含足以将一组 Kubernetes 资源安装到 Kubernetes 集群中的信息的 Helm 软件包。 8 | 9 | Chart 包含 Chart.yaml 文件以及模板,默认值(values.yaml)和依赖关系。 10 | 11 | Chart 是在定义良好的目录结构中开发的,然后打包成一个称为 chart 压缩包的压缩格式。 12 | 13 | ## Chart 压缩包 14 | 15 | 一个 chart 压缩包是一个 tar 打包和 gzip 压缩(签名可选)的 chart。 16 | 17 | ## Chart 依赖(Subcharts) 18 | 19 | Chart 可能依赖于其他 chart。有两种方式可能会出现依赖性: 20 | 21 | - 软依赖性:如果没有在集群中安装另一个 chart,chart 可能无法正常工作。Helm 不为这种情况提供工具。在这种情况下,依赖关系可以单独管理。 22 | - 硬性依赖性:chart 可能包含(在其 `charts/` 目录内)其所依赖的另一个 chart。在这种情况下,安装 chart 将安装它的所有依赖关系。在这种情况下,chart 及其依赖关系作为集合进行管理。 23 | 24 | 当一个 chart 打包(通过 `helm package`)时,它的所有硬依赖关系都与它捆绑在一起。 25 | 26 | ## Chart 版本 27 | 28 | 根据 [SemVer 2 29 | spec](https://semver.org) 规范对 chart 进行版本控制。每个 chart 上都需要一个版本号。 30 | 31 | ## Chart.yaml 32 | 33 | 有关 chart 的信息存储在名为 Chart.yaml 的特殊文件中。每个 chart 都必须有这个文件。 34 | 35 | ## Helm(和 helm) 36 | 37 | Helm 是 Kubernetes 的软件包管理员。由于操作系统软件包管理器可以轻松在 OS 上安装工具,因此 Helm 可以轻松将应用程序和资源安装到 Kubernetes 群集中。 38 | 39 | 虽然 Helm 是该项目的名称,命令行客户端也被命名 helm。按照惯例,当谈到这个项目时,Helm 被大写。在谈到客户时,掌舵是小写的。 40 | 41 | ## Helm Home (HELM_HOME) 42 | 43 | Helm 客户端将信息存储在称为 helm home 的本地目录中 。默认情况下,这是在 `$HOME/.helm` 目录中。 44 | 45 | 该目录包含配置和缓存数据,并由 `helm init` 创建。 46 | 47 | 48 | 49 | 50 | 51 | ## Kube Config(KUBECONFIG) 52 | 53 | Helm 客户端通过使用 Kube 配置文件格式的文件来了解 Kubernetes 集群。默认情况下,Helm 尝试在 `kubectl` 创建的地方找到这个文件(`$HOME/.kube/config`)。 54 | 55 | ## Lint(Linting) 56 | 57 | Lint chart 是验证它遵循约定和 Helm chart 标准的要求。Helm 提供了执行此操作的工具,特别是 `helm lint` 命令。 58 | 59 | ## 出处(出处文件) 60 | 61 | Helm chart 可能伴随着一个出处文件,该文件提供关于 chart 来自哪里以及它包含什么的信息。 62 | 63 | 出处文件是 Helm 安全的一部分。出处包含 chart 压缩文件,Chart.yaml 数据和签名块(OpenPGP“clearsign” 块)的加密哈希。当与钥匙串结合使用时,这为 chart 用户提供了以下功能: 64 | 65 | - 验证 chart 是否由可信方签署 66 | - 验证 chart 文件没有被篡改 67 | - 验证 chart 元数据(Chart.yaml)的内容 68 | - 快速将 chart 与其出处数据进行匹配 69 | 70 | Provenance 文件具有. prov 扩展名,可以从 chart 存储库服务器或任何其他 HTTP 服务器提供。 71 | 72 | ## Release 73 | 74 | 当安装 chart 时,Tiller(Helm 服务器)创建一个 Release 来跟踪该安装。 75 | 76 | 单个 chart 可以多次安装到同一个群集中,并创建许多不同的 release。例如,可以通过 `helm install` 以不同的 release 名称运行三次来安装三个 PostgreSQL 数据库。 77 | 78 | (在 2.0.0-Alpha.1 之前,release 被称为 deployment,但这造成了与 Kubernetes Deployment 类型的混淆。) 79 | 80 | ## Release 版本号 81 | 82 | 单个版本可以多次更新。顺序计数器用于在 release 更改时跟踪 release。通过 `helm install` 第一次安装后,release 版本的版本号为 1. 每次发布 release 升级或回滚时,版本号都会增加。 83 | 84 | ## 回滚 85 | 86 | Release 可以升级到更新 chart 或配置。但是,由于发布历史已存储,release 版本也可以回滚到以前的版本号。这是通过 `helm rollback` 命令完成的。 87 | 88 | 重要的是,回滚版本将获得新版本号。 89 | 90 | 91 | Operation | Release Number 92 | ----------|--------------- 93 | install | release 1 94 | upgrade | release 2 95 | upgrade | release 3 96 | rollback 1| release 4(但运行与 release 1 相同的配置) 97 | 98 | 上表说明了如何在安装,升级和回滚都会增加版本号。 99 | 100 | ## Tiller 101 | 102 | Tiller 是 Helm 的集群组件。它直接与 Kubernetes API 服务器交互以安装,升级,查询和删除 Kubernetes 资源。它还存储代表 release 的对象。 103 | 104 | ## Repository(Repo,Chart Repository) 105 | 106 | Helm chart 可以存储在专用的 HTTP 服务器上,称为 chart 存储库(存储库或库)。 107 | 108 | chart 存储库服务器是一个简单的 HTTP 服务器,可以提供 index.yaml 描述一批 chart 的文件,并提供有关每个 chart 可从哪里下载的信息。(许多 chart 存储库同时保存 chart 以及 index.yaml 文件。) 109 | 110 | Helm 客户端可以指向零个或多个 chart 存储库。默认情况下,Helm 客户端指向 stable 官方 Kubernetes chart 存储库。 111 | 112 | ## Values(值文件,values.yaml) 113 | 114 | Values 提供了一种用自己的信息覆盖模板默认值的方法。 115 | 116 | Helm chart 是 “参数化” 的,这意味着 chart 开发人员可能会公开可在安装时被覆盖的配置。例如,chart 可能会公开 username 允许为服务设置用户名的字段。 117 | 118 | 这些暴露的变量在 Helm 说法中被称为值 values。 119 | 120 | values可以在`helm install`和`helm upgrade`操作时设置,或通过直接,或通过上传values.yaml 文件。 121 | -------------------------------------------------------------------------------- /history-zh_cn.md: -------------------------------------------------------------------------------- 1 | ## 项目的历史 2 | Kubernetes Helm 是 [Helm 3 | Classic](https://github.com/helm/helm) 和 GCS Deployment Manager 的 Kubernetes 移植的合并结果。该项目由 Google 和 Deis 联合创建,尽管它现在是 CNCF 的一部分。许多公司现在定期为 Helm 做出贡献。 4 | 5 | 与 Helm Classic 的区别: 6 | 7 | - Helm 现在有一个客户端(`helm`)和一个服务端(`tiller`)。服务端在 Kubernetes 内部运行,并管理资源。 8 | - Helm 的 chart 格式更好: 9 | - 依赖关系是不可变的,并存储在 chart 的 `charts/` 目录中。 10 | - chart 使用 [SemVer 2](https://semver.org/spec/v2.0.0.html) 版本标准化 11 | - chart 可以从目录或 chart 归档文件中加载 12 | - Helm 支持 Go 模板,无需运行 `generate` 或 `template` 命令。 13 | - Helm 可以轻松配置 release - 并与团队的其他成员共享配置。 14 | - Helm chart 存储库现在使用普通的 HTTP(S)而不是 Git / GitHub。不再有任何 GitHub 依赖。 15 | - chart 存储库服务是一个简单的 HTTP 服务器 16 | - chart 由版本引用 17 | - `helm serve` 命令将运行本地 chart 服务器,也可以轻松使用对象存储(S3,GCS)或常规 Web 服务器。 18 | - 而且仍然可以从本地目录加载 chart。 19 | - Helm工作空间不存在了。现在可以在想要工作的文件系统上的任何地方工作。 20 | -------------------------------------------------------------------------------- /images/create-a-bucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whmzsu/helm-doc-zh-cn/9af4e23d9267374845d8eadcc1f49862cf4ba926/images/create-a-bucket.png -------------------------------------------------------------------------------- /images/create-a-gh-page-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whmzsu/helm-doc-zh-cn/9af4e23d9267374845d8eadcc1f49862cf4ba926/images/create-a-gh-page-button.png -------------------------------------------------------------------------------- /images/edit-permissions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whmzsu/helm-doc-zh-cn/9af4e23d9267374845d8eadcc1f49862cf4ba926/images/edit-permissions.png -------------------------------------------------------------------------------- /images/make-bucket-public.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whmzsu/helm-doc-zh-cn/9af4e23d9267374845d8eadcc1f49862cf4ba926/images/make-bucket-public.png -------------------------------------------------------------------------------- /images/nothing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whmzsu/helm-doc-zh-cn/9af4e23d9267374845d8eadcc1f49862cf4ba926/images/nothing.png -------------------------------------------------------------------------------- /images/set-a-gh-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whmzsu/helm-doc-zh-cn/9af4e23d9267374845d8eadcc1f49862cf4ba926/images/set-a-gh-page.png -------------------------------------------------------------------------------- /quickstart/install-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 安装 2 | 3 | Helm 有两个部分:Helm 客户端(helm)和 Helm 服务端(Tiller)。本指南介绍如何安装客户端,然后继续演示两种安装服务端的方法。 4 | 5 | ** 重要提示 ** :如果你负责的群集是在受控的环境,尤其是在共享资源时,强烈建议使用安全配置安装 Tiller。有关指导,请参阅 [安全 Helm 安装](securing_installation-zh_cn.md)。 6 | 7 | ## 安装 Helm 客户端 8 | 9 | Helm 客户端可以从源代码安装,也可以从预构建的二进制版本安装。 10 | 11 | ### 从二进制版本 12 | 13 | 每一个版本 [release](https://github.com/helm/helm/releases)Helm 提供多种操作系统的二进制版本。这些二进制版本可以手动下载和安装。 14 | 15 | 1. 下载你 [想要的版本](https://github.com/helm/helm/releases) 16 | 2. 解压缩(`tar -zxvf helm-v2.0.0-linux-amd64.tgz`) 17 | 3. `helm` 在解压后的目录中找到二进制文件,并将其移动到所需的位置(`mv linux-amd64/helm /usr/local/bin/helm`) 18 | 19 | 到这里,你应该可以运行客户端了:`helm help`。 20 | 21 | ### 通过 Snap (Linux) 22 | 23 | Snap package 维护站点 [Snapcrafters](https://github.com/snapcrafters/helm). 24 | 25 | ``` 26 | $ sudo snap install helm --classic 27 | ``` 28 | 29 | ### 通过 homebrew(macOS) 30 | 31 | Kubernetes 社区的成员为 Homebrew 贡献了 Helm。这个通常是最新的。 32 | 33 | ``` 34 | brew install kubernetes-helm 35 | ``` 36 | (注意:emacs-helm 也是一个软件,这是一个不同的项目。) 37 | 38 | ### 从 Chocolatey 或 scoop (Windows) 39 | 40 | Kubernetes 社区的成员为 Chocolatey 贡献了 Helm 包。这个软件包通常是最新的。 41 | 42 | ``` 43 | choco install kubernetes-helm 44 | ``` 45 | 也可以通过 [`scoop`](https://scoop.sh) 命令行安装. 46 | 47 | ``` 48 | scoop install helm 49 | ``` 50 | 51 | 52 | ### 从脚本 53 | 54 | Helm 现在有一个安装 shell 脚本,将自动获取最新版本的 Helm 客户端并在[本地安装](https://git.io/get_helm.sh).。 55 | 56 | 可以获取该脚本,然后在本地执行它。这种方法也有文档指导,以便可以在运行之前仔细阅读并理解它在做什么。 57 | 58 | ``` 59 | $ curl -LO https://git.io/get_helm.sh 60 | $ chmod 700 get_helm.sh 61 | $ ./get_helm.sh 62 | ``` 63 | 64 | ``` 65 | curl -L https://git.io/get_helm.sh | bash 66 | ``` 67 | 也可以做到这一点。 68 | 69 | ### 从金丝雀 (Canary) 构建 70 | 71 | “Canary” 版本是从最新的主分支构建的 Helm 软件的版本。它们不是正式版本,可能不稳定。但是,他们提供了测试最新功能的机会。 72 | 73 | "Canary" 版本 Helm 二进制文件存储在 Kubernetes Helm GCS 存储中。以下是常见构建的链接: 74 | 75 | - [Linux AMD64](https://kubernetes-helm.storage.googleapis.com/helm-canary-linux-amd64.tar.gz) 76 | - [macOS AMD64](https://kubernetes-helm.storage.googleapis.com/helm-canary-darwin-amd64.tar.gz) 77 | - [Experimental Windows AMD64](https://kubernetes-helm.storage.googleapis.com/helm-canary-windows-amd64.zip) 78 | 79 | ### 源代码方式(Linux,macOS) 80 | 81 | 从源代码构建 Helm 的工作稍微多一些,但如果你想测试最新的(预发布)Helm 版本,那么这是最好的方法。 82 | 83 | 你必须有一个安装 Go 工作环境 。 84 | 85 | ```bash 86 | $ cd $GOPATH 87 | $ mkdir -p src/k8s.io 88 | $ cd src/k8s.io 89 | $ git clone https://github.com/helm.git 90 | $ cd helm 91 | $ make bootstrap build 92 | ``` 93 | 94 | 该 `bootstrap` 目标将尝试安装依赖,重建 vendor / 树,并验证配置。 95 | 96 | 该 `build` 目标编译 `helm` 并将其放置在 `bin/helm` 目录。Tiller 也会编译,并且被放置在 `bin/tiller` 目录。 97 | 98 | ## 安装 Tiller 99 | 100 | Helm 的服务器端部分 Tiller 通常运行在 Kubernetes 集群内部。但是对于开发,它也可以在本地运行,并配置为与远程 Kubernetes 群集通信。 101 | 102 | ### Special Note for RBAC Users 103 | 104 | 大多数云提供商都支持名为基于角色的访问控制(简称 RBAC)的特性。如果您的云提供商启用了该特性,您将需要为 Tiller 创建一个具有访问资源的正确角色和权限的服务帐户 (service account)。 105 | 查看 [Kubernetes Distribution Guide](kubernetes_distros-zh_cn.md) 在云提供商中使用 Helm 是否还有其他兴趣点. 也可以查看 [Tiller and Role-Based Access Control](rbac-zh_cn.md) 来获取关于如何在 RBAC 的 K8S 集群中使用 Tiller 的更多信息。 106 | 107 | ### 快捷群集内安装 108 | 109 | 安装 `tiller` 到群集中最简单的方法就是运行 `helm init`。这将验证 `helm` 本地环境设置是否正确(并在必要时进行设置)。然后它会连接到 `kubectl` 默认连接的任何集群(`kubectl config view`)。一旦连接,它将安装 `tiller` 到 `kube-system` 命名空间中。 110 | 111 | `helm init` 以后,可以运行 `kubectl get pods --namespace kube-system` 并看到 Tiller 正在运行。 112 | 113 | 你可以通过参数运行 `helm init`: 114 | 115 | - `--canary-image` 参数安装金丝雀版本 116 | - `--tiller-image` 安装特定的镜像(版本) 117 | - `--kube-context` 使用安装到特定群集 118 | - `--tiller-namespace` 用一个特定的命名空间 (namespace) 安装 119 | - `--service-account` 使用 Service Account 安装 [RBAC enabled clusters](securing_installation-zh_cn.md#rbac)) 120 | - `--automount-service-account false` 不适用 service account 安装 121 | 122 | 一旦安装了 Tiller,运行 `helm version` 会显示客户端和服务器版本。(如果它仅显示客户端版本, helm 则无法连接到服务器, 使用 `kubectl` 查看是否有任何 tiller Pod 正在运行。) 123 | 124 | 除非设置 `--tiller-namespace` 或 `TILLER_NAMESPACE` 参数,否则 Helm 将在命名空间 `kube-system` 中查找 Tiller 。 125 | 126 | ### 安装 Tiller 金丝雀版本 127 | 128 | Canary 镜像是从 master 分支建立的。他们可能不稳定,但他们提供测试最新功能的机会。 129 | 130 | 安装 Canary 镜像最简单的方法是 helm init 与 --canary-image 参数一起使用: 131 | 132 | ```bash 133 | $ helm init --canary-image 134 | ``` 135 | 136 | 这将使用最近构建的容器镜像。可以随时使用 ` kubectl` 删除 `kube-system` 名称空间中的 Tiller deployment 来卸载 Tiller。 137 | 138 | ### 本地运行 Tiller 139 | 140 | 对于开发而言,有时在本地运行 Tiller 更容易,将其配置为连接到远程 Kubernetes 群集。 141 | 142 | 上面介绍了构建部署 Tiller 的过程。 143 | 144 | 一旦 tiller 构建部署完成,只需启动它: 145 | 146 | ```bash 147 | $ bin/tiller 148 | Tiller running on :44134 149 | ``` 150 | 151 | 当 Tiller 在本地运行时,它将尝试连接到由 `kubectl` 配置的 Kubernetes 群集。(运行 kubectl config view 以查看是哪个群集。) 152 | 153 | 必须告知 helm 连接到这个新的本地 Tiller 主机,而不是连接到群集中的一个。有两种方法可以做到这一点。第一种是在命令行上指定 `--host` 选项。第二个是设置 `$HELM_HOST` 环境变量。 154 | 155 | ```bash 156 | $ export HELM_HOST=localhost:44134 157 | $ helm version # Should connect to localhost. 158 | Client: &version.Version{SemVer:"v2.0.0-alpha.4", GitCommit:"db...", GitTreeState:"dirty"} 159 | Server: &version.Version{SemVer:"v2.0.0-alpha.4", GitCommit:"a5...", GitTreeState:"dirty"} 160 | ``` 161 | 162 | 注意,即使在本地运行,Tiller 也会将安装的 release 配置存储在 Kubernetes 内的 ConfigMaps 中。 163 | 164 | ## 升级 Tiller 165 | 166 | 从 Helm 2.2.0 开始,Tiller 可以升级使用 `helm init --upgrade`。 167 | 168 | 对于旧版本的 Helm 或手动升级,可以使用 `kubectl` 修改 Tiller 容器镜像: 169 | 170 | ```bash 171 | $ export TILLER_TAG=v2.0.0-beta.1 # Or whatever version you want 172 | $ kubectl --namespace=kube-system set image deployments/tiller-deploy tiller=gcr.io/kubernetes-helm/tiller:$TILLER_TAG 173 | deployment "tiller-deploy" image updated 174 | ``` 175 | 176 | 设置 `TILLER_TAG=canary` 将获得 master 版本的最新快照。 177 | 178 | ## 删除或重新安装 Tiller 179 | 180 | 由于 Tiller 将其数据存储在 Kubernetes ConfigMaps 中,因此可以安全地删除并重新安装 Tiller,而无需担心丢失任何数据。推荐删除 Tiller 的方法是使用 `kubectl delete deployment tiller-deploy --namespace kube-system` 或更简洁使用 `helm reset`。 181 | 182 | 然后可以从客户端重新安装 Tiller: 183 | 184 | ```bash 185 | $ helm init 186 | ``` 187 | 188 | ## 高级用法 189 | 190 | helm init 提供了额外的参数,用于在安装之前修改 Tiller 的 deployment manifest。 191 | 192 | ### 使用 `--node-selectors` 193 | 194 | `--node-selectors` 参数允许我们指定调度 Tiller Pod 所需的节点标签。 195 | 196 | 下面的例子将在 nodeSelector 属性下创建指定的标签。 197 | 198 | ``` 199 | helm init --node-selectors "beta.kubernetes.io/os"="linux" 200 | ``` 201 | 202 | 已安装的 deployment manifest 将包含我们的节点选择器标签。 203 | 204 | ``` 205 | ... 206 | spec: 207 | template: 208 | spec: 209 | nodeSelector: 210 | beta.kubernetes.io/os: linux 211 | ... 212 | ``` 213 | 214 | ### 使用 --override 215 | 216 | `--override` 允许指定 Tiller 的 deployment manifest 的属性。与在 Helm 其他地方 `--set` 使用的命令不同,`helm init --override` 修改最终 manifest 的指定属性(没有 "values" 文件)。因此,可以为 deployment manifest 中的任何有效属性指定任何有效值。 217 | 218 | #### 覆盖注释 219 | 220 | 在下面的示例中,我们使用 --override 添加修订版本属性并将其值设置为 1。 221 | 222 | ``` 223 | helm init --override metadata.annotations."deployment\.kubernetes\.io/revision"="1" 224 | ``` 225 | 226 | 输出: 227 | 228 | ``` 229 | apiVersion: extensions/v1beta1 230 | kind: Deployment 231 | metadata: 232 | annotations: 233 | deployment.kubernetes.io/revision: "1" 234 | ... 235 | ``` 236 | 237 | #### 覆盖亲和性 238 | 在下面的例子中,我们为节点设置了亲和性属性。`--override` 可以组合来修改同一列表项的不同属性。 239 | 240 | ``` 241 | helm init --override "spec.template.spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight"="1" --override "spec.template.spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].preference.matchExpressions[0].key"="e2e-az-name" 242 | ``` 243 | 244 | 指定的属性组合到 “preferredDuringSchedulingIgnoredDuringExecution” 属性的第一个列表项中。 245 | 246 | ``` 247 | ... 248 | spec: 249 | strategy: {} 250 | template: 251 | ... 252 | spec: 253 | affinity: 254 | nodeAffinity: 255 | preferredDuringSchedulingIgnoredDuringExecution: 256 | - preference: 257 | matchExpressions: 258 | - key: e2e-az-name 259 | operator: "" 260 | weight: 1 261 | ... 262 | ``` 263 | 264 | ### 使用 --output 265 | 266 | `--output` 参数允许我们跳过安装 Tiller 的 deployment 267 | manifest,并以 JSON 或 YAML 格式简单地将 deployment 268 | manifest 输出到标准输出 stdout。然后可以使用 `jq` 类似工具修改输出,并使用 `kubectl` 手动安装。 269 | 270 | 在下面的例子中,我们 helm init 用 --output json 参数执行。 271 | 272 | ``` 273 | helm init --output json 274 | ``` 275 | 276 | Tiller 安装被跳过,manifest 以 JSON 格式输出到 stdout。 277 | 278 | ```json 279 | "apiVersion": "extensions/v1beta1", 280 | "kind": "Deployment", 281 | "metadata": { 282 | "creationTimestamp": null, 283 | "labels": { 284 | "app": "helm", 285 | "name": "tiller" 286 | }, 287 | "name": "tiller-deploy", 288 | "namespace": "kube-system" 289 | }, 290 | ... 291 | ``` 292 | ### 存储后端 293 | 294 | 默认情况下,tiller 将安装 release 信息存储在其运行的名称空间中的 ConfigMaps 中。从 Helm 2.7.0 开始,现在有一个 Secrets 用于存储安装 release 信息的 beta 存储后端。添加了这个功能是为和 Kubernetes 的加密 Secret 一起,保护 chart 的安全性。 295 | 296 | 要启用 secrets 后端,需要使用以下选项启动 Tiller: 297 | 298 | ```bash 299 | helm init --override 'spec.template.spec.containers[0].command'='{/tiller,--storage=secret}' 300 | ``` 301 | 302 | 目前,如果想从默认后端切换到 secrets 后端,必须自行为此进行迁移配置信息。当这个后端从 beta 版本毕业时,将会有更正式的移徙方法。 303 | 304 | ## 总结 305 | 306 | 在大多数情况下,安装和获取预先构建的 helm 二进制代码和 `helm init` 一样简单。这个文档提供而了一些用例给那些想要用 Helm 做更复杂的事情的人。 307 | 308 | 一旦成功安装了Helm Client和Tiller,可以继续下一步使用Helm来管理charts。 309 | -------------------------------------------------------------------------------- /quickstart/install_faq-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 安装 FAQ 2 | 3 | 本节跟踪安装或开始使用 Helm 时遇到的一些经常遇到的问题。 4 | 5 | ** 欢迎你的帮助 ** 来更好的提供此文档。要添加,更正或删除信息,提出问题 [issue](https://github.com/helm/helm/issues) 或向我们发送 PR 请求。 6 | 7 | ## 下载 8 | 9 | 我想知道更多关于我的下载选项。 10 | 11 | ** 问:我无法获得最新 Helm 的 GitHub 发布。他们在哪?** 12 | 13 | 答:我们不再使用 GitHub 发布版本。二进制文件现在存储在 GCS 公共存储区中 [GCS public bucket](https://kubernetes-helm.storage.googleapis.com)。 14 | 15 | ** 问:为什么没有 Debian/Fedora/... Helm 的原生的软件包?** 16 | 17 | 我们很乐意提供这些信息,或者指向可靠的提供商。如果你对帮助感兴趣,我们很乐意。这就是 Homebrew 式的开始。 18 | 19 | ** 问:你为什么要提供一个 curl ...|bash 脚本?** 20 | 21 | 答:我们的 repo 库(`scripts/get`)中有一个脚本可以作为 `curl ..|bash` 脚本执行。这些传输全部受 HTTPS 保护,并且脚本会对其获取的包进行一些审计。但是,脚本具有任何 shell 脚本的所有常见危险。 22 | 23 | 我们提供它是因为它很有用,但我们建议用户先仔细阅读脚本。并且,我们真正喜欢的是 Helm 的的打包版本。 24 | 25 | ## 安装 26 | 27 | 我正在尝试安装 Helm/Tiller,但有些地方出了问题。 28 | 29 | ** 问:我如何将 Helm 客户端文件放在~/.helm 以外的地方?** 30 | 31 | 设置 `$HELM_HOME` 环境变量,然后运行 `helm init`: 32 | 33 | ```bash 34 | export HELM_HOME=/some/path 35 | helm init --client-only 36 | ``` 37 | 38 | 注意,如果你有现有的 repo 存储库,则需要通过 `helm repo add...`. 重新添加它们。 39 | 40 | ** 问:我如何配置 Helm,但不安装 Tiller?** 41 | 42 | 答:默认情况下,helm init 将确认本​​地 $HELM_HOME 配置,然后在群集上安装 Tiller。要本地配置,但不安装 Tiller,请使用 `helm init --client-only`。 43 | 44 | ** 问:如何在集群上手动安装 Tiller?** 45 | 46 | 答:Tiller 是作为 Kubernetes deployment 安装的。可以通过运行 `helm init --dry-run --debug` 获取 manifest,然后通过 kubectl 手动安装 。建议不要删除或更改该 deployment 中的标签 labels,因为它们有时支持脚本和工具需要用到。 47 | 48 | ** 问:为什么安装 Tiller 期间报错误 Error response from daemon: target is unknown?** 49 | 50 | 答:有用户报告无法在使用 Docker 1.13.0 的 Kubernetes 实例上安装 Tiller。造成这种情况的根本原因是 Docker 中的一个错误,它使得一个版本与早期版本的 Docker 推送到 Docker 注册表的镜像不兼容。 51 | 52 | 该问题在发布后不久就已修复,并在 Docker 1.13.1-RC1 和更高版本中提供。 53 | 54 | ## 入门 55 | 我成功安装了 Helm/Tiller,但我使用时碰到问题。 56 | 57 | ** 问:使用 Helm 时,收到错误 “客户端传输中断”** 58 | 59 | ``` 60 | E1014 02:26:32.885226 16143 portforward.go:329] an error occurred forwarding 37008 -> 44134: error forwarding port 44134 to pod tiller-deploy-2117266891-e4lev_kube-system, uid : unable to do port forwarding: socat not found. 61 | 2016/10/14 02:26:32 transport: http2Client.notifyError got notified that the client transport was broken EOF. 62 | Error: transport is closing 63 | ``` 64 | 65 | 答:这通常表明 Kubernetes 未设置为允许端口转发。 66 | 67 | 通常情况下,缺少的部分是 socat。如果正在运行 CoreOS,我们被告知它可能在安装时配置错误。CoreOS 团队建议阅读以下内容: 68 | 69 | https://coreos.com/kubernetes/docs/latest/kubelet-wrapper.html 70 | 71 | 以下是一些解决的问题案例,可以帮助开始使用: 72 | 73 | - https://github.com/kubernetes/helm/issues/1371 74 | - https://github.com/kubernetes/helm/issues/966 75 | 76 | **Q:使用 Helm 时, 报错误 "lookup XXXXX on 8.8.8.8:53: no such host"** 77 | 78 | ``` 79 | Error: Error forwarding ports: error upgrading connection: dial tcp: lookup kube-4gb-lon1-02 on 8.8.8.8:53: no such host 80 | ``` 81 | 82 | 答:我们在 Ubuntu 和 Kubeadm 多节点群集中有这个问题。问题原因是节点期望某些 DNS 记录可以通过全局 DNS 获得。在上游解决此问题之前,可以按照以下方式解决该问题。在每个控制平面节点上: 83 | 84 | 1. 添加条目到 `/etc/hosts`,将主机名映射到其 public IP 85 | 2. 安装 `dnsmasq`(例如 `apt install -y dnsmasq`) 86 | 3. 删除 k8s api 服务容器(kubelet 会重新创建它) 87 | 4. 然后 `systemctl restart docker`(或重新启动节点)请 / etc/resolv.conf 更改 88 | 请参阅此问题以获取更多信息:https://github.com/kubernetes/helm/issues/1455 89 | 90 | ** 问:在 GKE(Google Container Engine)上,报错 "No SSH tunnels currently open"** 91 | 92 | ``` 93 | Error: Error forwarding ports: error upgrading connection: No SSH tunnels currently open. Were the targets able to accept an ssh-key for user "gke-[redacted]"? 94 | ``` 95 | 96 | 错误消息的另一个形式是: 97 | 98 | ``` 99 | Unable to connect to the server: x509: certificate signed by unknown authority 100 | 101 | ``` 102 | 103 | 答:这个问题是你的本地 Kubernetes 配置文件必须具有正确的凭据。 104 | 105 | 在 GKE 上创建集群时,它将提供凭证,包括 SSL 证书和证书颁发机构信息。这些需要存储在一个 Kubernetes 配置文件中(默认:`~/.kube/config`,这样 `kubectl` 和 `helm` 可以访问它们)。 106 | 107 | ** 问:当我运行 Helm 命令时,出现有关隧道 tunnel 或代理 proxy 的错误 ** 108 | 109 | 答:Helm 使用 Kubernetes 代理服务连接到 Tiller 服务器。如果命令 `kubectl proxy` 不适用,Helm 也不行。通常,错误与缺失的 `socat` 服务有关。 110 | 111 | ** 问:Tiller 崩溃 ** 112 | 113 | 当我在 Helm 上运行命令时,Tiller 崩溃时会出现如下错误: 114 | 115 | ``` 116 | Tiller is listening on :44134 117 | Probes server is listening on :44135 118 | Storage driver is ConfigMap 119 | Cannot initialize Kubernetes connection: the server has asked for the client to provide credentials 2016-12-20 15:18:40.545739 I | storage.go:37: Getting release "bailing-chinchilla" (v1) from storage 120 | panic: runtime error: invalid memory address or nil pointer dereference 121 | [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x8053d5] 122 | 123 | goroutine 77 [running]: 124 | panic(0x1abbfc0, 0xc42000a040) 125 | /usr/local/go/src/runtime/panic.go:500 +0x1a1 126 | k8s.io/helm/vendor/k8s.io/kubernetes/pkg/client/unversioned.(*ConfigMaps).Get(0xc4200c6200, 0xc420536100, 0x15, 0x1ca7431, 0x6, 0xc42016b6a0) 127 | /home/ubuntu/.go_workspace/src/k8s.io/helm/vendor/k8s.io/kubernetes/pkg/client/unversioned/configmap.go:58 +0x75 128 | k8s.io/helm/pkg/storage/driver.(*ConfigMaps).Get(0xc4201d6190, 0xc420536100, 0x15, 0xc420536100, 0x15, 0xc4205360c0) 129 | /home/ubuntu/.go_workspace/src/k8s.io/helm/pkg/storage/driver/cfgmaps.go:69 +0x62 130 | k8s.io/helm/pkg/storage.(*Storage).Get(0xc4201d61a0, 0xc4205360c0, 0x12, 0xc400000001, 0x12, 0x0, 0xc420200070) 131 | /home/ubuntu/.go_workspace/src/k8s.io/helm/pkg/storage/storage.go:38 +0x160 132 | k8s.io/helm/pkg/tiller.(*ReleaseServer).uniqName(0xc42002a000, 0x0, 0x0, 0xc42016b800, 0xd66a13, 0xc42055a040, 0xc420558050, 0xc420122001) 133 | /home/ubuntu/.go_workspace/src/k8s.io/helm/pkg/tiller/release_server.go:577 +0xd7 134 | k8s.io/helm/pkg/tiller.(*ReleaseServer).prepareRelease(0xc42002a000, 0xc42027c1e0, 0xc42002a001, 0xc42016bad0, 0xc42016ba08) 135 | /home/ubuntu/.go_workspace/src/k8s.io/helm/pkg/tiller/release_server.go:630 +0x71 136 | k8s.io/helm/pkg/tiller.(*ReleaseServer).InstallRelease(0xc42002a000, 0x7f284c434068, 0xc420250c00, 0xc42027c1e0, 0x0, 0x31a9, 0x31a9) 137 | /home/ubuntu/.go_workspace/src/k8s.io/helm/pkg/tiller/release_server.go:604 +0x78 138 | k8s.io/helm/pkg/proto/hapi/services._ReleaseService_InstallRelease_Handler(0x1c51f80, 0xc42002a000, 0x7f284c434068, 0xc420250c00, 0xc42027c190, 0x0, 0x0, 0x0, 0x0, 0x0) 139 | /home/ubuntu/.go_workspace/src/k8s.io/helm/pkg/proto/hapi/services/tiller.pb.go:747 +0x27d 140 | k8s.io/helm/vendor/google.golang.org/grpc.(*Server).processUnaryRPC(0xc4202f3ea0, 0x28610a0, 0xc420078000, 0xc420264690, 0xc420166150, 0x288cbe8, 0xc420250bd0, 0x0, 0x0) 141 | /home/ubuntu/.go_workspace/src/k8s.io/helm/vendor/google.golang.org/grpc/server.go:608 +0xc50 142 | k8s.io/helm/vendor/google.golang.org/grpc.(*Server).handleStream(0xc4202f3ea0, 0x28610a0, 0xc420078000, 0xc420264690, 0xc420250bd0) 143 | /home/ubuntu/.go_workspace/src/k8s.io/helm/vendor/google.golang.org/grpc/server.go:766 +0x6b0 144 | k8s.io/helm/vendor/google.golang.org/grpc.(*Server).serveStreams.func1.1(0xc420124710, 0xc4202f3ea0, 0x28610a0, 0xc420078000, 0xc420264690) 145 | /home/ubuntu/.go_workspace/src/k8s.io/helm/vendor/google.golang.org/grpc/server.go:419 +0xab 146 | created by k8s.io/helm/vendor/google.golang.org/grpc.(*Server).serveStreams.func1 147 | /home/ubuntu/.go_workspace/src/k8s.io/helm/vendor/google.golang.org/grpc/server.go:420 +0xa3 148 | ``` 149 | 150 | 答:请检查 Kubernetes 的安全设置。 151 | 152 | Tiller 中的崩溃几乎总是由于未能与 Kubernetes API 服务器进行协商而导致的结果(此时,Tiller 功能不正常,因此崩溃并退出)。 153 | 154 | 通常,这是认证失败的结果,因为运行 Tiller 的 Pod 没有正确的令牌 token。 155 | 156 | 要解决这个问题,你需要修改 Kubernetes 配置。确保 --service-account-private-key-file 从 controller-manager 和 --service-account-key-file 从 API 服务器指向同一个 X509 RSA 密钥。 157 | 158 | ## 升级 159 | 160 | 我的 Helm 原来工作正常,然后我升级了。现在它工作不正常。 161 | 162 | ** 问:升级后,我收到错误 “Client version is incompatible”。怎么问题?** 163 | 164 | Tiller 和 Helm 必须协商一个通用版本,以确保他们可以安全地进行通信而不会违反 API 假设。该错误意味着版本差异太大而无法安全地继续。通常,需要为此手动升级 Tiller。 165 | 166 | 该安装指南 [Installation Guide](install-zh_cn.md) 有关于安全 Helm 升级和 Tiller 的详细信息。 167 | 168 | 版本号的规则如下: 169 | 170 | - 预发布版本与其他一切不兼容。Alpha.1 与... 不相容 Alpha.2。 171 | - 修补程序版本兼容:1.2.3 与 1.2.4 兼容 172 | - 少量修订不兼容:1.2.0 与 1.3.0 不兼容,但我们可能在未来放宽这一限制。 173 | - 主要版本不兼容:1.0.0 与 2.0.0 不兼容。 174 | 175 | ## 卸载 176 | 177 | 我正在尝试删除某些东西。 178 | 179 | ** 问:当我删除 Tiller deployment 时,为何所有安装的 release 信息还在集群里?** 180 | 181 | 安装 release 信息存储在 kube-system 名称空间内的 ConfigMaps 中。需要手动删除它们以删除记录或使用 helm delete --purge。 182 | 183 | 问:我想删除我的本地 Helm。它的所有文件在哪里? 184 | 185 | 包括helm二进制文件,Helm存储了一些文件在$HELM_HOME,默认位于~/.helm。 186 | -------------------------------------------------------------------------------- /quickstart/kubernetes_distros-zh_cn.md: -------------------------------------------------------------------------------- 1 | # Kubernetes 各发行版本指南 2 | 本文档描述有关在各 Kubernetes 发行版本环境中使用 Helm 的信息。 3 | 4 | 我们尝试为此文档添加更多详细信息。如果可以,请通过 Pull Requests 提供。 5 | 6 | ## MiniKube 7 | Helm 已经过测试并且已知可以与 minikube 一起使用。它不需要额外的配置。 8 | 9 | ## scripts/local-cluster 和 Hyperkube 10 | 通过配置 Hyperkube scripts/local-cluster.sh 已知可以工作。对于原始的 Hyperkube,可能需要进行一些手动配置。 11 | 12 | ## GKE 13 | 已知 Google 的 GKE 托管 Kubernetes 平台 默认启用 RBAC. 因此需要为 tiller 创建一个服务帐户(service account),并在初始化 helm 服务端时使用 --service-account 参数。查看 [Tiller 和 RBAC](rbac-zh_cn.md) 获取更详细的信息. 14 | 15 | ## Ubuntu 与'kubeadm' 16 | kubeadm 构建的 Kubernetes 已知可用于以下 Linux 发行版: 17 | 18 | - Ubuntu 16.04 19 | - Fedora 发布 25 20 | 21 | 某些版本的 Helm(v2.0.0-beta2)要求 `export KUBECONFIG=/etc/kubernetes/admin.conf` 或创建一个 `~/.kube/config` 文件。 22 | 23 | ## CoreOS 提供的 Container Linux 24 | Helm 要求 kubelet 可以访问 socat 程序的副本,以代理与 Tiller API 的连接。在 Container Linux 上,Kubelet 在具有 socat 的 [hyperkube](https://github.com/kubernetes/kubernetes/tree/master/cluster/images/hyperkube) 容器映像中运行。因此,尽管 Container Linux 没有 socat, 运行 kubelet 的容器​​文件系统具有 socat。要了解更多信息,请阅读 [Kubelet Wrapper](https://coreos.com/kubernetes/docs/latest/kubelet-wrapper.html) 文档。 25 | 26 | ## Openshift 27 | Helm 可在 OpenShift Online,OpenShift Dedicated,OpenShift Container Platform(版本 > = 3.6)或 OpenShift Origin(版本 > = 3.6)中直接使用。要了解更多,请阅读此 [博客文章](https://blog.openshift.com/getting-started-helm-openshift/)。 28 | 29 | ## Platform9 30 | Helm Client 和 Helm Server(Tiller)预装在 [Platform9 Managed Kubernetes](https://platform9.com/managed-kubernetes/?utm_source=helm_distro_notes)。Platform9 通过 App 目录 UI 和本地 Kubernetes CLI 提供对所有官方 Helm charts 的访问。其他 repo 存储库可以手动添加。有关更多详细信息,请参阅 [Platform9 App Catalog 文章](https://blog.openshift.com/getting-started-helm-openshift/)。 31 | 32 | ## DC / OS 33 | Helm(客户端和服务器)已经过测试,在Mesospheres DC / OS 1.11 Kubernetes平台工作正常,无需其他配置。 34 | -------------------------------------------------------------------------------- /quickstart/plugins-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 插件指南 2 | 3 | Helm 2.1.0 引入了客户端 Helm 插件_plugin_的概念。插件是一种可以通过 helm CLI 访问的工具,但它不是内置 Helm 代码库的一部分。 4 | 5 | 现有的插件可以在相关部分 [related](../related-zh_cn.md#Helm 插件) 找到或者通过搜索 [Github](https://github.com/search?q=topic%3Ahelm-plugin&type=Repositories)。 6 | 7 | 本指南介绍了如何使用和创建插件。 8 | 9 | ## 概述 10 | 11 | Helm 插件是与 Helm 无缝集成的附加工具。它们提供了扩展 Helm 核心功能集的方法,但不需要将每个新功能都通过 Go 语言写入并添加到核心工具中。 12 | 13 | Helm 插件具有以下功能: 14 | 15 | - 可以在 Helm 安装中添加和删除它们,而不会影响核心 Helm 工具。 16 | - 它们可以用任何编程语言编写。 17 | - 他们与 Helm 集成,并出现在 helm help 和其他地方。 18 | 19 | Helm 插件放置在 $(helm home)/plugins。 20 | 21 | Helm 插件模型部分建模在​​Git 的插件模型上。为此,有时可能会听到 helm 称为瓷层 _porcelain_,插件是管道 _plumbing_。这是揭示 Helm 提供用户体验和顶级处理逻辑,而插件则是执行所需操作的 “细节工作” 的简略说法。 22 | 23 | ## 安装插件 24 | 25 | 使用 `$ helm plugin install ` 命令安装插件。可以将路径设置为本地文件系统上的插件或远程 VCS repo 的 URL。`helm plugin install` 命令克隆或复制该插件的路径 / URL 到给定的 `$(helm home)/plugins` 26 | 27 | ```bash 28 | $ helm plugin install https://github.com/technosophos/helm-template 29 | ``` 30 | 31 | 如果你有一个插件 tar 分发版,只需将插件解压到 $(helm home)/plugins 目录中即可。 32 | 33 | 也可以通过直接从 URL 安装 tarball 插件 `helm plugin install http://domain/path/to/plugin.tar.gz` 34 | 35 | ## 构建插件 36 | 37 | 在很多方面,插件类似于 chart。每个插件都有一个顶级目录,然后是一个 `plugin.yaml` 文件。 38 | 39 | ``` 40 | $(helm home)/plugins/ 41 | |- keybase/ 42 | | 43 | |- plugin.yaml 44 | |- keybase.sh 45 | 46 | ``` 47 | 48 | 在上面的例子中,keybase 插件包含在名为 keybase 的目录中。它有两个文件:(`plugin.yaml` 必需)和一个可执行脚本 `keybase.sh`(可选)。 49 | 50 | 插件的核心是一个简单的 YAML 文件 `plugin.yaml`。这是一个插件的一个插件 YAML,它增加了对 Keybase 操作的支持: 51 | 52 | ``` 53 | name: "keybase" 54 | version: "0.1.0" 55 | usage: "Integrate Keybase.io tools with Helm" 56 | description: |- 57 | This plugin provides Keybase services to Helm. 58 | ignoreFlags: false 59 | useTunnel: false 60 | command: "$HELM_PLUGIN_DIR/keybase.sh" 61 | ``` 62 | 63 | `name` 是插件的名称。当 Helm 执行插件时,这是它将使用的名称(例如,`helm NAME` 将调用此插件)。 64 | 65 | _`name` 应该匹配目录名称。_ 在我们上面的例子中,这意味着插件 `name: keybase` 应该在一个名为 keybase 的目录中。 66 | 67 | `name` 的限制: 68 | 69 | - `name` 不能一个现有的 helm 顶级命令重复。 70 | - name 必须限制为 ASCII az,AZ,0-9 `_` 和 `-。 71 | 72 | `version` 是插件的 SemVer 2 版本。 `usage` 和 `description` 都用于生成命令的帮助文本。 73 | 74 | `ignoreFlags` 告诉 H​​elm 不会将参数传递给插件。所以,如果一个插件被 `helm myplugin --foo` 调用,并且 `ignoreFlags: true`,那么 `--foo` 将被忽略。 75 | 76 | `useTunnel` 指示插件需要一个隧道去连接 Tiller。这在任何时候插件与 Tiller 对接都应该设置为 true 。它会使 Helm 打开一个隧道,然后 ``$TILLER_HOST` 为该隧道设置正确的本地地址。不用担心:如果 Helm 由于 Tiller 在本地运行而检测到隧道是不必啊哟的,它就不会创建隧道。 77 | 78 | 最后,也是最重要的是,`command`,是这个插件在调用时会执行的命令。在执行插件之前会插入环境变量。上面的模式说明了指出插件程序所在位置的首选方式。 79 | 80 | 有一些使用插件命令的策略: 81 | 82 | - 如果插件包含可执行文件 `command:`,则应将可执行文件打包到插件目录中。 83 | - `command:` 将在执行前展开任何环境变量。`$HELM_PLUGIN_DIR` 将指向插件目录。 84 | - 该命令本身不在 shell 中执行。所以你不能在一个 shell 脚本上运行。 85 | - Helm 将大量配置注入到环境变量中。查看环境以查看可用信息。 86 | - Helm 对插件的语言没有任何设限。你可以用你喜欢的任何方式来写。 87 | - 命令负责执行具体的帮助文本 `-h` 和 `--help`。helm 将使用 usage 和 description 对 helm help 和 helm help myplugin 进行处理,但不会处理 `helm myplugin --help`。 88 | 89 | ## 下载器插件 90 | 91 | 默认情况下,Helm 可以使用 HTTP/S 获取图表。从 Helm 2.4.0 开始,插件可以从任意源下载 chart。 92 | 93 | 插件应在 plugin.yaml 文件(顶层)中声明这个特殊功能: 94 | 95 | ``` 96 | downloaders: 97 | - command: "bin/mydownloader" 98 | protocols: 99 | - "myprotocol" 100 | - "myprotocols" 101 | ``` 102 | 103 | 如果安装了这样的插件,Helm 可以通过调用 `command` 指定的协议方案与存储库 repo 进行交互。特殊存储库应与常规存储库类似添加:特殊存储库 `helm repo add favorite myprotocol://example.com/` 的规则与常规存储库的规则相同:Helm 必须能够下载 index.yaml 文件以发现并缓存可用 charts 列表。 104 | 105 | 定义的命令将使用以下方案调用: `command certFile keyFile caFile full-URL`。SSL 凭证来自存储在 `$HELM_HOME/repository/repositories.yaml` 其中的 repo 定义, 。下载器插件将原始内容转储到 stdout 并在 stderr 上报告错误。 106 | 107 | ## 环境变量 108 | 109 | 当 Helm 执行插件时,它将外部环境传递给插件,并且还会注入一些其他环境变量。 110 | 111 | 类似 `KUBECONFIG` 的变量将为插件设置,如果他们设置在外部环境变量中。 112 | 113 | 保证以下变量设置: 114 | 115 | - HELM_PLUGIN:插件目录的路径 116 | - HELM_PLUGIN_NAME:插件的名称,正如 `helm` 所调用的。所以 `helm myplug` 会有简称 `myplug`。 117 | - HELM_PLUGIN_DIR:包含该插件的目录。 118 | - HELM_BIN:`helm` 命令的路径(由用户执行)。 119 | - HELM_HOME:Helm 的 home 的路径。 120 | - HELM_PATH_*:重要 Helm 文件和目录的路径存储在前缀为 `HELM_PATH` 的环境变量中。 121 | - TILLER_HOST:Tiller 的 `domain:port`。如果创建隧道,则会指向隧道的本地端点。否则,它会指向 ``$HELM_HOST`,`--host` 或默认主机(按照优先级的规则)。 122 | 123 | 虽然 `HELM_HOST` 可以设置,但不能保证它会指向正确的 Tiller 实例。这是为了允许插件开发人员在插件本身需要手动配置连接时以其原始状态进行访问 `HELM_HOST` 。 124 | 125 | ## 关于 `useTunnel` 126 | 127 | 如果插件指定 `useTunnel: true`,Helm 将执行以下操作(按顺序): 128 | 129 | 1. 解析全局标志和环境 130 | 2. 创建隧道 131 | 3. 设置 `TILLER_HOST` 132 | 4. 执行插件 133 | 5. 关闭隧道 134 | 135 | 命令退出后,隧道即被删除。因此,一个进程要使用该隧道,它不能是后台进程。 136 | 137 | ## 关于参数标记解析 138 | 139 | 在执行插件时,Helm 会解析全局标志以供自己使用。其中一些参数标志不会传递给插件。 140 | 141 | - `--debug`:如果已指定,`$HELM_DEBUG` 则设为 `1` 142 | - `--home`:这被转换为 `$HELM_HOME` 143 | - `--host`:这被转换为 `$HELM_HOST` 144 | - `--kube-context`:将丢弃。如果你的插件使用 `useTunnel`,这是用来为你设置隧道的。 145 | 146 | `-h`和`--help`,插件应该显示帮助文本,然后退出。在所有其他情况下,插件可以根据需要使用参数标志。 147 | -------------------------------------------------------------------------------- /quickstart/quickstart-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 快速入门 2 | 本指南介绍如何快速开始使用 Helm。 3 | 4 | ## 前提条件 5 | 需要准备以下前提条件才能成功且安全地使用 Helm。 6 | 7 | 1. 一个 Kubernetes 集群 8 | 2. 确定使用哪种安装安全配置(如果有的话) 9 | 3. 安装和配置 Helm 和集群端服务 Tiller。 10 | 11 | ### 安装 Kubernetes 或有权访问群集 12 | - 必须已安装 Kubernetes。对于 Helm 的最新版本,我们推荐最新的 Kubernetes 稳定版本,在大多数情况下它是次新版本。 13 | - 应该有一个本地配置好的 `kubectl`。 14 | 15 | ** 注意:** 1.6 之前的 Kubernetes 版本对于基于角色的访问控制(RBAC),要么有限制,或者不支持。 16 | 17 | Helm 将通过 Kubernetes 配置文件(通常是 `$HOME/.kube/config`)来确定在哪里安装 Tiller 。这个配置文件也是 kubectl 使用的文件。 18 | 19 | 要找出 Tiller 将安装到哪个集群,可以运行 `kubectl config current-context` 或 `kubectl cluster-info`。 20 | 21 | ```bash 22 | $ kubectl config current-context 23 | my-cluster 24 | ``` 25 | ### 了解集群配置的安全上下文 26 | 与所有强大的工具一样,需要确保为你的场景正确安装它。 27 | 28 | 如果你在完全控制的群集上使用 Helm,如 minikube 或专用网络中的不考虑共享的群集,则默认安装(不采用安全配置)很合适,并且是最容易的。要在无需额外安全措施的场景下安装 Helm,请参考 [安装 Helm](# 安装 Helm),然后 [初始化 Helm](# 初始化 Helm 并安装 Tiller)。 29 | 30 | 但是,如果集群暴露于更大的网络中,或者集群与他人共享 - 生产集群属于此类别 - 则必须采取额外步骤来确保安装安全,以防止不小心或恶意的操作者损坏集群或其集群数据。在生产环境和其他多租户方案中,要使用安全配置安装 Helm,请参阅 [Helm 安全安装](securing_installation-zh_cn.md)。 31 | 32 | 如果群集启用了基于角色的访问控制(RBAC),在继续之前配置 [服务帐户 (service account) 和规则](rbac-zh_cn.md)。 33 | 34 | ## 安装 Helm 35 | 下载 Helm 客户端的二进制版本。可以使用类似工具如 `homebrew`,或查看 [官方发布页面](https://github.com/helm/helm/releases)。 36 | 37 | 有关更多详细信息或其他选项,请参阅 [安装指南](install-zh_cn.md)。 38 | 39 | ## 初始化 Helm 并安装 Tiller 40 | 有了 Helm 安装文件,就可以初始化本地 CLI,并将 Tiller 安装到 Kubernetes 集群中: 41 | 42 | ```bash 43 | $ helm init --history-max 200 44 | ``` 45 | **TIP:** 推荐带 `--history-max 200` 参数, 因为 configmaps 和其他对象的历史记录会增长到很大的数量。没有这个参数的话,历史记录为永久保留,这样 Helm 和 Tiller 需要维护大量的历史数据. 46 | 47 | 这会将 Tiller 安装到对应的 Kubernetes 群集中, 集群同 `kubectl config current-context`。 48 | 49 | ** 提示:** 想要安装到不同的群集中?使用 --kube-context 参数。 50 | 51 | ** 提示:** 如果要升级 Tiller,请运行 helm init --upgrade。 52 | 53 | 默认情况下,安装 Tiller 时,没有启用身份验证。要了解有关为 Tiller 配置增强 TLS 身份验证的更多信息,请参阅 [Tiller TLS 指南](tiller_ssl-zh_cn.md)。 54 | 55 | ## 安装示例 Chart 56 | 要安装一个 chart,可以运行 `helm install` 命令。Helm 有几种方法来查找和安装 chart,但最简单的方法是使用其中一个官方 `stable` 稳定版本的 chart。 57 | 58 | ```bash 59 | $ helm repo update #确保我们获得最新的 chart 清单 60 | $ helm install stable/mysql 61 | Released smile-penguin 62 | NAME: wintering-rodent 63 | LAST DEPLOYED: Thu Oct 18 14:21:18 2018 64 | NAMESPACE: default 65 | STATUS: DEPLOYED 66 | 67 | RESOURCES: 68 | ==> v1/Secret 69 | NAME AGE 70 | wintering-rodent-mysql 0s 71 | 72 | ==> v1/ConfigMap 73 | wintering-rodent-mysql-test 0s 74 | 75 | ==> v1/PersistentVolumeClaim 76 | wintering-rodent-mysql 0s 77 | 78 | ==> v1/Service 79 | wintering-rodent-mysql 0s 80 | 81 | ==> v1beta1/Deployment 82 | wintering-rodent-mysql 0s 83 | 84 | ==> v1/Pod(related) 85 | 86 | NAME READY STATUS RESTARTS AGE 87 | wintering-rodent-mysql-6986fd6fb-988x7 0/1 Pending 0 0s 88 | 89 | 90 | NOTES: 91 | MySQL can be accessed via port 3306 on the following DNS name from within your cluster: 92 | wintering-rodent-mysql.default.svc.cluster.local 93 | 94 | To get your root password run: 95 | 96 | MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default wintering-rodent-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo) 97 | 98 | To connect to your database: 99 | 100 | 1. Run an Ubuntu pod that you can use as a client: 101 | 102 | kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il 103 | 104 | 2. Install the mysql client: 105 | 106 | $ apt-get update && apt-get install mysql-client -y 107 | 108 | 3. Connect using the mysql cli, then provide your password: 109 | $ mysql -h wintering-rodent-mysql -p 110 | 111 | To connect to your database directly from outside the K8s cluster: 112 | MYSQL_HOST=127.0.0.1 113 | MYSQL_PORT=3306 114 | 115 | # Execute the following command to route the connection: 116 | kubectl port-forward svc/wintering-rodent-mysql 3306 117 | 118 | mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD} 119 | 120 | 121 | ``` 122 | 在上面的例子中,stable/mysql 已经安装,安装版本的 release 的名字是 `wintering-rodent`。通过运行 `helm inspect stable/mysql` 可以简单了解这个 MySQL chart 的功能。 123 | 124 | 无论何时安装 chart,都会创建一个新 release 版本。所以一个 chart 可以多次安装到同一个群集中。而且每个都可以独立管理和升级。 125 | 126 | `helm install` 命令功能非常丰富,具有很多强大功能。要了解更多信息,请查看 [使用 Helm 指南](using_helm-zh_cn.md) 127 | 128 | ## 了解安装的 release 129 | 130 | 很容易通过如下命令查看已使用 Helm 安装的 release: 131 | 132 | ```bash 133 | $ helm ls 134 | +NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE 135 | +wintering-rodent 1 Thu Oct 18 15:06:58 2018 DEPLOYED mysql-0.10.1 5.7.14 default 136 | ``` 137 | 138 | ## 卸载安装的 release 139 | 140 | 要卸载安装的 release,请使用以下 `helm delete` 命令: 141 | 142 | ```bash 143 | $ helm delete wintering-rodent 144 | release "wintering-rodent" deleted 145 | ``` 146 | 147 | `wintering-rodent` release 将从 Kubernetes 卸载,但仍然可以查询有关该 release 的信息: 148 | 149 | ```bash 150 | $ helm status wintering-rodent 151 | LAST DEPLOYED: Thu Oct 18 14:21:18 2018 152 | NAMESPACE: default 153 | STATUS: DELETED 154 | 155 | NOTES: 156 | MySQL can be accessed via port 3306 on the following DNS name from within your cluster: 157 | wintering-rodent-mysql.default.svc.cluster.local 158 | 159 | To get your root password run: 160 | 161 | MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default wintering-rodent-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo) 162 | 163 | To connect to your database: 164 | 165 | 1. Run an Ubuntu pod that you can use as a client: 166 | 167 | kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il 168 | 169 | 2. Install the mysql client: 170 | 171 | $ apt-get update && apt-get install mysql-client -y 172 | 173 | 3. Connect using the mysql cli, then provide your password: 174 | $ mysql -h wintering-rodent-mysql -p 175 | 176 | To connect to your database directly from outside the K8s cluster: 177 | MYSQL_HOST=127.0.0.1 178 | MYSQL_PORT=3306 179 | 180 | # Execute the following command to route the connection: 181 | kubectl port-forward svc/wintering-rodent-mysql 3306 182 | 183 | mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD} 184 | 185 | ``` 186 | 187 | 由于 Helm 在删除它们之后也会跟踪该 release,因此可以审核群集的历史记录,甚至可以取消删除动作(使用 `helm rollback`)。 188 | 189 | ## 阅读帮助文本 190 | 191 | 要了解有关 Helm 命令的更多信息,请使用 `helm help` 或键入一个后跟 `-h` 标志的命令: 192 | 193 | ```bash 194 | $ helm get -h 195 | ``` 196 | -------------------------------------------------------------------------------- /quickstart/rbac-zh_cn.md: -------------------------------------------------------------------------------- 1 | # RBAC - 基于角色的访问控制 2 | 3 | 在 Kubernetes 中,确保应用程序在指定的范围内运行, 最佳的做法是,为特定的应用程序的服务帐户授予角色。要详细了解服务帐户权限请阅读 [官方 Kubernetes 文档](https://kubernetes.io/docs/admin/authorization/rbac/#service-account-permissions). 4 | 5 | Bitnami 写了一个在集群中配置 RBAC 的 [指导](https://docs.bitnami.com/kubernetes/how-to/configure-rbac-in-your-kubernetes-cluster/),可让你了解 RBAC 基础知识。 6 | 7 | 本指南面向希望对 Helm 限制如下权限的用户: 8 | 1. Tiller 将资源安装到特定 namespace 能力 9 | 2. 授权 Helm 客户端对 Tiller 实例的访问 10 | 11 | ## Tiller 和基于角色的访问控制 12 | 13 | 14 | 可以在配置 Helm 时使用 `--service-account ` 参数将服务帐户添加到 Tiller 。前提条件是必须创建一个角色绑定,来指定预先设置的角色 [role](https://kubernetes.io/docs/admin/authorization/rbac/#role-and-clusterrole) 和服务帐户 [service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) 名称。 15 | 16 | 在前提条件下,并且有了一个具有正确权限的服务帐户,就可以像这样运行一个命令来初始化 Tiller: `helm init --service-account ` 17 | 18 | ### Example: 服务账户带有 cluster-admin 角色权限 19 | 20 | ```bash 21 | $ kubectl create serviceaccount tiller --namespace kube-system 22 | serviceaccount "tiller" created 23 | ``` 24 | 25 | 文件 `rbac-config.yaml`: 26 | 27 | ```yaml 28 | apiVersion: v1 29 | kind: ServiceAccount 30 | metadata: 31 | name: tiller 32 | namespace: kube-system 33 | --- 34 | apiVersion: rbac.authorization.k8s.io/v1 35 | kind: ClusterRoleBinding 36 | metadata: 37 | name: tiller 38 | roleRef: 39 | apiGroup: rbac.authorization.k8s.io 40 | kind: ClusterRole 41 | name: cluster-admin 42 | subjects: 43 | - kind: ServiceAccount 44 | name: tiller 45 | namespace: kube-system 46 | ``` 47 | 48 | _Note: cluster-admin 角色是在 Kubernetes 集群中默认创建的,因此不必再显式地定义它。_ 49 | 50 | ```bash 51 | $ kubectl create -f rbac-config.yaml 52 | serviceaccount "tiller" created 53 | clusterrolebinding "tiller" created 54 | $ helm init --service-account tiller --history-max 200 55 | ``` 56 | 57 | ### 在特定 namespace 中部署 Tiller,并仅限于在该 namespace 中部署资源 58 | 59 | 在上面的例子中,我们让 Tiller 管理访问整个集群。当然,Tiller 正常工作并不一定要为它设置集群管理员访问权限。我们可以指定 Role 和 RoleBinding 来将 Tiller 的范围限制为特定的 namespace,而不是指定 ClusterRole 或 ClusterRoleBinding。 60 | 61 | ```bash 62 | $ kubectl create namespace tiller-world 63 | namespace "tiller-world" created 64 | $ kubectl create serviceaccount tiller --namespace tiller-world 65 | serviceaccount "tiller" created 66 | ``` 67 | 68 | 定义允许 Tiller 管理 namespace `tiller-world` 中所有资源的角色 ,文件 `role-tiller.yaml`: 69 | 70 | ```yaml 71 | kind: Role 72 | apiVersion: rbac.authorization.k8s.io/v11 73 | metadata: 74 | name: tiller-manager 75 | namespace: tiller-world 76 | rules: 77 | - apiGroups: ["","extensions","apps"] 78 | resources: ["*"] 79 | verbs: ["*"] 80 | ``` 81 | 82 | ```bash 83 | $ kubectl create -f role-tiller.yaml 84 | role "tiller-manager" created 85 | ``` 86 | 87 | 文件 `rolebinding-tiller.yaml`, 88 | 89 | ```yaml 90 | kind: RoleBinding 91 | apiVersion: rbac.authorization.k8s.io/v11 92 | metadata: 93 | name: tiller-binding 94 | namespace: tiller-world 95 | subjects: 96 | - kind: ServiceAccount 97 | name: tiller 98 | namespace: tiller-world 99 | roleRef: 100 | kind: Role 101 | name: tiller-manager 102 | apiGroup: rbac.authorization.k8s.io 103 | ``` 104 | 105 | ```bash 106 | $ kubectl create -f rolebinding-tiller.yaml 107 | rolebinding "tiller-binding" created 108 | ``` 109 | 110 | 之后,运行 `helm init` 来在 `tiller-world` namespace 中安装 Tiller 。 111 | 112 | ```bash 113 | $ helm init --service-account tiller --tiller-namespace tiller-world 114 | $HELM_HOME has been configured at /Users/awesome-user/.helm. 115 | 116 | Tiller (the Helm server side component) has been installed into your Kubernetes Cluster. 117 | Happy Helming! 118 | 119 | $ helm install nginx --tiller-namespace tiller-world --namespace tiller-world 120 | NAME: wayfaring-yak 121 | LAST DEPLOYED: Mon Aug 7 16:00:16 2017 122 | NAMESPACE: tiller-world 123 | STATUS: DEPLOYED 124 | 125 | RESOURCES: 126 | ==> v1/Pod 127 | NAME READY STATUS RESTARTS AGE 128 | wayfaring-yak-alpine 0/1 ContainerCreating 0 0s 129 | ``` 130 | 131 | ### Example: 在一个 namespace 中部署 Tiller,并限制它在另一个 namespace 部署资源 132 | 133 | 在上面的例子中,我们让 Tiller 管理它部署所在的 namespace。现在,让我们限制 Tiller 的范围,将资源部署在不同的 namespace 中! 134 | 135 | 下面例子中,让我们在 `myorg-system` namespace 中安装 Tiller,并允许 Tiller 在 `myorg-users` namespace 中部署资源。 136 | 137 | ```bash 138 | $ kubectl create namespace myorg-system 139 | namespace "myorg-system" created 140 | $ kubectl create serviceaccount tiller --namespace myorg-system 141 | serviceaccount "tiller" created 142 | ``` 143 | 144 | 在 `role-tiller.yaml` 中,定义了一个允许 Tiller 管理所有 `myorg-users` 资源的角色: 145 | 146 | ```yaml 147 | kind: Role 148 | apiVersion: rbac.authorization.k8s.io/v11 149 | metadata: 150 | name: tiller-manager 151 | namespace: myorg-users 152 | rules: 153 | - apiGroups: ["","extensions","apps"] 154 | resources: ["*"] 155 | verbs: ["*"] 156 | ``` 157 | 158 | ```bash 159 | $ kubectl create -f role-tiller.yaml 160 | role "tiller-manager" created 161 | ``` 162 | 163 | 将 service account 与那个 role 绑定. `rolebinding-tiller.yaml`, 164 | 165 | ```yaml 166 | kind: RoleBinding 167 | apiVersion: rbac.authorization.k8s.io/v11 168 | metadata: 169 | name: tiller-binding 170 | namespace: myorg-users 171 | subjects: 172 | - kind: ServiceAccount 173 | name: tiller 174 | namespace: myorg-system 175 | roleRef: 176 | kind: Role 177 | name: tiller-manager 178 | apiGroup: rbac.authorization.k8s.io 179 | ``` 180 | 181 | ```bash 182 | $ kubectl create -f rolebinding-tiller.yaml 183 | rolebinding "tiller-binding" created 184 | ``` 185 | 我们还需要授予 Tiller 访问权限来读取 `myorg-system` 中的 configmaps,以便它可以存储 release 信息。如 `role-tiller-myorg-system.yaml`: 186 | 187 | ```yaml 188 | kind: Role 189 | apiVersion: rbac.authorization.k8s.io/v11 190 | metadata: 191 | namespace: myorg-system 192 | name: tiller-manager 193 | rules: 194 | - apiGroups: ["","extensions","apps"] 195 | resources: ["configmaps"] 196 | verbs: ["*"] 197 | ``` 198 | 199 | ```bash 200 | $ kubectl create -f role-tiller-myorg-system.yaml 201 | role "tiller-manager" created 202 | ``` 203 | 204 | 相应的 role 绑定. 如 `rolebinding-tiller-myorg-system.yaml`: 205 | 206 | ```yaml 207 | kind: RoleBinding 208 | apiVersion: rbac.authorization.k8s.io/v11 209 | metadata: 210 | name: tiller-binding 211 | namespace: myorg-system 212 | subjects: 213 | - kind: ServiceAccount 214 | name: tiller 215 | namespace: myorg-system 216 | roleRef: 217 | kind: Role 218 | name: tiller-manager 219 | apiGroup: rbac.authorization.k8s.io 220 | ``` 221 | 222 | ```bash 223 | $ kubectl create -f rolebinding-tiller-myorg-system.yaml 224 | rolebinding "tiller-binding" created 225 | ``` 226 | 227 | ## Helm 和基于角色的访问控制 228 | 229 | 在 pod 中运行 Helm 客户端时,为了让 Helm 客户端与 Tiller 实例进行通信,需要授予某些特权。具体来说,Helm 客户端需要能够创建 pods,转发端口并能够在 Tiller 运行的 namespace 中列出 pod(这样它才可以找到 Tiller)。 230 | 231 | ### Example: 在一个 namespace 中部署 Helm,与在另一个 namespace 中与 Tiller 交互 232 | 233 | 在这个例子中,我们将假设 Tiller 在名为 `tiller-world` 的 namespace 中运行,并且 Helm 客户端在 `helm-world` 的 namespace 中运行。默认情况下,Tiller 在 `kube-system` namespace 中运行。 234 | 235 | 如 `helm-user.yaml`: 236 | 237 | ```yaml 238 | apiVersion: v1 239 | kind: ServiceAccount 240 | metadata: 241 | name: helm 242 | namespace: helm-world 243 | --- 244 | apiVersion: rbac.authorization.k8s.io/v11 245 | kind: Role 246 | metadata: 247 | name: tiller-user 248 | namespace: tiller-world 249 | rules: 250 | - apiGroups: 251 | - "" 252 | resources: 253 | - pods/portforward 254 | verbs: 255 | - create 256 | - apiGroups: 257 | - "" 258 | resources: 259 | - pods 260 | verbs: 261 | - list 262 | --- 263 | apiVersion: rbac.authorization.k8s.io/v11 264 | kind: RoleBinding 265 | metadata: 266 | name: tiller-user-binding 267 | namespace: tiller-world 268 | roleRef: 269 | apiGroup: rbac.authorization.k8s.io 270 | kind: Role 271 | name: tiller-user 272 | subjects: 273 | - kind: ServiceAccount 274 | name: helm 275 | namespace: helm-world 276 | ``` 277 | 278 | ```bash 279 | $ kubectl create -f helm-user.yaml 280 | serviceaccount "helm" created 281 | role "tiller-user" created 282 | rolebinding "tiller-user-binding" created 283 | ``` 284 | -------------------------------------------------------------------------------- /quickstart/securing_installation-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 安全安装 2 | Helm 是一款强大而灵活的 Kubernetes 软件包管理和运维工具。使用默认安装命令 `helm init-` 可以快速轻松地安装它和 **Tiller**,与 Helm 相对应的服务端组件。 3 | 4 | 但是,默认安装没有启用任何安全配置。使用这种类型的安装在下面的场景下是完全合适的,在没有安全问题或几乎没有安全问题的群集时可以使用这种安装方式,例如使用 Minikube 进行本地开发,或者使用在专用网络中,安全性良好且无数据共享或无其他用户或团队。如果是这种情况,那么默认安装很合适,但请记住:权力越大,责任越大。决定使用默认安装时始终要注意相应的安全问题。 5 | 6 | ## 谁需要安全配置? 7 | 对于以下类型的集群,我们强烈建议使用正确的安全配置应用于 Helm 和 Tiller,以确保集群,集群中的数据以及它所连接的网络的安全性。 8 | 9 | - 暴露于不受控制的网络环境的群集:不受信任的网络参与者可以访问群集,也可以访问网络环境的不受信任的应用程序。 10 | - 许多人使用的群集 - 多租户群集 - 作为共享环境 11 | - 有权访问或使用高价值数据或任何类型网络的群集 12 | 13 | 通常,像这样的环境被称为 _生产等级_ 或 _生产质量_ 的环境,因为任何因滥用集群而对任何公司造成的损害对于客户,对公司本身或者两者都是深远的。一旦损害风险变得足够高,无论实际风险如何,都需要确保集群的安全完整性。 14 | 15 | 要为环境正确配置安装,必须: 16 | 17 | - 了解群集的安全上下文 18 | - 选择合适的 helm 安装的最佳实践 19 | 20 | 以下假定有一个 Kubernetes 配置文件(一个 kubeconfig 文件),或者有一个用于访问群集的文件。 21 | 22 | ## 了解群集的安全上下文 23 | helm init 将 Tiller 安装到 kube-system 名称空间中的集群中,而不应用任何 RBAC 规则。这适用于本地开发和其他私人场景,因为它可以让立即开始工作。它还使你能够继续使用没有基于角色的访问控制(RBAC)支持的 Kubernetes 群集来运行 Helm,直到可以将工作负载移动到更新的 Kubernetes 版本。 24 | 25 | 在 Tiller 安全安装时,需要考虑四个主要方面: 26 | 27 | 1. 基于角色的访问控制或 RBAC 28 | 2. Tiller 的 gRPC 端点及 Helm 的使用情况 29 | 3. Tiller 的 release 信息 30 | 4. Helm harts 31 | 32 | ### RBAC 33 | Kubernetes 的最新版本采用基于角色的访问控制([RBAC] (https://en.wikipedia.org/wiki/Role-based_access_control) )系统(与现代操作系统一样),以帮助缓解证书被滥用或存在错误时可能造成的损害。即使在身份被劫持的情况下,这个身份在受控空间也只有这么多的权限。这有效地增加了一层安全性,以限制使用该身份进行攻击的范围。 34 | 35 | Helm 和 Tiller 在安装,删除和修改逻辑应用程序时,可以包含许多服务交互。因此,它的使用通常涉及整个集群的操作,在多租户集群中意味着 Tiller 安装必须非常小心才能访问整个集群,以防止不正确的安全活动。 36 | 37 | 特定用户和团队 - 开发人员,运维人员,系统和网络管理员 - 需要他们自己的群集分区,以便他们可以使用 Helm 和 Tiller,而不会冒着集群其他分区的风险。这需要启用 RBAC 的 Kubernetes 集群,并配置 Tiller 的 RBAC 权限。有关在 Kubernetes 中使用 RBAC 的更多信息,请参阅使用 RBAC 授权 [Using RBAC Authorization](rbac-zh_cn.md)。 38 | 39 | #### Tiller 和用户权限 40 | 当前情况下的 Tiller 不提供将用户凭据映射到 Kubernetes 内的特定权限的方法。当 Tiller 在集群内部运行时,它将使用其服务帐户的权限运行。如果没有服务帐户名称提供给 Tiller,它将使用该名称空间的默认服务帐户运行。这意味着该服务器上的所有 Tiller 操作均使用 Tiller pod 的凭据和权限执行。 41 | 42 | 为了合适的限制 Tiller 本身的功能,标准 Kubernetes RBAC 机制必须配置到 Tiller 上,包括角色和角色绑定,这些角色明确的限制了 Tiller 实例可以安装什么以及在哪里安装。 43 | 44 | 这种情况在未来可能会改变。社区有几种方法可以解决这个问题,采用客户端权限而不是 Tiller 权限的情况下,活动的权限取决于 Pod 身份工作组,已经解决了的安全的一般性问题。 45 | 46 | ### Tiller gRPC 端点和 TLS 47 | 在默认安装中,Tiller 提供的 gRPC 端点在集群内部(不在集群外部)可用,不需要应用认证配置。如果不应用身份验证,集群中的任何进程都可以使用 gRPC 端点在集群内执行操作。在本地或安全的专用群集中,这可以实现快速使用并且是合适的。(当在集群外部运行时,Helm 通过 Kubernetes API 服务器进行身份验证,以达到 Tiller,利用现有的 Kubernetes 身份验证支持。) 48 | 49 | The following two sub-sections describe options of how to setup Tiller so there isn't an unauthenticated endpoint (i.e. gRPC) in your cluster. 50 | 51 | #### Enabling TLS 52 | 53 | (Note that out of the two options, this is the recommended one for Helm 2.) 54 | 共享和生产群集 - 大多数情况下 - 应至少使用 Helm 2.7.2,并为每个 Tiller gRPC 端点配置 TLS,以确保群集内 gRPC 端点的使用仅适用于该端点的正确身份验证标识。这样做可以在任意数量的 namespace 中部署任意数量的 Tiller 实例,任何 gRPC 端点未经授权不可使用。使用 Helm `init` 和 `--tiller-tls-verify` 选择安装启用 TLS 的 Tiller, 并验证远程证书,所有其他 Helm 命令都应该使用该 `--tls` 选项。 55 | 56 | 有关正确配置并使用 TLS 的 Tiller 和 Helm 的正确步骤的更多信息,请参阅下面的章节 [Best Practices](#Helm 和 Tiller 安全最佳实践) 以及 Helm 和 Tiller 使用 SSL[在 Helm 和 Tiller 之间使用 SSL](tiller_ssl-zh_cn.md)。 57 | 58 | 当 Helm 客户端从群集外部连接时,Helm 客户端和 API 服务器之间的安全性由 Kubernetes 本身管理。你可能需要确保这个链接是安全的。请注意,如果使用上面建议的 TLS 配置,则 Kubernetes API 服务器也无法访问客户端和 Tiller 之间的加密消息。 59 | 60 | #### Running Tiller Locally 61 | 62 | 与上面的章节 [Enabling TLS](#Enabling TLS) 相反, 本节不涉及在集群中运行分蘖服务器 pod(就其价值而言,它符合当前情况 [helm v3 proposal](https://github.com/helm/community/blob/master/helm-v3/000-helm-v3.md)), 因此没有 gRPC 端点(因此不需要创建和管理 TLS 证书来保护每个 gRPC 端点)。 63 | 64 | 步骤: 65 | * 获取最新安装包 [GitHub release page](https://github.com/helm/helm/releases), 解压缩,并将 `helm` and `tiller` 放到你的路径 `$PATH`. 66 | * "服务端": 运行 `tiller --storage=secret`. (`tiller` 默认监听 ":44134" 通过 `--listen` 参数.) 67 | * "客户端": 在另一个终端 (同一台运行 `tiller` 的机器上): 运行 `export HELM_HOST=:44134`, 然后运行 `helm`. 68 | 69 | ### Tiller Release 信息 70 | 由于历史原因,Tiller 将其 release 信息存储在 ConfigMaps 中。我们建议将默认设置更改为 Secrets。 71 | 72 | Secrets 是 Kubernetes 用于保存被认为是敏感的配置数据的可接受的方法。尽管 secrets 本身并不提供很多保护,但 Kubernetes 集群管理软件经常将它们与其他对象区别开来。因此,我们建议使用 secrets 来存储 release 信息。 73 | 74 | 启用此功能目前需要在 Tiller 部署时设置参数 `--storage=secret`。这需要直接修改 deployment 或使用 `helm init --override 'spec.template.spec.containers[0].command'='{/tiller,--storage=secret}'`,因为当前没有 helm init 参数可供执行此操作。 75 | 76 | ### 关于 chart 77 | 由于 Helm 的相对生命周期,Helm chart 生态系统的发展并没有考虑到整个集群的控制,这在开发人员来说,是完全合理的。但是,chart 是一种不仅可以安装可能已经验证或可能未验证的容器的包,它也可以安装到多个 namespace 中。 78 | 79 | 与所有共享的软件一样,在受控或共享的环境中,必须在安装之前验证自己安装的所有软件。如果已经通过 TLS 配置安装了 Tiller,并且只有一个或部分 namespace 的权限,某些 chart 可能无法安装 - 在这些环境中,这正是你想要的。如果需要使用 chart,可能必须与创建者一起工作或自行修改它,以便在应用了适当的 RBAC 规则的多租户群集中安全地使用它。`helm template` 命令在本地呈现 chart 并显示输出。 80 | 81 | 一旦通过检查,可以使用 Helm 的工具来确保使用的 chart 的出处和完整性 [ensure the provenance and integrity of charts](provenance.md)。 82 | 83 | ### gRPC 工具和安全 Tiller 配置 84 | 许多非常有用的工具直接使用 gRPC 接口,并且已经针对默认安装构建 - 它们提供了集群范围的访问 - 一旦应用了安全配置后就可能工作不正常。RBAC 策略由你或集群运维人员控制,并且可以针对该工具进行调整,或者可以将该工具配置为,在应用于 Tiller 的特定 RBAC 策略的约束范围内来正常工作。如果 gRPC 端点受到保护,则可能需要执行相同的操作:为了使用特定的 Tiller 实例,这些工具需要自己的安全 TLS 配置。RBAC 策略和 gRPC 工具一起配置的安全 gRPC 端点的组合,使你能够按照自己的需要控制群集环境。 85 | 86 | ## Helm 和 Tiller 安全最佳实践 87 | 以下指导原则重申了 Helm 和 Tiller 安全并正确使用它们的最佳方法。 88 | 89 | 1. 创建一个启用了 RBAC 的集群 90 | 2. 配置每个 Tiller gRPC 端点以使用单独的 TLS 证书 91 | 3. Release 信息应该使用 Kubernetes Secret 92 | 4. 为每个用户,团队或其他具有 `--service-account` 参数,role 和 RoleBindings 的组织安装一个 Tiller 93 | 5. `helm init` 使用 --tiller-tls-verify,其他 Helm 命令 `--tls` 来强制验证 94 | 95 | 如果遵循这些步骤,则 helm init 命令可能如下所示: 96 | 97 | ```bash 98 | $ helm init \ 99 | --override 'spec.template.spec.containers[0].command'='{/tiller,--storage=secret}' \ 100 | --tiller-tls \ 101 | --tiller-tls-verify \ 102 | --tiller-tls-cert=cert.pem \ 103 | --tiller-tls-key=key.pem \ 104 | --tls-ca-cert=ca.pem \ 105 | --service-account=accountname 106 | ``` 107 | 108 | 此命令将通过gRPC进行强身份验证,release信息存储在Kubernetes Secret,并使用RBAC策略的服务帐户安装启动Tiller。 109 | -------------------------------------------------------------------------------- /quickstart/tiller_ssl-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 在 Helm 和 Tiller 之间使用 SSL 2 | 3 | 本文讲述了如何在 Helm 和 Tiller 之间创建强 SSL/TLS 连接。这里强调的是创建一个内部 CA,并使用 SSL 的加密和身份识别功能。 4 | 5 | > 在 Helm 2.3.0 中引入了对基于 TLS 的身份验证的支持 6 | 7 | 配置 SSL 是一个高级主题,需要你已了解 Helm 和 Tiller。 8 | 9 | ## 概述 10 | 11 | Tiller 认证模型使用客户端 SSL 证书。Tiller 自己使用证书认证授权验证这些证书。同样,客户端还通过证书授权验证 Tiller 的身份。 12 | 13 | 有许多可能的设置证书和权限的配置,但我们在这里覆盖的方法适用于大多数情况。 14 | 15 | > 从 Helm 2.7.2 开始,Tiller 要求客户端证书由其 CA 验证。在之前的版本中,Tiller 使用了允许自签名证书的较弱验证策略。 16 | 17 | 在本指南中,我们将展示如何: 18 | 19 | - 创建用于为 Tiller 客户端和服务端颁发证书的私有 CA. 20 | - 为 Tiller 创建证书 21 | - 为 Helm 客户端创建一个证书 22 | - 创建一个使用该证书的 Tiller 实例 23 | - 配置 Helm 客户端以使用 CA 和客户端证书 24 | 25 | 在本指南结束时,你应该有一个正在运行的 Tiller 实例,它只接受来自可以通过 SSL 证书进行身份验证的客户端的连接。 26 | 27 | ## 生成证书认证授权和证书 28 | 29 | 生成 SSL CA 的一种方法是通过 `openssl` 命令行工具。线上提供了许多指南和最佳实践文档。此文档着重于在少量时间内准备好配置。对于生产配置,我们建议读者阅读官方文档 [the official documentation](https://www.openssl.org) 并咨询其他资源。 30 | 31 | ### 生成证书授权 32 | 33 | 生成证书授权的最简单方法是运行两个命令: 34 | 35 | ```bash 36 | $ openssl genrsa -out ./ca.key.pem 4096 37 | $ openssl req -key ca.key.pem -new -x509 -days 7300 -sha256 -out ca.cert.pem -extensions v3_ca 38 | Enter pass phrase for ca.key.pem: 39 | You are about to be asked to enter information that will be incorporated 40 | into your certificate request. 41 | What you are about to enter is what is called a Distinguished Name or a DN. 42 | There are quite a few fields but you can leave some blank 43 | For some fields there will be a default value, 44 | If you enter '.', the field will be left blank. 45 | ----- 46 | Country Name (2 letter code) [AU]:US 47 | State or Province Name (full name) [Some-State]:CO 48 | Locality Name (eg, city) []:Boulder 49 | Organization Name (eg, company) [Internet Widgits Pty Ltd]:tiller 50 | Organizational Unit Name (eg, section) []: 51 | Common Name (e.g. server FQDN or YOUR name) []:tiller 52 | Email Address []:tiller@example.com 53 | ``` 54 | 55 | 请注意,上面输入的数据是样例数据。你应该根据自己的规格进行定制。 56 | 57 | 以上将生成一个密钥和一个 CA. 请注意,这两个文件非常重要。尤其是 key 文件要特别注意处理。 58 | 59 | 通常,你需要生成中间签名密钥。为了简洁起见,我们将使用我们的根 CA 签署密钥。 60 | 61 | ### 生成证书 62 | 63 | 我们将生成两个证书,每个证书代表一种证书类型: 64 | 65 | - 一个证书是用于 Tiller 的。每个 tiller 主机需要一个。 66 | - 一个证书是给用户的。每个 helm 用户需要一个。 67 | 68 | 由于生成这些命令的命令是相同的,我们将同时创建。名字将表明他们的目标用处。 69 | 70 | 首先,Tiller 密钥: 71 | 72 | ```bash 73 | $ openssl genrsa -out ./tiller.key.pem 4096 74 | Generating RSA private key, 4096 bit long modulus 75 | ..........................................................................................................................................................................................................................................................................................................................++ 76 | ............................................................................++ 77 | e is 65537 (0x10001) 78 | Enter pass phrase for ./tiller.key.pem: 79 | Verifying - Enter pass phrase for ./tiller.key.pem: 80 | ``` 81 | 82 | 接下来,生成 Helm 客户端的密钥: 83 | 84 | ```bash 85 | $ openssl genrsa -out ./helm.key.pem 4096 86 | Generating RSA private key, 4096 bit long modulus 87 | .....++ 88 | ......................................................................................................................................................................................++ 89 | e is 65537 (0x10001) 90 | Enter pass phrase for ./helm.key.pem: 91 | Verifying - Enter pass phrase for ./helm.key.pem: 92 | ``` 93 | 94 | 同样,对于生产用途,将为每个用户生成一个客户端证书。 95 | 96 | 接下来,我们需要从这些密钥创建证书。对于每个证书,这有两个步骤,创建 CSR,然后创建证书。 97 | 98 | 99 | ```bash 100 | $ openssl req -key tiller.key.pem -new -sha256 -out tiller.csr.pem 101 | Enter pass phrase for tiller.key.pem: 102 | You are about to be asked to enter information that will be incorporated 103 | into your certificate request. 104 | What you are about to enter is what is called a Distinguished Name or a DN. 105 | There are quite a few fields but you can leave some blank 106 | For some fields there will be a default value, 107 | If you enter '.', the field will be left blank. 108 | ----- 109 | Country Name (2 letter code) [AU]:US 110 | State or Province Name (full name) [Some-State]:CO 111 | Locality Name (eg, city) []:Boulder 112 | Organization Name (eg, company) [Internet Widgits Pty Ltd]:Tiller Server 113 | Organizational Unit Name (eg, section) []: 114 | Common Name (e.g. server FQDN or YOUR name) []:tiller-server 115 | Email Address []: 116 | 117 | Please enter the following 'extra' attributes 118 | to be sent with your certificate request 119 | A challenge password []: 120 | An optional company name []: 121 | ``` 122 | 123 | 我们为 Helm 客户端证书重复这一步骤: 124 | 125 | ```bash 126 | $ openssl req -key helm.key.pem -new -sha256 -out helm.csr.pem 127 | # Answer the questions with your client user's info 128 | ``` 129 | 130 | (在极少数情况下,我们必须在生成请求时添加标志 `-nodes`。) 131 | 132 | 现在我们使用我们创建的 CA 证书对每个 CSR 进行签名(调整 days 参数以满足你的要求): 133 | 134 | ```bash 135 | $ openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in tiller.csr.pem -out tiller.cert.pem -days 365 136 | Signature ok 137 | subject=/C=US/ST=CO/L=Boulder/O=Tiller Server/CN=tiller-server 138 | Getting CA Private Key 139 | Enter pass phrase for ca.key.pem: 140 | ``` 141 | 142 | 再次为客户证书: 143 | 144 | ```bash 145 | $ openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in helm.csr.pem -out helm.cert.pem -days 365 146 | ``` 147 | 148 | 到此,对我们来说重要的文件是这些: 149 | 150 | ``` 151 | # The CA. Make sure the key is kept secret. 152 | ca.cert.pem 153 | ca.key.pem 154 | # The Helm client files 155 | helm.cert.pem 156 | helm.key.pem 157 | # The Tiller server files. 158 | tiller.cert.pem 159 | tiller.key.pem 160 | ``` 161 | 162 | 现在我们准备好继续下一步。 163 | 164 | ## 创建自定义 Tiller 安装 165 | 166 | Helm 全面支持创建 SSL 配置的部署。通过指定几个标志,`helm init` 命令可以创建一个新的 Tiller 安装,并完成所有 SSL 配置。 167 | 168 | 要看看这将产生什么,运行这个命令: 169 | 170 | ```bash 171 | $ helm init --dry-run --debug --tiller-tls --tiller-tls-cert ./tiller.cert.pem --tiller-tls-key ./tiller.key.pem --tiller-tls-verify --tls-ca-cert ca.cert.pem 172 | ``` 173 | 174 | 输出将显示一个 Deployment,一个 Secret 和一个 Service。SSL 信息将预先加载到 Secret 中,Deployment 将在启动时挂载到 pod。 175 | 176 | 如果要定制 manifest,可以将该输出保存到文件中,然后用 kubectl create 它将其加载到群集中。 177 | 178 | > 我们强烈建议在集群上启用 RBAC 并 使用 RBAC 添加服务帐户 [service accounts](rbac.md)。 179 | 180 | 另外,可以删除 `--dry-run` 和 `--debug` 标志。我们还建议将 Tiller 放入非系统 namespace(`--tiller-namespace=something`)并启用服务帐户(`--service-account=somename`)。但是对于这个例子,我们将继续使用基础配置: 181 | 182 | ```bash 183 | $ helm init --tiller-tls --tiller-tls-cert ./tiller.cert.pem --tiller-tls-key ./tiller.key.pem --tiller-tls-verify --tls-ca-cert ca.cert.pem 184 | ``` 185 | 186 | 在一两分钟内它就应该准备好了。我们可以像这样检查 Tiller: 187 | 188 | ```bash 189 | $ kubectl -n kube-system get deployment 190 | NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE 191 | ... other stuff 192 | tiller-deploy 1 1 1 1 2m 193 | ``` 194 | 195 | 如果出现问题,可能需要使用 `kubectl get pods -n kube-system` 以找出问题所在。通过 SSL/TLS 支持,最常见的问题都与不正确生成的 TLS 证书有关,或意外更换证书和密钥。 196 | 197 | 此时,运行基本的 Helm 命令时应该会报错: 198 | 199 | 200 | ```bash 201 | $ helm ls 202 | Error: transport is closing 203 | ``` 204 | 205 | 这是因为您的 Helm 客户端没有正确的证书来向 Tiller 进行身份验证。 206 | 207 | ## 配置 Helm 客户端 208 | 209 | Tiller 服务现在运行通过 TLS 保护。现在需要配置 Helm 客户端来执行 TLS 操作。 210 | 211 | 对于快速测试,我们可以手动指定我们的配置。我们将运行一个普通的 Helm 命令(`helm ls`),但启用 SSL/TLS。 212 | 213 | ```bash 214 | helm ls --tls --tls-ca-cert ca.cert.pem --tls-cert helm.cert.pem --tls-key helm.key.pem 215 | ``` 216 | 217 | 此配置将发送我们的客户端证书以确认身份,使用客户端密钥进行加密,并使用 CA 证书验证远程 Tiller 的身份。 218 | 219 | 尽管如此,键入长命令很麻烦。快捷方法是将密钥,证书和 CA 移入 `$HELM_HOME`: 220 | 221 | ```bash 222 | $ cp ca.cert.pem $(helm home)/ca.pem 223 | $ cp helm.cert.pem $(helm home)/cert.pem 224 | $ cp helm.key.pem $(helm home)/key.pem 225 | ``` 226 | 227 | 有了这个,你可以简单地运行 helm ls --tls 以启用 TLS。 228 | 229 | ### 故障排除 230 | 231 | * 运行命令,报错 `Error: transport is closing`* 232 | 233 | 这几乎总是由于配置错误导致客户端缺少证书(`--tls-cert`)或证书不正确。 234 | 235 | * 我使用证书,但得到 `Error: remote error: tls: bad certificate`* 236 | 237 | 这意味着 Tiller 的 CA 无法验证你的证书。在上面的例子中,我们使用一个 CA 来生成客户端和服务端证书。在这些例子中,CA 已经签署了客户的证书。然后,我们将该 CA 加载到 Tiller。因此,当客户端证书发送到服务器时,Tiller 会根据 CA 检查客户端证书。 238 | 239 | * 如果我使用 `--tls-verify` 客户端,报错 `Error: x509: certificate is valid for tiller-server, not localhost`* 240 | 241 | 如果打算 --tls-verify 在客户端上使用,则需要确保 Helm 连接的主机名与证书上的主机名匹配。在某些情况下,这很尴尬,因为 Helm 将通过本地主机 localhost 连接,或者 FQDN 不可用于公共解析。 242 | 243 | * 如果我在客户端使用 `--tls-verify` , 返回报错信息 `Error: x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs`* 244 | 245 | 246 | 默认情况下,Helm 客户端通过隧道(即 kube 代理)127.0.0.1 连接到 Tiller。 在 TLS 握手期间,通常提供主机名(例如 example.com),对证书进行检查,包括附带的信息。 但是,由于通过隧道,目标是 IP 地址。因此,要验证证书,必须在 Tiller 证书中将 IP 地址 127.0.0.1 列为 IP 附带备用名称(IP SAN: IP subject alternative name)。 247 | 248 | 例如,要在生成 Tiller 证书时将 127.0.0.1 列为 IP SAN: 249 | 250 | ```bash 251 | $ echo subjectAltName=IP:127.0.0.1 > extfile.cnf 252 | $ openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in tiller.csr.pem -out tiller.cert.pem -days 365 -extfile extfile.cnf 253 | ``` 254 | 255 | 256 | * 如果我在客户端使用 `--tls-verify`,报错 `Error: x509: certificate has expired or is not yet valid`* 257 | 258 | 你的 Helm 证书已过期,需要使用你的私钥和 CA 签署新证书(并考虑增加天数) 259 | 260 | 如果你的 Tiller 证书已经过期,你需要签署一个新的证书,使用 base64 对它进行编码并更新 Tiller Secret: `kubectl edit secret tiller-secret` 261 | 262 | ## 参考 263 | https://github.com/denji/golang-tls 264 | 265 | https://www.openssl.org/docs/ 266 | 267 | https://jamielinux.com/docs/openssl-certificate-authority/sign-server-and-client-certificates.html 268 | -------------------------------------------------------------------------------- /quickstart/using_helm-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 使用 2 | 本指南讲述使用 Helm(和 Tiller)来管理 Kubernetes 群集上的软件包的基础知识。前提是假定你已经安装了 Helm 客户端和 Tiller 服务端(通常通过 helm init)。 3 | 4 | 如果只是想运行一些简单命令,可以从 [快速入门指南](quickstart-zh_cn.md) 开始。本章将介绍 Helm 命令的具体内容,并解释如何使用 Helm。 5 | 6 | ## 三大概念 7 | 8 | 一个 *Chart* 是一个 Helm 包。它包含在 Kubernetes 集群内部运行应用程序,工具或服务所需的所有资源定义。把它想像为一个自制软件,一个 Apt dpkg 或一个 Yum RPM 文件的 Kubernetes 环境里面的等价物。 9 | 10 | 一个 *Repository* 是 Charts 收集和共享的地方。它就像 Perl 的 [CPAN archive](https://www.cpan.org) 或 Fedora 软件包 repo[Fedora Package Database]((https://apps.fedoraproject.org/packages/s/pkgdb)。 11 | 12 | 一个 *Release* 是处于 Kubernetes 集群中运行的 Chart 的一个实例。一个 chart 通常可以多次安装到同一个群集中。每次安装时,都会创建一个新 _release_ 。比如像一个 MySQL chart。如果希望在群集中运行两个数据库,则可以安装该 chart 两次。每个都有自己的 _release_,每个 _release_ 都有自己的 _release name_。 13 | 14 | 有了这些概念,我们现在可以这样解释 Helm: 15 | 16 | Helm 将 _charts_ 安装到 Kubernetes 中,每个安装创建一个新 _release_ 。要找到新的 chart,可以搜索 Helm charts 存储库 _repositories_。 17 | 18 | ## 'helm search': 查找 Charts 19 | 20 | 首次安装 Helm 时,它已预配置为使用官方 Kubernetes chart 存储库 repo。该 repo 包含许多精心设计和维护的 charts。此 charts repo 默认以 stable 命名。 21 | 22 | 可以通过运行 `helm search` 查看有哪些 charts 可用: 23 | 24 | ``` 25 | $ helm search 26 | NAME VERSION DESCRIPTION 27 | stable/drupal 0.3.2 One of the most versatile open source content m... 28 | stable/jenkins 0.1.0 A Jenkins Helm chart for Kubernetes. 29 | stable/mariadb 0.5.1 Chart for MariaDB 30 | stable/mysql 0.1.0 Chart for MySQL 31 | ... 32 | ``` 33 | 34 | 如果没有使用过滤条件,helm search 显示所有可用的 charts。可以通过使用过滤条件进行搜索来缩小搜索的结果范围: 35 | 36 | ``` 37 | $ helm search mysql 38 | NAME VERSION DESCRIPTION 39 | stable/mysql 0.1.0 Chart for MySQL 40 | stable/mariadb 0.5.1 Chart for MariaDB 41 | ``` 42 | 现在只会看到与过滤条件匹配的结果。 43 | 44 | 为什么 `mariadb` 在列表中?因为它的包描述与 MySQL 相关。我们可以使用 `helm inspect chart` 到这个: 45 | 46 | ``` 47 | $ helm inspect stable/mariadb 48 | Fetched stable/mariadb to mariadb-0.5.1.tgz 49 | description: Chart for MariaDB 50 | engine: gotpl 51 | home: https://mariadb.org 52 | keywords: 53 | - mariadb 54 | - mysql 55 | - database 56 | - sql 57 | ... 58 | ``` 59 | 60 | 搜索是找到可用软件包的好方法。一旦找到想要安装的软件包,可以使用 `helm install` 它来安装它。 61 | 62 | ## 'helm install':安装一个软件包 63 | 64 | 要安装新的软件包,请使用该 `helm install` 命令。最简单的方法,它只需要一个参数:chart 的名称。 65 | 66 | ``` 67 | $ helm install stable/mariadb 68 | Fetched stable/mariadb-0.3.0 to /Users/mattbutcher/Code/Go/src/k8s.io/helm/mariadb-0.3.0.tgz 69 | NAME: happy-panda 70 | LAST DEPLOYED: Wed Sep 28 12:32:28 2016 71 | NAMESPACE: default 72 | STATUS: DEPLOYED 73 | 74 | Resources: 75 | ==> extensions/Deployment 76 | NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE 77 | happy-panda-mariadb 1 0 0 0 1s 78 | 79 | ==> v1/Secret 80 | NAME TYPE DATA AGE 81 | happy-panda-mariadb Opaque 2 1s 82 | 83 | ==> v1/Service 84 | NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE 85 | happy-panda-mariadb 10.0.0.70 3306/TCP 1s 86 | 87 | 88 | Notes: 89 | MariaDB can be accessed via port 3306 on the following DNS name from within your cluster: 90 | happy-panda-mariadb.default.svc.cluster.local 91 | 92 | To connect to your database run the following command: 93 | 94 | kubectl run happy-panda-mariadb-client --rm --tty -i --image bitnami/mariadb --command -- mysql -h happy-panda-mariadb 95 | ``` 96 | 97 | 现在 mariadb chart 已安装,请注意,安装 chart 会创建一个新 _release_ 对象。上面的 release 被命名 为 `happy-panda`。(如果你想使用你自己的 release 名称,只需使用 --name 参数 配合 helm install。) 98 | 99 | 在安装过程中,`helm` 客户端将打印有关创建哪些资源的有用信息,release 的状态以及是否可以或应该采取其他的配置步骤。 100 | 101 | Helm 不会一直等到所有资源都运行才退出。许多 charts 需要大小超过 600M 的 Docker 镜像,因此可能需要很长时间才能安装到群集中。 102 | 103 | 要跟踪 release 状态或重新读取配置信息,可以使用 `helm status`: 104 | 105 | ``` 106 | $ helm status happy-panda 107 | Last Deployed: Wed Sep 28 12:32:28 2016 108 | Namespace: default 109 | Status: DEPLOYED 110 | 111 | Resources: 112 | ==> v1/Service 113 | NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE 114 | happy-panda-mariadb 10.0.0.70 3306/TCP 4m 115 | 116 | ==> extensions/Deployment 117 | NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE 118 | happy-panda-mariadb 1 1 1 1 4m 119 | 120 | ==> v1/Secret 121 | NAME TYPE DATA AGE 122 | happy-panda-mariadb Opaque 2 4m 123 | 124 | 125 | Notes: 126 | MariaDB can be accessed via port 3306 on the following DNS name from within your cluster: 127 | happy-panda-mariadb.default.svc.cluster.local 128 | 129 | To connect to your database run the following command: 130 | 131 | kubectl run happy-panda-mariadb-client --rm --tty -i --image bitnami/mariadb --command -- mysql -h happy-panda-mariadb 132 | ``` 133 | 134 | 以上显示了集群内 release 的当前状态。 135 | 136 | ### 在安装前自定义 chart 137 | 138 | 上面的安装方式使用 chart 的默认配置选项。很多时候,我们需要自定义 chart 以使用自定义配置。 139 | 140 | 要查看 chart 上可配置的选项,请使用 `helm inspect values`: 141 | 142 | ```bash 143 | helm inspect values stable/mariadb 144 | Fetched stable/mariadb-0.3.0.tgz to /Users/mattbutcher/Code/Go/src/k8s.io/helm/mariadb-0.3.0.tgz 145 | ## Bitnami MariaDB image version 146 | ## ref: https://hub.docker.com/r/bitnami/mariadb/tags/ 147 | ## 148 | ## Default: none 149 | imageTag: 10.1.14-r3 150 | 151 | ## Specify a imagePullPolicy 152 | ## Default to 'Always' if imageTag is 'latest', else set to 'IfNotPresent' 153 | ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images 154 | ## 155 | # imagePullPolicy: 156 | 157 | ## Specify password for root user 158 | ## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#setting-the-root-password-on-first-run 159 | ## 160 | # mariadbRootPassword: 161 | 162 | ## Create a database user 163 | ## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#creating-a-database-user-on-first-run 164 | ## 165 | # mariadbUser: 166 | # mariadbPassword: 167 | 168 | ## Create a database 169 | ## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#creating-a-database-on-first-run 170 | ## 171 | # mariadbDatabase: 172 | ``` 173 | 174 | 然后,可以在 YAML 格式的文件中覆盖任何这些设置,然后在安装过程中使用该文件。 175 | 176 | ```bash 177 | $ cat < config.yaml 178 | mariadbUser: user0 179 | mariadbDatabase: user0db 180 | EOF 181 | $ helm install -f config.yaml stable/mariadb 182 | ``` 183 | 184 | 以上将创建一个名称为 MariaDB 的默认用户 `user0`,并授予此用户对新创建 `user0db` 数据库的访问权限,其他使用这个 chart 的默认值。 185 | 186 | 在安装过程中有两种方式传递自定义配置数据: 187 | 188 | - --values(或 - f):指定一个 overrides 的 YAML 文件。可以指定多次,最右边的文件将优先使用 189 | - --set (也包括 `--set-string` 和 `--set-file`): :在命令行上指定 overrides。 190 | 191 | 如果两者都使用,则将 `--set` 值合并到 `--values` 更高的优先级中。指定的 override `--set` 将保存在 configmap 中。`--set` 可以通过使用特定的版本查看已经存在的值 `helm get values `,`--set` 设置的值可以通过运行 helm upgrade 带有 --reset-values 参数重置。 192 | 193 | #### `--set` 格式和限制 194 | 195 | `--set` 选项使用零个或多个 name/value 对。最简单的用法:--set name=value。YAML 的表示是: 196 | 197 | ```yaml 198 | name: value 199 | ``` 200 | 201 | 多个值由, 字符分隔。因此 --set a=b,c=d 变成: 202 | 203 | ```yaml 204 | a: b 205 | c: d 206 | ``` 207 | 208 | 支持更复杂的表达式。例如,--set outer.inner=value 变成这样: 209 | 210 | ```yaml 211 | outer: 212 | inner: value 213 | ``` 214 | 215 | 列表可以通过在 {和} 中包含值来表示。例如, --set name={a, b, c} 转化为: 216 | 217 | ```yaml 218 | name: 219 | - a 220 | - b 221 | - c 222 | ``` 223 | 224 | 从 Helm 2.5.0 开始,可以使用数组索引语法访问列表项。例如,--set servers[0].port=80 变成: 225 | 226 | ```yaml 227 | servers: 228 | - port: 80 229 | ``` 230 | 231 | 可以通过这种方式设置多个值。该行 --set servers[0].port=80,servers[0].host=example 变成: 232 | 233 | ```yaml 234 | servers: 235 | - port: 80 236 | host: example 237 | ``` 238 | 239 | 有时候你需要在 `--set` 行中使用特殊字符。可以使用反斜杠来转义字符; `--set name="value1\,value2"` 会变成: 240 | 241 | ```yaml 242 | name: "value1,value2" 243 | ``` 244 | 245 | 同样,也可以转义点序列,这可能在 chart 中使用 `toYaml` 函数解析注释,标签和节点选择器时派上用场 。--set nodeSelector."kubernetes\.io/role"=master 的语法变为: 246 | 247 | ```yaml 248 | nodeSelector: 249 | kubernetes.io/role: master 250 | ``` 251 | 252 | 使用深层嵌套的数据结构可能很难用 `--set` 表达。鼓励 chart 设计师在设计 values.yaml 文件格式时考虑 `--set` 使用情况。 253 | 254 | Helm 会使用 `--set` 将指定的某些值转换为整数。例如,`--set foo = true`Helm 会将 `true` 强制转换为 int64 值。如果你想要一个字符串,请使用 `--set` 的变体名为 `--set-string`。 `--set-string foo = true` 会设置字符串值为 `"true"`。 255 | 256 | `--set-file key = filepath` 是 `--set` 的另一种变体。 它读取文件并将其内容用作值。 它的一个示例用例是将多行文本注入值而不处理 YAML 中的缩进。 假设您要创建一个 [brigade](https://github.com/Azure/brigade) 项目,其中包含包含 5 行 JavaScript 代码的特定值,您可以编写一个 `values.yaml`,如: 257 | 258 | ```yaml 259 | defaultScript: | 260 | const {events, Job} = require("brigadier") 261 | function run(e, project) { 262 | console.log("hello default script") 263 | } 264 | events.on("run", run) 265 | ``` 266 | 267 | 嵌入在 YAML 中,这使你更难以使用支持编写代码的 IDE 功能和测试框架等。 因此,你可以使用 `-set-file defaultScript = brigade.js` 替代,`brigade.js` 包含: 268 | 269 | ```javascript 270 | const {events, Job} = require("brigadier") 271 | function run(e, project) { 272 | console.log("hello default script") 273 | } 274 | events.on("run", run) 275 | ``` 276 | 277 | ### 更多的安装方法 278 | helm install 命令可以从多个来源安装: 279 | 280 | - 一个 chart repository (像上面看到的) 281 | - 一个本地 chart 压缩包 (`helm install foo-0.1.1.tgz`) 282 | - 一个解压后的 chart 目录 (`helm install path/to/foo`) 283 | - 一个完整 URL (`helm install https://example.com/charts/foo-1.2.3.tgz`) 284 | 285 | 286 | ## 'helm upgrade' and 'helm rollback':升级版本和失败时恢复 287 | 当新版本的 chart 发布时,或者当你想要更改 release 配置时,可以使用 `helm upgrade` 命令。 288 | 289 | 升级需要已有的 release 并根据提供的信息进行升级。由于 Kubernetes chart 可能很大而且很复杂,因此 Helm 会尝试执行最小侵入式升级。它只会更新自上次发布以来发生更改的内容。 290 | 291 | ```bash 292 | $ helm upgrade -f panda.yaml happy-panda stable/mariadb 293 | Fetched stable/mariadb-0.3.0.tgz to /Users/mattbutcher/Code/Go/src/k8s.io/helm/mariadb-0.3.0.tgz 294 | happy-panda has been upgraded. Happy Helming! 295 | Last Deployed: Wed Sep 28 12:47:54 2016 296 | Namespace: default 297 | Status: DEPLOYED 298 | ... 299 | ``` 300 | 301 | 在上面的例子中,happy-panda release 使用相同的 chart 进行升级,但使用新的 YAML 文件: 302 | 303 | ```yaml 304 | mariadbUser: user1 305 | ``` 306 | 307 | 我们可以使用 `helm get values` 看看这个新设置是否生效。 308 | 309 | ```bash 310 | $ helm get values happy-panda 311 | mariadbUser: user1 312 | ``` 313 | 314 | 该 helm get 命令是查看集群中的 release 的有用工具。正如我们上面所看到的,它表明我们的新值 panda.yaml 已被部署到群集中。 315 | 316 | 现在,如果在发布过程中某些事情没有按计划进行,那么使用回滚到以前的版本很容易 `helm rollback [RELEASE] [REVISION]`。 317 | 318 | ```bash 319 | $ helm rollback happy-panda 1 320 | ``` 321 | 322 | 上述回滚我们的 “happy-panda” 到它的第一个 release 版本。release 版本是增量修订。每次安装,升级或回滚时,修订版本号都会增加 1. 第一个修订版本号始终为 1. 我们可以使用 `helm history [RELEASE]` 查看特定版本的修订版号。 323 | 324 | ## 安装 / 升级 / 回滚的有用选项 325 | 在安装 / 升级 / 回滚期间,可以指定几个其他有用的选项来定制 Helm 的行为。请注意,这不是 cli 参数的完整列表。要查看所有参数的说明,请运行 helm --help。 326 | 327 | - `--timeout`:等待 Kubernetes 命令完成的超时时间值(秒),默认值为 300(5 分钟) 328 | - `--wait`:等待所有 Pod 都处于就绪状态,PVC 绑定完,将 release 标记为成功之前,Deployments 有最小(Desired-maxUnavailable)Pod 处于就绪状态,并且服务具有 IP 地址(如果是 `LoadBalancer`,则为 Ingress )。它会等待 `--timeout` 的值。如果达到超时,release 将被标记为 FAILED。注意:在部署 replicas 设置为 1 maxUnavailable 且未设置为 0,作为滚动更新策略的一部分的情况下, `--wait` 它将返回就绪状态,因为它已满足就绪状态下的最小 Pod。 329 | - `--no-hooks`:这会跳过命令的运行钩子 330 | - `--recreate-pods`(仅适用于 upgrade 和 rollback):此参数将导致重新创建所有 pod(属于 deployment 的 pod 除外) 331 | 332 | ## 'helm delete':删除 Release 333 | 334 | 在需要从群集中卸载或删除 release 时,请使用以下 `helm delete` 命令: 335 | 336 | ``` 337 | $ helm delete happy-panda 338 | ``` 339 | 340 | 这将从集群中删除该 release。可以使用以下 helm list 命令查看当前部署的所有 release: 341 | 342 | ``` 343 | $ helm list 344 | NAME VERSION UPDATED STATUS CHART 345 | inky-cat 1 Wed Sep 28 12:59:46 2016 DEPLOYED alpine-0.1.0 346 | ``` 347 | 348 | 从上面的输出中,我们可以看到该 happy-panda release 已被删除。 349 | 350 | 尽快如此,Helm 总是保留记录发生了什么。需要查看已删除的版本?`helm list --deleted` 可显示这些内容,并 `helm list --all` 显示了所有 release(已删除和当前部署的,以及失败的版本): 351 | 352 | 353 | ```bash 354 | ⇒ helm list --all 355 | NAME VERSION UPDATED STATUS CHART 356 | happy-panda 2 Wed Sep 28 12:47:54 2016 DELETED mariadb-0.3.0 357 | inky-cat 1 Wed Sep 28 12:59:46 2016 DEPLOYED alpine-0.1.0 358 | kindred-angelf 2 Tue Sep 27 16:16:10 2016 DELETED alpine-0.1.0 359 | ``` 360 | 361 | 由于 Helm 保留已删除 release 的记录,因此不能重新使用 release 名称。(如果 _确实_ 需要重新使用此 release 名称,则可以使用此 `--replace` 参数,但它只会重用现有 release 并替换其资源。) 362 | 363 | 请注意,因为 release 以这种方式保存,所以可以回滚已删除的资源并重新激活它。 364 | 365 | ## 'helm repo':使用存储库 366 | 367 | 到目前为止,我们一直只从 stable 存储库 repo 安装 chart。但是可以配置 helm 使用其他 repo。Helm 在该 helm repo 命令下提供了多个 repo 工具。 368 | 369 | 可以使用 helm repo list 以下命令查看配置了哪些 repo: 370 | 371 | ```bash 372 | $ helm repo list 373 | NAME URL 374 | stable https://kubernetes-charts.storage.googleapis.com 375 | local http://localhost:8879/charts 376 | mumoshu https://mumoshu.github.io/charts 377 | ``` 378 | 379 | 新的 repo 可以通过 `helm repo add` 添加: 380 | 381 | ```bash 382 | $ helm repo add dev https://example.com/dev-charts 383 | ``` 384 | 385 | 由于 chart repo 经常更改,因此可以随时通过运行 `helm repo updat` 确保 Helm 客户端处于最新状态。 386 | 387 | ## 创建你自己的 charts 388 | 该 chart 开发指南 [Chart Development Guide](../chart/charts-zh_cn.md) 介绍了如何开发自己的 charts。也可以通过使用以下 helm create 命令快速入门: 389 | 390 | ```bash 391 | $ helm create deis-workflow 392 | Creating deis-workflow 393 | ``` 394 | 395 | 现在有一个 chart`./deis-workflow`。可以编辑它并创建自己的模板。 396 | 397 | 在编辑 chart 时,可以通过 `helm lint` 验证它是否格式正确。 398 | 399 | 当将 chart 打包分发时,可以运行以下 helm package 命令: 400 | 401 | ```bash 402 | $ helm package deis-workflow 403 | deis-workflow-0.1.0.tgz 404 | ``` 405 | 406 | 现在可以通过 `helm install` 以下方式轻松安装该 chart: 407 | 408 | ```bash 409 | $ helm install ./deis-workflow-0.1.0.tgz 410 | ... 411 | ``` 412 | 413 | 可以将已归档的 chart 加载到 chart repo 中。请参阅 chart repo 服务器的文档以了解如何上传。 414 | 415 | 注意:stable repo 在 Helm Charts GitHub 存储库 [Helm Charts GitHub repository](https://github.com/helm/charts) 上进行管理。该项目接受 chart 源代码,并且(在审计后)自动打包。 416 | 417 | ## Tiller,Namespaces 和 RBAC 418 | 在某些情况下,可能希望将 Tiller 的范围或将多个 Tillers 部署到单个群集。以下是在这些情况下操作的一些最佳做法。 419 | 420 | 1. Tiller 可以安装到任何 namespace。默认情况下,它安装在 kube-system 中。可以运行多个 Tillers,只要它们各自在自己的 namespace 中运行。 421 | 2. 限制 Tiller 只能安装到特定的 namespace 和 / 或资源类型由 Kubernetes RBAC 角色和角色绑定控制。可以通过在配置 Helm 时通过 `helm init --service-account ` 向 Tiller 添加服务帐户。你可以在这里 [here](rbac-zh_cn.md). 找到更多的信息。 422 | 3. Release 名称在每个 Tiller 实例中是唯一的。 423 | 4. chart 应该只包含存在于单个命名空间中的资源。 424 | 5. 不建议将多个 Tillers 配置为在相同的命名空间中管理资源。 425 | ## 总结 426 | 427 | 本章介绍了 helm 客户端的基本使用模式,包括搜索,安装,升级和删除。它也涵盖了有用的工具命令类似如 `helm status`,`helm get` 和 `helm repo`。 428 | 429 | 有关这些命令的更多信息,请查看 Helm 的内置帮助:`helm help`。 430 | 431 | 在下一章中,我们将看看开发chart的过程。 432 | -------------------------------------------------------------------------------- /related-zh_cn.md: -------------------------------------------------------------------------------- 1 | # 相关项目和文档 2 | Helm 社区已经制作了许多关于 Helm 的额外工具,插件和文档。我们喜欢听到这些项目。如果有任何想要添加到此列表中的内容,请 [issue](https://github.com/kubernetes/helm/issues) 3 | 或 [pull request](https://github.com/kubernetes/helm/pulls)。 4 | 5 | ## 文章,博客,操作方法和额外文档 6 | - [Awesome Helm](https://github.com/cdwv/awesome-helm) - List of awesome Helm resources 7 | - [CI/CD with Kubernetes, Helm & Wercker](https://www.slideshare.net/Diacode/cicd-with-kubernetes-helm-wercker-madscalability) 8 | - [Creating a Helm Plugin in 3 Steps](http://technosophos.com/2017/03/21/creating-a-helm-plugin.html) 9 | - [Awesome Helm](https://github.com/cdwv/awesome-helm) - List of awesome Helm resources 10 | - [Deploying Kubernetes Applications with Helm](https://cloudacademy.com/blog/deploying-kubernetes-applications-with-helm/) 11 | - [GitLab, Consumer Driven Contracts, Helm and Kubernetes](https://medium.com/@enxebre/gitlab-consumer-driven-contracts-helm-and-kubernetes-b7235a60a1cb#.xwp1y4tgi) 12 | - [Honestbee's Helm Chart Conventions](https://gist.github.com/so0k/f927a4b60003cedd101a0911757c605a) 13 | - [Releasing backward-incompatible changes: Kubernetes, Jenkins, Prometheus Operator, Helm and Traefik](https://medium.com/@enxebre/releasing-backward-incompatible-changes-kubernetes-jenkins-plugin-prometheus-operator-helm-self-6263ca61a1b1#.e0c7elxhq) 14 | - [The Missing CI/CD Kubernetes Component: Helm package manager](https://hackernoon.com/the-missing-ci-cd-kubernetes-component-helm-package-manager-1fe002aac680#.691sk2zhu) 15 | - [Using Helm to Deploy to Kubernetes](https://daemonza.github.io/2017/02/20/using-helm-to-deploy-to-kubernetes/) 16 | - [Writing a Helm Chart](https://www.influxdata.com/packaged-kubernetes-deployments-writing-helm-chart/) 17 | - [A basic walk through Kubernetes Helm](https://github.com/muffin87/helm-tutorial) 18 | - [Tillerless Helm v2](https://rimusz.net/tillerless-helm/) 19 | 20 | ## 视频, 音频, and Podcast 21 | 22 | - [CI/CD with Jenkins, Kubernetes, and Helm](https://www.youtube.com/watch?v=NVoln4HdZOY): AKA "The Infamous Croc Hunter Video". 23 | - [Helm with Michelle Noorali and Matthew Butcher](https://gcppodcast.com/post/episode-50-helm-with-michelle-noorali-and-matthew-butcher/): The official Google CloudPlatform Podcast interviews Michelle and Matt about Helm. 24 | - [KubeCon2016: Delivering Kubernetes-Native Applications by Michelle Noorali](https://www.youtube.com/watch?v=zBc1goRfk3k&index=49&list=PLj6h78yzYM2PqgIGU1Qmi8nY7dqn9PCr4) 25 | 26 | 27 | ## Helm 插件 28 | 29 | - [App Registry](https://github.com/app-registry/helm-plugin) - Plugin to manage charts via the [App Registry specification](https://github.com/app-registry/spec) 30 | - [helm-backup](https://github.com/maorfr/helm-backup) - Plugin which performs backup/restore of releases in a namespace to/from a file 31 | - [Helm Diff](https://github.com/databus23/helm-diff) - Preview `helm upgrade` as a coloured diff 32 | - [Helm Value Store](https://github.com/skuid/helm-value-store) - Plugin for working with Helm deployment values 33 | - [Technosophos's Helm Plugins](https://github.com/technosophos/helm-plugins) - Plugins for GitHub, Keybase, and GPG 34 | - [helm-convert](https://github.com/ContainerSolutions/helm-convert) - Plugin to convert charts into Kustomize compatible packages 35 | - [helm-cos](https://github.com/imroc/helm-cos) - Plugin to manage repositories on Tencent Cloud Object Storage 36 | - [helm-edit](https://github.com/mstrzele/helm-edit) - Plugin for editing release's values 37 | - [helm-env](https://github.com/adamreese/helm-env) - Plugin to show current environment 38 | - [helm-gcs](https://github.com/nouney/helm-gcs) - Plugin to manage repositories on Google Cloud Storage 39 | - [helm-github](https://github.com/sagansystems/helm-github) - Plugin to install Helm Charts from Github repositories 40 | - [helm-hashtag](https://github.com/balboah/helm-hashtag) - Plugin for tracking docker tag hash digests as values 41 | - [helm-inject](https://github.com/maorfr/helm-inject) - Plugin for injecting additional configurations during release upgrade 42 | - [helm-k8comp](https://github.com/cststack/k8comp) - Plugin to create Helm Charts from hiera using k8comp 43 | - [helm-last](https://github.com/adamreese/helm-last) - Plugin to show the latest release 44 | - [helm-local](https://github.com/adamreese/helm-local) - Plugin to run Tiller as a local daemon 45 | - [helm-logs](https://github.com/maorfr/helm-logs) - Plugin to view changed releases over time 46 | - [helm-monitor](https://github.com/ContainerSolutions/helm-monitor) - Plugin to monitor a release and rollback based on Prometheus/ElasticSearch query 47 | - [helm-nuke](https://github.com/adamreese/helm-nuke) - Plugin to destroy all releases 48 | - [helm-plugin-utils](https://github.com/maorfr/helm-plugin-utils) - Utility functions to be used within Helm plugins 49 | - [helm-restore](https://github.com/maorfr/helm-restore) - Plugin to restore a deployed release to its original state 50 | - [helm-secrets](https://github.com/futuresimple/helm-secrets) - Plugin to manage and store secrets safely 51 | - [helm-stop](https://github.com/IBM/helm-stop) - Plugin for stopping a release pods 52 | - [helm-template](https://github.com/technosophos/helm-template) - Debug/render templates client-side 53 | - [helm-tiller](https://github.com/adamreese/helm-tiller) - Additional commands to work with Tiller 54 | - [helm-tiller-info](https://github.com/maorfr/helm-tiller-info) - Plugin which prints information about Tiller 55 | - [helm-unittest](https://github.com/lrills/helm-unittest) - Plugin for unit testing chart locally with YAML 56 | - [Tillerless Helm v2](https://github.com/rimusz/helm-tiller) - Helm plugin for using Tiller locally and in CI/CD pipelines 57 | We also encourage GitHub authors to use the [helm-plugin](https://github.com/search?q=topic%3Ahelm-plugin&type=Repositories) 58 | tag on their plugin repositories. 59 | 60 | 61 | 62 | ## 其他工具 63 | 分布在 Helm 或 Tiller 之上的工具。 64 | 65 | - [AppsCode Swift](https://github.com/appscode/swift) - Ajax friendly Helm Tiller Proxy using [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) 66 | - [Armada](https://github.com/att-comdev/armada) - Manage prefixed releases throughout various Kubernetes namespaces, and removes completed jobs for complex deployments. Used by the [Openstack-Helm](https://github.com/openstack/openstack-helm) team. 67 | - [Autohelm](https://github.com/reactiveops/autohelm) - Autohelm is _another_ simple declarative spec for deploying helm charts. Written in python and supports git urls as a source for helm charts. 68 | - [ChartMuseum](https://github.com/chartmuseum/chartmuseum) - Helm Chart Repository with support for Amazon S3 and Google Cloud Storage 69 | - [Chartify](https://github.com/appscode/chartify) - Generate Helm charts from existing Kubernetes resources. 70 | - [Codefresh](https://codefresh.io) - Kubernetes native CI/CD and management platform with UI dashboards for managing Helm charts and releases 71 | - [Cog](https://github.com/ohaiwalt/cog-helm) - Helm chart to deploy Cog on Kubernetes 72 | - [Drone.io Helm Plugin](http://plugins.drone.io/ipedrazas/drone-helm/) - Run Helm inside of the Drone CI/CD system 73 | - [Helm Chart Publisher](https://github.com/luizbafilho/helm-chart-publisher) - HTTP API for publishing Helm Charts in an easy way 74 | - [Helm.NET](https://github.com/qmfrederik/helm) - A .NET client for Tiller's API 75 | - [Helmfile](https://github.com/roboll/helmfile) - Helmfile is a declarative spec for deploying helm charts 76 | - [Helmsman](https://github.com/Praqma/helmsman) - Helmsman is a helm-charts-as-code tool which enables installing/upgrading/protecting/moving/deleting releases from version controlled desired state files (described in a simple TOML format). 77 | - [Landscaper](https://github.com/Eneco/landscaper/) - "Landscaper takes a set of Helm Chart references with values (a desired state), and realizes this in a Kubernetes cluster." 78 | - [Monocular](https://github.com/helm/monocular) - Web UI for Helm Chart repositories 79 | - [Orca](https://github.com/nuvo/orca) - Advanced CI\CD tool for Kubernetes and Helm made simple. 80 | - [Quay App Registry](https://coreos.com/blog/quay-application-registry-for-kubernetes.html) - Open Kubernetes application registry, including a Helm access client 81 | - [Rudder](https://github.com/AcalephStorage/rudder) - RESTful (JSON) proxy for Tiller's API 82 | - [Schelm](https://github.com/databus23/schelm) - Render a Helm manifest to a directory 83 | - [VIM-Kubernetes](https://github.com/andrewstuart/vim-kubernetes) - VIM plugin for Kubernetes and Helm 84 | 85 | ## 集成 Helm 86 | 87 | 包含 Helm 支持的平台,发行版和服务。 88 | 89 | - [Cabin](http://www.skippbox.com/cabin/) - Mobile App for Managing Kubernetes 90 | - [Fabric8](https://fabric8.io) - Integrated development platform for Kubernetes 91 | - [Jenkins X](https://jenkins-x.io/) - open source automated CI/CD for Kubernetes which uses Helm for [promoting](https://jenkins-x.io/about/features/#promotion) applications through [environments via GitOps](https://jenkins-x.io/about/features/#environments) 92 | - [Kubernetic](https://kubernetic.com/) - Kubernetes Desktop Client 93 | - [Qstack](https://qstack.com) 94 | 95 | ## 杂项 96 | 97 | 为 chart 作者和 Helm 用户抓取有用的东西 98 | 99 | - [Await](https://github.com/saltside/await) - Docker image to "await" different conditions--especially useful for init containers. [More Info](http://blog.slashdeploy.com/2017/02/16/introducing-await/) 100 | -------------------------------------------------------------------------------- /release_checklist-zh-cn.md: -------------------------------------------------------------------------------- 1 | # 版本发布 Checklist 2 | (感觉很通用,挺适合左右社区合作开发的软件项目) 3 | ** IMPORTANT 重要 ** : 如果你的经历与此文档不同, 请更新此文档以保持最新. 4 | 5 | ## 版本发布会 6 | 作为版本发布过程的一部分,每周开发者的两个电话会议将被选为 “版本会”。 7 | 8 | ### 开始版本周期 9 | 10 | 版本后的第一个开发人员电话会议将用作版本会议,以启动下一个版本周期。在此会议期间,必须确定以下事宜: 11 | 12 | - 版本日期 13 | - 此版本的目标 / 目的 14 | - 版本经理(谁来剪彩(冻结?)) 15 | - 社区的任何其他重要细节 16 | 17 | 所有这些信息都应添加到给定版本的 GitHub 里程碑中。在选择是否向特定版本添加问题和 PR 时,这应该为社区和维护者提供一套明确的指导原则。 18 | 19 | ### 结束(几乎)版本周期 20 | 21 | 最接近计划版本日期前两周的开发人员电话会议将用于审查应该推送到版本中的任何剩余的 PR。这是一个讨论我们是否应该在冻结版本和任何其他问题之前等待的地方。在本次会议结束时,如果版本日期尚未推出,则应该冻结第一个 RC。在此会议和版本日期之间的后续开发人员电话会议应该留出一些时间来查看是否发现了任何错误。达到版本日期后,可以冻结最终版本。 22 | 23 | ## 维护者发布 Helm 指南 24 | 25 | 如果你负责 Helm 的版本发布??太棒了,下面是需要做的事情 26 | ![TODO: Nothing](images/nothing.png) 27 | 28 | 开玩笑的哈 :trollface: 29 | 30 | 所有版本的格式均为 vX.YZ,其中 X 是主版本号,Y 是次版本号,Z 是补丁版本号。该项目严格遵循 [semantic versioning](https://semver.org/),因此遵循此步骤至关重要。 31 | 32 | 请务必注意,本文档假定存储库中与 “https://github.com/helm/helm” 对应的 git 远程名称为 “upstream”。如果不是(例如,如果您选择将其命名为 “origin” 或类似名称),请务必相应地调整列出的本地环境片段。如果不确定上游远程命名的是什么,请使用命令 git remote -v 来查找。 33 | 34 | 如果没有远端上游,可以使用以下方法轻松添加: 35 | 36 | ```shell 37 | git remote add upstream git@github.com:helm/helm.git 38 | ``` 39 | 40 | 在本文档中,我们将引用一些环境变量,你可能希望为方便起见而设置这些变量。对于主要 / 次要版本,请使用以下内容: 41 | 42 | ```shell 43 | export RELEASE_NAME=vX.Y.0 44 | export RELEASE_BRANCH_NAME="release-X.Y" 45 | export RELEASE_CANDIDATE_NAME="$RELEASE_NAME-rc.1" 46 | ``` 47 | 48 | 如果要创建修补程序版本,则可能需要使用以下代码: 49 | 50 | ```shell 51 | export PREVIOUS_PATCH_RELEASE=vX.Y.Z 52 | export RELEASE_NAME=vX.Y.Z+1 53 | export RELEASE_BRANCH_NAME="release-X.Y" 54 | export RELEASE_CANDIDATE_NAME="$RELEASE_NAME-rc.1" 55 | ``` 56 | 57 | ## 1. 创建版本分支 58 | 59 | ### 主要 / 次要版本 60 | 61 | 62 | 主要版本用于新功能添加和行为更改,从而 * 破坏了向后兼容性 * 。次要版本适用于不会破坏向后兼容性的新功能添加。要创建主要版本或次要版本,请首先从 master 创建分支 release-vX.Y.0 。 63 | 64 | ```shell 65 | git fetch upstream 66 | git checkout upstream/master 67 | git checkout -b $RELEASE_BRANCH_NAME 68 | ``` 69 | 70 | 这个新的分支将成为版本的基础,我们将在稍后进行迭代。 71 | 72 | ### 补丁版本 73 | 74 | 补丁版本是现有版本的一些关键修复程序。首先从最新的补丁版本创建分支 release-vX.Y.Z。 75 | 76 | ```shell 77 | git fetch upstream --tags 78 | git checkout $PREVIOUS_PATCH_RELEASE 79 | git checkout -b $RELEASE_BRANCH_NAME 80 | ``` 81 | 82 | 从这里,我们可以挑选我们想要在补丁版本中的提交: 83 | 84 | ```shell 85 | # get the commits ids we want to cherry-pick 86 | git log --oneline 87 | # cherry-pick the commits starting from the oldest one, without including merge commits 88 | git cherry-pick -x 89 | git cherry-pick -x 90 | ``` 91 | 92 | 这个新的分支将成为发布的基础,我们将在稍后进行迭代。 93 | 94 | ## 2. 更改 Git 中的版本号 95 | 96 | 97 | 在进行次要发布时,请确保使用新版本更新 pkg/version/version.go。 98 | 99 | ``` 100 | $ git diff pkg/version/version.go 101 | diff --git a/pkg/version/version.go b/pkg/version/version.go 102 | index 2109a0a..6f5a1a4 100644 103 | --- a/pkg/version/version.go 104 | +++ b/pkg/version/version.go 105 | @@ -26,7 +26,7 @@ var ( 106 | // Increment major number for new feature additions and behavioral changes. 107 | // Increment minor number for bug fixes and performance enhancements. 108 | // Increment patch number for critical fixes to existing releases. 109 | - Version = "v2.6" 110 | + Version = "v2.7" 111 | 112 | // BuildMetadata is extra build time data 113 | BuildMetadata = "unreleased" 114 | ``` 115 | 116 | ``` 117 | git add . 118 | git commit -m "bump version to $RELEASE_CANDIDATE_NAME" 119 | ``` 120 | 121 | ## 3. 提交并推送发布分支 122 | 123 | 为了让其他人开始测试,我们现在可以将发布分支推送到上游并开始测试过程. 124 | 125 | ```shell 126 | git push upstream $RELEASE_BRANCH_NAME 127 | ``` 128 | 129 | 确保在 [helm on CircleCI](https://circleci.com/gh/helm/helm) 上检查 helm 并确保在继续之前版本通过了 CI。 130 | 131 | 如果有其他人,请让其他人对该分支进行同行审查,然后再继续确保已完成所有正确的更改并且所有版本的提交已完成。 132 | 133 | ## 4. 创建候选发布版 134 | 135 | 现在发布分支已经准备就绪,现在是时候开始创建和迭代发布候选版本了。 136 | 137 | ```shell 138 | git tag --sign --annotate "${RELEASE_CANDIDATE_NAME}" --message "Helm release ${RELEASE_CANDIDATE_NAME}" 139 | git push upstream $RELEASE_CANDIDATE_NAME 140 | ``` 141 | 142 | CircleCI 将自动创建标记的发布镜像和客户端二进制文件以进行测试。 143 | 144 | 对于测试人员,在 CircleCI 完成构建工件之后开始测试的过程涉及以下步骤从 Google 云端存储中获取客户端的: 145 | 146 | linux/amd64,使用 / bin/bash: 147 | 148 | ```shell 149 | wget https://kubernetes-helm.storage.googleapis.com/helm-$RELEASE_CANDIDATE_NAME-linux-amd64.tar.gz 150 | ``` 151 | 152 | darwin/amd64, 使用 Terminal.app: 153 | 154 | ```shell 155 | wget https://kubernetes-helm.storage.googleapis.com/helm-$RELEASE_CANDIDATE_NAME-darwin-amd64.tar.gz 156 | ``` 157 | 158 | windows/amd64, 使用 PowerShell: 159 | 160 | ```shell 161 | PS C:\> Invoke-WebRequest -Uri "https://kubernetes-helm.storage.googleapis.com/helm-$RELEASE_CANDIDATE_NAME-windows-amd64.zip" -OutFile "helm-$ReleaseCandidateName-windows-amd64.zip" 162 | ``` 163 | 164 | 然后,解压缩并将二进制文件移动到 $PATH 上的某个位置,或将其移动到某处并将其添加到 $PATH(例如 / usr/ local/bin/helm 用于 linux macOS,C\Program Files\helm\helm.exe 用于 Windows)。 165 | 166 | ## 5. 迭代连续发布的候选版本 167 | 168 | 花几天时间明确投入时间和资源,尝试以各种可能的方式破坏 helm,记录与版本相关的任何发现。这个时间应该用于测试并找到版可能导致各种功能或升级环境出现问题的方式,而不是编码。在此期间,该版本将在代码冻结中,并且任何其他代码更改将被推送到下一个版本。 169 | 170 | 在此阶段,$RELEASE_BRANCH_NAME 分支将继续发展,因为将生成新的候选版本。新候选版本的频率取决于版本经理:使用最佳判断,考虑报告问题的严重性,测试人员的可用性以及版本截止日期。一般来说,最好让版本时间超过截止日期,而不是发布不可靠版本。 171 | 172 | Each time you'll want to produce a new release candidate, you will start by 173 | adding commits to the branch by cherry-picking from master: 174 | 175 | 每次你想要创建新的候选版本时,可以通过从 master 中挑选来的分支添加提交 commits: 176 | 177 | ```shell 178 | git cherry-pick -x 179 | ``` 180 | 181 | 还需要将步骤 2 和 3 中的版本号和 CHANGELOG 更新为单独的提交。 182 | 183 | 之后,标记它并通知用户新的候选版本: 184 | 185 | ```shell 186 | export RELEASE_CANDIDATE_NAME="$RELEASE_NAME-rc.2" 187 | git tag --sign --annotate "${RELEASE_CANDIDATE_NAME}" --message "Helm release ${RELEASE_CANDIDATE_NAME}" 188 | git push upstream $RELEASE_CANDIDATE_NAME 189 | ``` 190 | 191 | 从这里开始重复这个过程,不断测试,直到你对发布候选版本感到满意为止。 192 | 193 | ## 6. 完成版本 194 | 195 | 如果对候选版本的质量感到满意,那么可以继续前进并创建最终的东西。最后一次仔细检查以确保一切正常,然后最后推送版本标签。 196 | 197 | ```shell 198 | git checkout $RELEASE_BRANCH_NAME 199 | git tag --sign --annotate "${RELEASE_NAME}" --message "Helm release ${RELEASE_NAME}" 200 | git push upstream $RELEASE_NAME 201 | ``` 202 | 203 | ## 7. PGP 签署下载 204 | 205 | 虽然哈希提供了下载内容就是生成内容的签名,但签名包提供了包来自何处的可追溯性。 206 | 207 | 为此,请运行以下 make 命令: 208 | 209 | ```shell 210 | make clean 211 | make fetch-dist 212 | make sign 213 | ``` 214 | 215 | 这将为 CI 推送的每个文件生成 ascii 签名文件。 216 | 217 | 所有签名文件都需要上传到 GitHub 上的版本。 218 | 219 | 220 | ## 8. 编写版本说明 221 | 222 | 223 | 我们将根据版本周期中发生的提交自动生成更改日志,但如果版本说明是由 人 / 营销团队 / 狗 手写的,则通常对最终用户更有利。 224 | 225 | 如果要发布主要 / 次要版本,列出值得注意的面向用户的功能通常就足够了。对于修补程序版本,请执行相同操作,但请记下症状和受影响的人员。 226 | 227 | 次要版本的示例发行说明如下所示: 228 | 229 | ```markdown 230 | ## vX.Y.Z 231 | 232 | Helm vX.Y.Z is a feature release. This release, we focused on . Users are encouraged to upgrade for the best experience. 233 | 234 | The community keeps growing, and we'd love to see you there! 235 | 236 | - Join the discussion in [Kubernetes Slack](https://kubernetes.slack.com): 237 | - `#helm-users` for questions and just to hang out 238 | - `#helm-dev` for discussing PRs, code, and bugs 239 | - Hang out at the Public Developer Call: Thursday, 9:30 Pacific via [Zoom](https://zoom.us/j/696660622) 240 | - Test, debug, and contribute charts: [GitHub/helm/charts](https://github.com/helm/charts) 241 | 242 | ## Features and Changes 243 | 244 | - Major 245 | - features 246 | - list 247 | - here 248 | 249 | ## Installation and Upgrading 250 | 251 | Download Helm X.Y. The common platform binaries are here: 252 | 253 | - [MacOS amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-darwin-amd64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-darwin-amd64.tar.gz.sha256) / CHECKSUM_VAL) 254 | - [Linux amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-amd64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-amd64.tar.gz.sha256) / CHECKSUM_VAL) 255 | - [Linux arm](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm.tar.gz.sha256) / CHECKSUM_VAL) 256 | - [Linux arm64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm64.tar.gz.sha256) / CHECKSUM_VAL) 257 | - [Linux i386](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-386.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-386.tar.gz.sha256) / CHECKSUM_VAL) 258 | - [Linux ppc64le](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-ppc64le.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-ppc64le.tar.gz.sha256) / CHECKSUM_VAL) 259 | - [Linux s390x](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-s390x.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-s390x.tar.gz.sha256) / CHECKSUM_VAL) 260 | - [Windows amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-windows-amd64.zip) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-windows-amd64.zip.sha256) / CHECKSUM_VAL) 261 | 262 | Once you have the client installed, upgrade Tiller with `helm init --upgrade`. 263 | 264 | The [Quickstart Guide](https://docs.helm.sh/using_helm/#quickstart-guide) will get you going from there. For **upgrade instructions** or detailed installation notes, check the [install guide](https://docs.helm.sh/using_helm/#installing-helm). You can also use a [script to install](https://raw.githubusercontent.com/helm/helm/master/scripts/get) on any system with `bash`. 265 | 266 | ## What's Next 267 | 268 | - vX.Y.Z+1 will contain only bug fixes. 269 | - vX.Y+1.Z is the next feature release. This release will focus on ... 270 | 271 | ## Changelog 272 | 273 | ### Features 274 | - ref(*): kubernetes v1.11 support efadbd88035654b2951f3958167afed014c46bc6 (Adam Reese) 275 | - feat(helm): add $HELM_KEY_PASSPHRASE environment variable for signing helm charts (#4778) 1e26b5300b5166fabb90002535aacd2f9cc7d787 276 | 277 | ### Bug fixes 278 | - fix circle not building tags f4f932fabd197f7e6d608c8672b33a483b4b76fa (Matthew Fisher) 279 | 280 | ### Code cleanup 281 | - ref(kube): Gets rid of superfluous Sprintf call 3071a16f5eb3a2b646d9795617287cc26e53dba4 (Taylor Thomas) 282 | - chore(*): bump version to v2.7.0 08c1144f5eb3e3b636d9775617287cc26e53dba4 (Adam Reese) 283 | 284 | ### Documentation Changes 285 | - docs(release_checklist): fix changelog generation command (#4694) 8442851a5c566a01d9b4c69b368d64daa04f6a7f (Matthew Fisher) 286 | ``` 287 | 288 | 可以使用以下命令生成发行说明底部的更改日志: 289 | 290 | ```shell 291 | PREVIOUS_RELEASE=vX.Y.Z 292 | git log --no-merges --pretty=format:'- %s %H (%aN)' $PREVIOUS_RELEASE..$RELEASE_NAME 293 | ``` 294 | 295 | 生成更改日志后,需要对更改进行分类,如上例所示。 296 | 297 | 完成后,进入 GitHub 并使用此处写的注释编辑标记版本的发行说明。 298 | 299 | 请记住将上一步中生成的 ascii 签名附加到发行说明中。 300 | 301 | ## 9. 传福音 302 | 303 | 恭喜!你完成了。去抓一个 $DRINK_OF_CHOICE。这是你应得的。 304 | 305 | 在享受了一个不错的 $DRINK_OF_CHOICE 之后,请前往并宣布 Slack 和 Twitter 上新版本的喜讯。您还应该通知 helm 社区中的任何关键合作伙伴,例如 homebrew formula 维护者,孵化项目的所有者(例如 ChartMuseum)和任何其他感兴趣的团体。 306 | 307 | (可选)写一篇关于新版本的博客文章,并在那里展示一些新功能! 308 | --------------------------------------------------------------------------------