在本文中,我们将介绍Kubernetes平台上一个十分常用的部署工具——Helm,同时讨论如何在不同类型的工作流中使用Helm能最有效地为Kubernetes上的基础架构提供简单安全的部署。
Helm是Kubernetes软件生态中的一个软件包管理器,提供了一种“简单的方法来查找、共享和使用为 Kubernetes 而构建的软件”,因此它是常用的管理应用程序部署的工具之一。需要注意的是,Helm是一种打包格式,而非将代码部署到Kubernetes上的工作流程。
Helm是围绕chart构建的。从根本上来说,这些chart是一系列定义Kubernetes资源相关的YAML文件,是Helm用于打包Kubernetes资源的方式。chart可以让我们给Kubernetes构建模块。
一个基本的Helm chart
~/charts/app├── Chart.yaml├── README.md├── templates│ ├── NOTES.txt│ ├── _helpers.tpl│ ├── deployment.yaml│ ├── ingress.yaml│ ├── secret.yaml│ └── service.yaml└── values.yaml
一个最简单的Helm chart由一个chart元数据(Chart.yaml和values.yaml)和组成主要chart的template构成。主要的chart配置包括chart的命名和版本控制。values文件中提供安装chart时配置参数的默认值。Helm作为一个抽象层,简化了一组可以扩展为多个Kubernetes资源清单的值。
Deployment、Service和Ingress
大多数Helm chart的核心工作是发布联网的应用程序。有3种资源是部署应用程序的关键,同时还能够从外部集群与之进行通信:
Deployment发布你的代码
Service将流量从内部路由到你的代码
Ingress将外部流量路由到集群中的代码
现在让我们来看一个关于在Helm chart中service的例子以及template如何让我们重定义选项:
apiVersion: v1kind: Servicemetadata: name: {{ include "app.fullname" . }} labels:{{ include "app.labels" . | indent 4 }}spec: type: {{ .Values.service.type }}
这一简单的service资源示例显示了一些模板工具,可用于创建帮助程序以指定资源的全名。创建此服务的相应值如下所示:
service: type: ClusterIP port: 80
这是使用Helm抽象出底层资源的一个简单示例。
固定的工作发布流程
Helm旨在减少分散的资源管理以安装软件到你的集群中。在选择Helm发布代码时,这里有两套工作流程:
发布第三方代码到集群。此代码通常是语义版本,并以较慢的节奏发布,可能是每月或每年,具体取决于更新周期。
持续部署到你的Kubernetes集群。这类代码常常每日发布,或者更频繁。
第一种情况是Helm最初的设计目的,它要求chart实现语义版本并使chart升级相对简单。使用Helm最有效的方法是配合第三方程序一起使用,如Terraform。这组合可以在集群中实现稳定且一致的发布流程。这通常与你的基础架构的其余部分一起作为代码工作流程。
本文的主要目的是了解在持续部署过程中如何使用Helm。在开始时,有效地执行此操作可能看起来很简单,但要确保部署有效,还是需要注意一些事项。
使用Helm和CLI一起部署会相对简单,指定以下命令集以使用生产value文件中的值在默认命名空间中发布新的chart:
helm upgrade --install release-name \ --namespace default \ --values ./production.yml
当我运行这一命令时会发生什么呢?Helm有一个称为Tiller的服务端,Helm打开与Kubernetes集群的连接,并将你的Helm chart与作为参数传递的值一起写入此连接。服务端组件将这些值发送给模板,并将它们应用到Kubernetes集群中。
这些是Helm运行部署的基础知识。固定的部分和工作流程包括确定作为参数传递的值以及何时运行Helm升级命令。接下来,我们将讨论在企业内执行这些操作的正确方式。
避免在每个service都创建一个chart
使用Helm chart的一个好处是你可以跨组织或跨项目使用一个通用的配置也能够保持一致,还能将配置合并到一个chart中。虽然将单个chart放在要部署的每个repository中更简单,但是还是需要花费一些时间来构建一组核心chart,这些chart可用于整个组织的service。
这可以加快诸如标准化健康检查路径之类的速度,并保持跨资源配置的一致。此外,如果你想在Kubernetes资源成熟时采用更新的api版本,你可以从中心位置执行此操作。
但是目前Helm chart逐渐变得冗长,因此在实际操作中创建十分困难。你需要确保未定义的变量不会出错,同时标签是一致的,并且不会有任何Yaml缩进错误。然后最好将Helm chart交给那些使用Kubernetes方面经验丰富的人进行创建,开发人员可以将其作为模板。
分离生产和staging配置值
你推送到chart中的配置值能在环境之间分离开。构建简单的可扩展的chart可以覆盖每个环境。
例如,一个优秀的工作流程为每个环境提供不同的value文件,并且文件之间有特定区别:
~/myapp└── config ├── production.yml └── staging.yml
根据部署环境使用每个value文件,这与使用if语句或其他逻辑将配置bake到Helm chart相反。Helm可以抽象出Kubernetes资源,而value文件是传递环境和应用程序特定信息的方式。
请使用“require”语句和linting工具以确保在部署时没有未定义的值。如果以下变量未定义,可能会导致相对严重的配置问题:
host: {{ .Values.hostPrefix }}.example.com
Secret管理
Kubernetes secret是管理应用程序secret最简单的方式之一。Helm不会尝试以任何方式管理secret而你可能会陷入配置复杂工作流程的困境。这里有一个secret管理的简单的建议:
使用你的CI/CD在它们的dashboard中存储secret
传递secret value到在deployment上的chart value
当这些secret value发生变化时,使用校验来roll out 这些pod
我们想在集群中发布一个新的secret,以便在我们的deployment流水线中可审计和可见,同时我们希望开发人员也可以访问它。
这里推荐一个十分好用的secret管理的工具——vault,它深度集成了Kubernetes以提供更进一步的安全性。它可能需要花费更长的时间设置,但它提供了一些企业可以使用的高级功能。
编辑value
确保在使用Helm CLI时,只有Helm可以更改Kubernetes资源清单中的值。例如,不要在Helm的外部修改deployment的副本并且使用Helm来更改value。如果你之前使用过Kubernetes,你可能使用过kubectl apply这个工具。这是应用基础设施到集群中最简单的方式之一。但Helm不与kubectl使用相同的技术。这意味着如果你在Helm外部编辑基础设施,下次运行Helm命令时可能会导致问题。
Helm chart repository
Helm chart repository本质上是一个web服务器,提供chart资源。你可以github.com/helm/charts上查看官方提供的chart资源。chart repository最初是为了语义版本chart而设计的。因此,chart repository无法很好地处理并发更新。
Helm chart 应该是语义版本的模块,它们代表底层基础架构以部署应用程序。将它们视为一个用于抽象Kubernetes复杂性的库。将chart存储在整个组织可访问的repository中,并允许开发人员使用这些chart来在企业中进行部署。
在整个组织中分发chart的简单方式是使用S3甚至GitHub版本作为chart的存储。还有一个简单的模式是拥有一个共同的myorg / charts repository,其中包含您的团队已经策划和构建的所有chart,都可以安装到Kubernetes中。
保护你的Tiller
如果你的Kubernetes集群有严格的访问控制,你可能会被Tiller(Helm的服务器端组件)作为Kubernetes集群中的超级用户运行的问题难住。对于此,有一些解决方法但需要使用一些更复杂的配置。而对于大多数团队而言,默认的配置是连接到Helm时具有集群的管理员访问权限,因此太过复杂的配置不太适合。
一个常见的修复这一问题的方法是在不同的命名空间中创建一个不同的Tiller实例。如果你的Kubernetes集群规模很大,这可能是一种将特定团队细分为只能访问单个Tiller的方法。
总 结
新的Kubernetes deployment面临的最大挑战之一是没有花时间阅读最佳实践和意见以在第一次时正确设置deployment流水线。Helm deployment有许多问题,你需要找到正确的设置,一旦正确完成,即可获得灵活性等优势,可以有效地连接你的deployment。