Helm全链路精通:从入门到实战,Kubernetes应用管理新高度
#作者:曹付江
Helm全链路精通:从入门到实战,Kubernetes应用管理新高度
- Helm入门介绍
- Helm 相关组件和版本介绍
- Helm 原理
- 创建 或 删除 release
- 更新release
- Helm 常用命令
- 创建一个chart范例
- 检查chart语法
- 使用默认chart部署到k8s
- 查看当前的部署列表
- 查询一个特定的 Release 的状态
- 打包chart
- 使用包去做release部署
- 升级当前release
- 回滚当前release
- 删除该release
- Helm来预览、安装、升级、回滚一个 Kubernetes 应用
- Helm 自定义模板
- helm和kustomize对比
- kustomize的用法
- 1)使用 kustomize 提供的简单的配置项来对 Kubernetes 资源进行修改。
- 2)手动修改资源
- 3)组织应用
Helm入门介绍
Helm是一个k8s应用包管理工具,负责云原生应用的安装部署和生命周期管理,是查找、分享和使用软件构建 Kubernetes 的最优方式。
官网地址:https://helm.sh/。
在没使用 helm 之前,向 kubernetes 部署应用,我们要依次部署 deployment、svc 等,步骤较为繁琐。况且随着很多项目微服务化,复杂的应用在容器中部署以及管理显得较为复杂,helm 通过打包的方式,支持发布的版本管理和控制,很大程度上简化了 Kubernetes 应用的部署和管理。
Helm本质就是让 K8s的应用管理(Deployment,Service等 ) 可配置,且能动态生成。通过动态生成 K8s资源清单文件(deployment.yaml,service.yaml)。然后调用 Kubectl自动执行 K8s 资源部署。Helm 是官方提供的类似于YUM 的包管理器,是部署环境的流程封装。Helm 有两个重要的概念:chart 和release。
Helm 相关组件和版本介绍
Helm 包含两个组件,分别是 helm 客户端 和 Tiller 服务器:
helm : 是一个命令行工具,用于本地开发及管理chart,chart仓库管理等
Tiller: 是 Helm 的服务端。Tiller 负责接收 Helm 的请求,与 k8s 的 apiserver 交互,根据chart来生成一个 release 并管理 release
chart: Helm的打包格式叫做chart,所谓chart就是一系列文件, 它描述了一组相关的 k8s 集群资源。chart 的基本结构:Chart中的文件安装特定的目录结构组织, 最简单的chart 目录如下所示:
release: 使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release
当前社区从Helm v2演进到Helm v3,主要有以下变化:
1) 移除tiller
Helm v3 使用更加简单和灵活的架构,移除了 tiller,直接通过kubeconfig连接apiserver,简化安全模块,降低了用户的使用壁垒。
2) 改进了升级策略,采用三路策略合并补丁
Helm v2 使用双路策略合并补丁。在升级过程中,会对比最近一次发布的chart manifest和本次发布的chart manifest的差异,来决定哪些更改会应用到Kubernetes资源中。如果更改是集群外带的(比如通过kubectl edit),则修改不会被Helm识别和考虑。结果就是资源不会回滚到之前的状态。
Helm v3 使用三路策略来合并补丁,Helm在生成一个补丁时,会考虑之前原来的manifest的活动状态。因此,Helm在使用原来的chart manifest生成新补丁时会考虑当前活动状态,并将其与之前原来的 manifest 进行比对,并再比对新的 manifest 是否有改动,并进行自动补全,以此来生成最终的更新补丁。
3) 默认存储驱动程序更改为secrets
Helm v2 默认情况下使用 ConfigMaps 存储发行信息,而在 Helm v3 中默认使用 Secrets。
4) 发布名称限制在namespace范围内
Helm v2 只使用tiller 的namespace作为release信息的存储,这样全集群的release名字都不能重复。Helm v3只会在release安装的所在namespace记录对应的信息,这样release名称可在不同命名空间重用。应用和release命名空间一致。
5) 校验方式改变
Helm v3 对模板格式的校验更加严格,如Helm v3 将chart.yaml的apiVersion从v1切换到v2,针对Helm v2的chart.yaml,强要求指定apiVersion为v1。可安装Helm v3客户端后,通过执行helm lint命令校验模板格式是否符合v3规范。
适配方案:根据Helm官方文档 https://helm.sh/docs/topics/charts/适配Helm v3模板,apiVersion字段必填。
6) 废弃crd-install
Helm v3删除了crd-install hook,并用chart中的crds目录替换。需要注意的是,crds目录中的资源只有在release安装时会部署,升级时不会更新,删除时不会卸载crds目录中的资源。若crd已存在,则重复安装不会报错。适配方案:根据Helm官方文档 https://helm.sh/docs/chart_best_practices/custom_resource_definitions/, 当前可使用crds目录或者将crd定义单独放入chart。考虑到目前不支持使用Helm升级或删除CRD,推荐分隔chart,将CRD定义放入chart中,然后将所有使用该CRD的资源放到另一个 chart中进行管理。
7) 未通过helm创建的资源不强制update,releaes默认不强制升级
Helm v3强制升级逻辑变化,不再是升级失败后走删除重建,而是直接走put更新逻辑。因此当前CCE release升级默认使用非强制更新逻辑,无法通过Patch更新的资源将导致release升级失败。若环境存在同名资源且无Helm V3的归属标记app.kubernetes.io/managed-by: Helm,则会提示资源冲突。
适配方案:删除相关资源,并通过Helm创建。
8) Release history数量限制更新
为避免release 历史版本无限增加,当前release升级默认只保留最近10个历史版本。
Helm 原理
创建 或 删除 release
- helm 客户端从指定的目录或本地tar文件或远程repo仓库解析出chart的结构信息
- helm 客户端指定的 chart 结构和 values 信息通过 gRPC 传递给 Tiller
- Tiller 服务端根据 chart 和 values 生成一个 release
- Tiller 将install release请求直接传递给 kube-apiserver
更新release
- helm 客户端将需要更新的 chart 的 release 名称 chart 结构和 value 信息传给 Tiller
- Tiller 将收到的信息生成新的 release,并同时更新这个 release 的 history
- Tiller 将新的 release 传递给 kube-apiserver 进行更新
Helm 常用命令
创建一个chart范例
helm create HELM-NAME
检查chart语法
helm lint ./HELM-NAME
使用默认chart部署到k8s
helm install --name RELEASE-NAME ./HELM-NAME --set service.type=NodePort
查看当前的部署列表
helm ls
查询一个特定的 Release 的状态
helm status RELEASE-NAME
打包chart
helm package ./HELM-NAME –debug
使用包去做release部署
helm install --name RELEASE-NAME HELM-NAME-0.1.0.tgz --set service.type=NodePort
升级当前release
helm upgrade RELEASE-NAME ./HELM-NAME
回滚当前release
helm rollback RELEASE-NAME 3(版本号)
删除该release
helm delete RELEASE-NAME
helm del --purge RELEASE-NAME
Helm来预览、安装、升级、回滚一个 Kubernetes 应用
预览安装:使用模板动态生成K8s资源清单,非常需要能提前预览生成的结果,使用 --dry-run 选项来打印出生成的清单文件内容,而不执行部署:
helm install . --dry-run
安装:
升级:
回滚:
删除:(完全删除)
删除后回滚:版本号增加
Helm 自定义模板
创建自描述文件 Chart.yaml , 这个文件必须有 name 和 version 定义:
vim Chart.yaml
name: hello-world
version: 1.0
创建模板文件, 用于生成 Kubernetes 资源清单,模板文件名必须为 templates:
mkdir templates
vim templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: helm-nginx
spec:selector:matchLabels:app: helm-nginxreplicas: 3template:metadata:labels:app: helm-nginxspec:containers:- name: helm-nginximage: docker.io/nginximagePullPolicy: IfNotPresentports:- containerPort: 80
vim templates/service.yaml
apiVersion: v1
kind: Service
metadata:name: helm-nginx-svc
spec:type: NodePortports:- port: 80targetPort: 80protocol: TCPselector:app: helm-nginx
使用命令 helm install RELATIVE_PATH_TO_CHART 创建一次Release
helm install .
查看下我们创建以后的资源:
访问测试:
通过 values.yaml 配置 helm 应用:
vim values.yaml
image:
repository: docker.io/nginx
tag: latest
pullPolicy: IfNotPresent
vim templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: helm-nginx-1
spec:selector:matchLabels:app: helm-nginx-1replicas: 3template:metadata:labels:app: helm-nginx-1spec:containers:- name: helm-nginximage: {{ .Values.image.repository }}:{{ .Values.image.tag }}imagePullPolicy: IfNotPresentports:- containerPort: 80
vim templates/service.yaml
apiVersion: v1
kind: Service
metadata:name: helm-nginx-svc-1
spec:type: NodePortports:- port: 80targetPort: 80protocol: TCPselector:app: helm-nginx-1
helm和kustomize对比
Kubernetes 上的包管理工具 Helm。Helm Chart 以模板的形式来生成 Kubernetes 上的资源定义,允许对应用的安装进行灵活的定制。Helm 也提供了对安装到 Kubernetes 上的 release 的管理。不过,Helm Chart 的开发相对复杂,需要了解模板的语法。
kustomize 则提供了另外一种安装应用的方案,kustomize 的名称来源于英文单词 customize ,也就是自定义,只不过把 c 换成了表示 Kubernetes 的 k。kustomize 是一个通用的工具,它的作用是对描述 Kubernetes 资源的 YAML 文件进行定制,产生新的 YAML 文件,并保持原始的 YAML 文件不变。从这个意义上来说,你可以把 kustomize 看成是 Kubernetes YAML 文件的转换工具,可以与 XML 和 XSLT 进行类比。
kustomize 的一个重要特征是不使用模板,而是直接工作在原始的 YAML 文件上。这一点与 Helm 是不同的。不使用模板好处在于简单易懂,不需要掌握复杂的模板语法。kustomize 的另外一个优势是集成在 kubectl 中,这就意味着不需要安装额外的工具就可以进行定制。需要注意的是,由于实现上的原因,kubectl 自带的 kustomize 的版本比较低,目前仍然需要安装单独的 kustomize 工具。这个问题要到 1.20 版本才会解决。kubectl来管理kustomize文件,需使用kubectl的v1.21及其后续版本,kustomize 使用 kustomization.yaml 文件来描述对 YAML 文件的修改。
kubectl create deploy nginx --image nginx --dry-run=client -o yaml > deployment.yaml
问题:
① 只要yaml中有tab键就会造成kubectl kustomize .预览yaml的时候有\n \等特殊字符,常见在创建configmap中出现,空行中携带有tab或者冒号后面有空格
# tab换成4个空格
sed -i 's/\t/ /g' test.conf
kustomize的用法
1)使用 kustomize 提供的简单的配置项来对 Kubernetes 资源进行修改。
在这个实例中,deployment.yaml 是一个 nginx 部署的资源。在 kustomization.yaml 文件中,resources 表示所包含的资源文件,namePrefix 表示为所有资源名称添加的前缀,commonAnnotations 表示为所有资源添加的注解,commonLabels 表示为所有资源添加的标签。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:- deployment.yaml
namePrefix: dev-
commonAnnotations:updatedBy: kustomize
commonLabels:owner: test-companyserverVersion: v1
使用 kustomize build 可以输出修改之后的 YAML 文件的内容。
$ kustomize build nginx
从输出的内容可以看到,生成的 Deployment 添加了相应的名称前缀、注解和标签。
输出的内容可以直接传递给 kubectl apply 命令,在 Kubernetes 上应用。
$ kustomize build nginx | kubectl apply -f -
也可以直接使用 kubectl 来应用。
$ kubectl apply -k nginx
2)手动修改资源
第二个实例是生成 ConfigMap 和对资源进行手动修改。给出的 deployment.yaml 文件部署一个 busybox 容器。在 kustomization.yaml 文件中,configMapGenerator 用来生成 ConfigMap,而 ConfigMap 中的内容可以是通过 files 声明的文件,或是通过 literals 声明的名值对。而 options 中的disableNameSuffixHash 表示不在名称之后添加Hash值作为后缀。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:- deployment.yamlpatches:
- path: patch.yaml configMapGenerator:
- name: app-propertiesfiles:- application.propertiesliterals:- EXTRA_ARG=demooptions:disableNameSuffixHash: true
在 patches 中声明了对资源 YAML 文件的修改。在 patch.yaml 文件中,只需要声明 Deployment 资源中需要修改的部分即可,最终生成的 YAML 文件会把原始的 deployment.yaml 文件和 patch.yaml 文件做合并。
3)组织应用
最后一个例子展示了使用 kustomize 来组织应用的安装。在 base 目录中,包含了应用相关的资源,以及基本的定制。在 overlays 目录中,development 和 production 分别表示开发和生产环境,包含环境相关的定制。
app
├── base
│ ├── deployment.yaml
│ ├── kustomization.yaml
│ └── service.yaml
└── overlays├── development│ ├── kustomization.yaml│ └── resource_config.yaml└── production├── kustomization.yaml└── resource_config.yaml
在每个环境中有各自的 kustomization.yaml 文件来声明所做的修改。这里的 resources 指向 base 目录。在 patches 中声明的 resource_config.yaml 用来修改容器的资源需求。
resources:- ../../basenamePrefix: dev-
patches:
- path: resource_config.yaml
多个 kustomization.yaml 文件所声明的修改,可以叠加在一起,从而产生最终的资源文件。