Helm 从入门到实践 | 从 0 开始制作一个 Helm Charts

本文涉及的产品
云原生网关 MSE Higress,422元/月
应用实时监控服务-应用监控,每月50GB免费额度
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 本周 Helm 官方发布博客,指导用户从 v2 迁移到 v3,这标志 Helm 逐渐走向成熟。早在今年 6 月,阿里云就正式发布了国内首个 Helm Hub 中国镜像站:开放云原生应用中心 - Cloud Native App Hub。

05


本周 Helm 官方发布博客,指导用户从 v2 迁移到 v3,这标志 Helm 逐渐走向成熟。早在今年 6 月,阿里云就正式发布了国内首个 Helm Hub 中国镜像站:开放云原生应用中心 - Cloud Native App Hub


历经三个月的成长和沉淀, Helm Hub 中国镜像站目前已经实时全量同步了 Helm Hub 的所有内容,同时还精选同步了比如 GitLab 等多个热门的第三方 Charts Repo,截止今日已总计上线了 859 个 Charts,并且还在不断增加中。



06


为了鼓励和普及 Helm Charts 在国内的使用,帮助国内开发者通过云原生的方式打包和分发自己的应用,从而更好的借助云原生的浪潮,让自己的软件在云时代发挥出最大的能量,阿里云举办了首届云原生应用开发大赛,历经 42 天、最终评选出 33 个 Helm Charts 获得最受欢迎奖,1 个 Helm Charts 获得评委选择奖。所有提交的 Chart 都会经过评委严格的测试和评估。

评委选择奖


 获奖作品:_etcd-manage_
 作者 GitHub ID:_shiguanghuxian_


etcd-manage 是一个用 Go 编写的 etcd 管理工具,具有友好的界面(类似阿里云后台),管理 key 就像管理本地文件一样方便。支持简单权限管理区分只读和读写权限。



评委点评

07

etcd-manage 是一个简洁的 etcd 管理工具,提供了很不错的可视化界面,原创性好,实用性强,贴近社区云原生理念。


另一方面可以看到作者在用户体验上做的也很到位,对于依赖的数据库提供了自动安装和导入外部数据库两种选项,文档也写的比较全面。

最受欢迎奖

经过几位评委从技术角度和实用性角度综合考量,最终有 33 个作品收获“最受欢迎奖”。

08


数据截止到 9 月 2 日 10:00

参赛选手的话


 获奖作品:_redis-operator_
 作者 GitHub ID:SataQiu


云原生是未来!很高兴参加本次云原生应用大赛,感谢评委的耐心指导,让我对云原生有了更为深入的理解,希望以后还能举办类似的比赛和活动,我很乐意参加!




 获奖作品:_etcd-manage_
 作者 GitHub ID:_shiguanghuxian_


语言表达能力有限,希望 App Hub 中国站能为更多公司和开发者提供便捷的应用发布和服务中间件的部署能力,随着 K8s 这类服务部署和开发模式的流行 Helm 的应用前景肯定会很美好。

这次参赛加班加点搞定自己应用 2.0 的首版,目标是做一个大家的实用工具,从不知道 Helm 到学习打包应用,从中学到了很多,未来还会开发一些应用,另外希望能借助 Helm 开发一些便捷应用部署的工具。


 获奖作品:_nvidia-gpu-exporter_
 作者 GitHub ID:wikiios


App Hub 需要更多实用 Helm,云原生应用是不可阻挡的趋势!


 获奖作品:_hugo_
 作者 GitHub ID:_sunny0826_

参加本次云原生应用大赛,不仅使得平时掌握的 Helm 技巧得以施展,同时在与其他参赛者的交流中获得了很多提升,找到了很多有意思的 charts,受益良多。希望App Hub 不断地发展,在不久的将来在 K8s 集群上部署云原生应用能像在 CentOS 上使用 yum 安装一样方便!


……

如何制作自己的 Helm Charts


我们平时在日常生活中会经常在不同的平台上与各种各样的应用打交道,比如从苹果的 App Store 里下载的淘宝、高德、支付宝等应用,或者是在 PC 端安装的Word、Photoshop、Steam。这些各类平台上的应用程序,对用户而言,大多只需要点击安装就可使用。


然而,在云(Kubernetes)上,部署一个应用往往却不是那么简单。如果想要部署一个应用程序到云上,首先要准备好它所需要的环境,打包成 Docker 镜像。进而把镜像放在部署文件(Deployment)中、配置服务(Service)、应用所需的账户(ServiceAccount)及权限(Role)、命名空间(Namespace)、密钥信息(Secret)、可持久化存储(PersistentVolumes)等资源。也就是编写一系列互相相关的 YAML 配置文件,将它们部署在 Kubernetes 集群上。


但是即便应用的开发者可以把这些Docker镜像存放在公共仓库中,并且将部署所需的 YAML 资源文件提供给用户,用户仍然需要自己去寻找这些资源文件,并把它们一一部署。倘若用户希望修改开发者提供的默认资源,比如使用更多的副本(Replicas)或是修改服务端口(Port),他还需要自己去查应该在这些资源文件的哪些地方修改,更不用提版本变更与维护会给开发者和用户造成多少麻烦了。可见最原始的 Kubernetes 应用形态并不便利。

Helm 与 Helm Chart


在这样的大环境下,有一系列基于 Kubernetes 的应用包管理工具横空出世。而我们今天的主角 Helm,就是这其中最受欢迎的选择之一。


09




开发者按照 Helm Chart 的格式,将应用所需的资源文件包装起来,通过模版化(Templating)的方式将一些可变字段(比如我们之前提到的暴露哪个端口,使用多少副本)暴露给用户,最后将封装好的应用包,也就是 Helm Chart,集中存放在统一的仓库中供用户浏览下载。


站在用户角度,用户只需要一行简单的命令就可以完成应用的安装、卸载与升级。对于安装之后状态,也可以通过 helm list 或者是原生的 kubectl 进行查询。

$ helm install redis stable/redis
$ kubectl get pods
NAME                  READY       STATUS     RESTARTS           AGE
redis-master-0        1/1         Running    0                  63s
redis-slave-0-0       1/1         Running    0                  63s
redis-slave-1-0       1/1         Running    0                  13s
$ helm delete redis

创作 Helm Chart


那么站在开发者的角度上,我们应该如何去创作一个 Helm 应用包呢?

准备工作


首先我们需要一个准备部署的镜像。这个镜像可以是一个 Java 程序、一个 Python 脚本、甚至是一个空的 linux 镜像跑几条命令。


10




这里我们使用一个简单的基于 golang 的。该服务通过读取环境变量 USERNAME 获得用户自己定义的名称,然后监听 80 端口。对于任意 HTTP 请求,返回 Hello ${USERNAME}。比如如果设置 USERNAME=world(默认场景),该服务会返回 Hello world


然后我们使用 对镜像进行打包。先对 Golang 代码进行编译,然后将编译后的程序放在基于 alpine 的镜像中,以缩小镜像体积。


11



在 Docker 构建好镜像之后,我们把镜像上传到仓库中,比如 Docker Hub 或是阿里云容器镜像仓库。准备工作做好之后,我们就可以开始创作 Helm Chart 了。

开始创作


运行 helm create my-hello-world,会得到一个 helm 自动生成的空 chart。这个 chart 里的名称是my-hello-world需要注意的是,Chart 里面的 my-hello-world 名称需要和生成的 Chart 文件夹名称一致。如果修改 my-hello-world,则需要做一致的修改。 现在,我们看到 Chart 的文件夹目录如下:

my-hello-world
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── ingress.yaml
│   ├── NOTES.txt
│   └── service.yaml
└── values.yaml


在根目录下的 Chart.yaml 文件内,声明了当前 Chart 的名称、版本等基本信息,这些信息会在该 Chart 被放入仓库后,供用户浏览检索。比如我们可以把 Chart 的 Description 改成 "My first hello world helm chart"。在 Chart.yaml 里有两个跟版本相关的字段,其中 version 指明的是 Chart 的版本,也就是我们应用包的版本;而 appVersion 指明的是内部实际使用的应用版本。


在 templates 文件夹内存放了各类应用部署所需要使用的 YAML 文件,比如 Deployment 和 Service。在我们当前的应用内,我们只需要一个 deployment,而有的应用可能包含不同组件,需要多个 deployments,那么我们就可以在 templates 文件夹下放置 deploymentA、deploymentB 等。同样的,如果我们需要配置 serviceaccount、secret、volumes 等内容,也可以在里面添加相应的配置文件。

apiVersion: apps/v1beta2
kind: Deployment
metadata:
 name: {{ template "my-hello-world.fullname" . }}
 labels:
{{ include "my-hello-world.labels" . | indent 4 }}
spec:
 replicas: {{ .Values.replicaCount }}
 selector:
   matchLabels:
     app.kubernetes.io/name: {{ include "my-hello-world.name" . }}
     app.kubernetes.io/instance: {{ .Release.Name }}
 template:
   metadata:
     labels:
       app.kubernetes.io/name: {{ include "my-hello-world.name" . }}
       app.kubernetes.io/instance: {{ .Release.Name }}
   spec:
     containers:
       - name: {{ .Chart.Name }}
         image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}"
         imagePullPolicy: {{ .Values.image.pullPolicy }}
         env:
           - name: USERNAME
             value: {{ .Values.Username }}
......


Helm Chart 对于应用的打包,不仅仅是将 Deployment 和 Service 以及其它资源整合在一起。我们看到 deployment.yaml 和 service.yaml 文件被放在 templates/ 文件夹下,相较于原生的 Kubernetes 配置,多了很多渲染所用的可注入字段。比如在 deployment.yaml 的spec.replicas 中,使用的是 .Values.replicaCount 而不是 Kubernetes 本身的静态数值。这个用来控制应用在 Kubernetes 上应该有多少运行副本的字段,在不同的应用部署环境下可以有不同的数值,而这个数值便是由注入的 Values 提供。

replicaCount: 1
image:
 repository: somefive/hello-world
 pullPolicy: IfNotPresent
nameOverride: ""
fullnameOverride: ""
service:
 type: ClusterIP
 port: 80
......
Username: AppHub


在根目录下我们看到有一个 values.yaml 文件,这个文件提供了应用在安装时的默认参数。在默认的 Values 中,我们看到 replicaCount: 1 说明该应用在默认部署的状态下只有一个副本。


为了使用我们要部署应用的镜像,我们看到 deployment.yaml 里在 spec.template.spec.containers 里,image 和 imagePullPolicy 都使用了 Values 中的值。


其中 image 字段由 .Values.image.repository 和 .Chart.AppVersion 组成。看到这里,同学们应该就知道我们需要变更的字段了:一个是位于 values.yaml 内的 image.repository,另一个是位于 Chart.yaml 里的 AppVersion。我们将它们与我们需要部署应用的 docker 镜像匹配起来。这里我们把 values.yaml 里的 image.repository 置成 somefive/hello-world,把 Chart.yaml 里的 AppVersion设置成 1.0.0 即可。


类似的,我们可以查看 service.yaml 内我们要部署的服务,其中的主要配置也在 values.yaml 中。默认生成的服务将 80 端口暴露在 Kubernetes 集群内部。我们暂时不需要对这一部分进行修改。


由于部署的 hello-world 服务会从环境变量中读取 USERNAME 环境变量,我们将这个配置加入 deployment.yaml。

- name: {{ .Chart.Name }}
  image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}"
  imagePullPolicy: {{ .Values.image.pullPolicy }}
  env:
  - name: USERNAME
    value: {{ .Values.Username }}


现在我们的 deployment.yaml 模版会从 values.yaml 中加载 Username 字段,因此相应的,我们也在 values.yaml 中添加 Username: AppHub。现在,我们的应用就会从 values.yaml 中读取 Username 把它放入镜像的环境变量中启动了。

校验打包


在准备好我们的应用后,我们可以使用 Helm lint 来粗略地检查一下制作的 Chart 有没有什么语法上的错误。如果没有问题的话,我们就可以使用 helm package 命令对我们的 Chart 文件夹进行打包,打包后我们可以得到一个 my-hello-world-0.1.0.tgz 的应用包。这个便是我们完成的应用了。

$ helm lint --strict my-hello-world
1 chart(s) linted, 0 chart(s) failed
    [INFO] Chart.yaml: icon is recommended
$ helm package my-hello-world


我们可以使用 helm install 命令尝试安装一下刚刚做好的应用包,然后用 kubectl 查看一下运行 pod 的状态。我们可以通过 port-forward 命令将该 pod 的端口映射到本地端口上,这个时候我们就可以通过访问 localhost 来访问部署好的应用了。

$ helm install my-hello-world-chart-test my-hello-world-0.1.0.tgz
$ kubectl get pods
NAME                                          READY    STATUS     RESTARTS    AGE
my-hello-world-chart-test-65d6c7b4b6-ptk4x-0  1/1      Running    0           4m3s
$ kubectl port-forward my-hello-world-chart-test-65d6c7b4b6-ptk4x 8080:80
$ curl localhost:8080
Hello AppHub

参数重载


有的同学可能会有疑惑,虽然我们应用开发者把可配置的信息暴露在的 values.yaml 中,用户使用应用时想要修改该怎么办呢?答案很简单,用户只需要在 install 时使用 set 参数设置想要覆盖的参数即可。


应用开发者在 Chart 的 values 配置中只是提供了默认的安装参数,用户也可以在安装时指定自己的配置。类似的,如果用户可以用 upgrade 命令替代 install,实现在原有部署好的应用的基础上变更配置。

$ helm install my-app my-hello-world-0.1.0.tgz --set Username="Cloud Native"
$ helm install my-super-app my-hello-world-0.1.0.tgz -f my-values.yaml
$ helm upgrade my-super-app my-hello-world-0.1.0.tgz -f my-new-values.yaml

修改提示信息


我们注意到在安装 Chart 指令运行后,屏幕的输出会出现:

NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods -l "app=my-hello-world,release=my-hello-world-chart-test2" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80


这里的注释是由 Chart 中的 templates/NOTES.txt 提供的。我们注意到原始的 NOTES 中,所写的 "app={{ template "my-hello-world.name" . }},release={{ .Release.Name }}" 和我们的 deployment.yaml 中所写的配置不太一样。我们可以把它改成"app.kubernetes.io/name={{ template "my-hello-world.name" . }},app.kubernetes.io/instance={{ .Release.Name }}",将 values.yaml 中的version 更新成 0.1.1。然后重新打包 Chart(运行 helm package)。得到新的 my-hello-world-0.1.1.tgz 之后,升级原有 Chart(运行 helm upgrade my-hello-world-chart-test2 my-hello-world-0.1.1.tgz --set Username="New Chart"),就能看到更新过后的 NOTES 了。

NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods -l "app.kubernetes.io/name=my-hello-world,app.kubernetes.io/instance=my-hello-world-chart-test2" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80

应用分享


12




那么制作完成的应用如何和其他人分享呢?Helm 官方推出的 ChartMuseum 提供了 Chart 仓库的构建方法,使用它可以创建自己的 Chart 仓库。然而自行维护一个仓库本身成本不小,而且对于用户而言如果每一个开发者都是自己的仓库,他就需要将所需应用对应的仓库都加入自己的检索列表中,很不利于应用的传播与分享。

13


开放云原生应用中心 Cloud Native App Hub,同步了各类应用,同时还提供了开发者上传应用的渠道。


在我们的开放云原生应用中心中,应用来自两个渠道。一方面,我们定期从一些国外的知名 Helm 仓库同步 Chart 资源,在同步的过程中,会对 Chart 内部使用的一部分 Docker 镜像进行同步替换(例如 gcr.io 或者 quay.io 的镜像),方便国内用户访问使用;另一方面,我们和 Helm 官方库一样在 上接受开发者通过 Pull Request 的形式提交自己的应用。提交成功的应用会在短期内同步至云原生应用中心,和其他官方应用展示在一起供其他用户使用。


希望大家共同参与,让开放云原生应用中心更加丰富,惠及更多人!



14

作者简介
殷达,清华大学与卡内基梅隆大学计算机专业在读研究生,于阿里云容器平台部实习,主要参与ACK容器服务多云技术及云原生应用开发。



扫描下方二维码添加小助手,与 8000 位云原生爱好者讨论技术趋势,实战进阶!


进群暗号:公司-岗位-城市

15

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
Docker 容器
【registry】docker 私有仓库实现https 访问
【registry】docker 私有仓库实现https 访问
1779 2
【registry】docker 私有仓库实现https 访问
|
Ubuntu Linux 网络安全
Linux:使用ntpdate命令同步更新系统时间
Linux:使用ntpdate命令同步更新系统时间
4221 0
|
缓存 Kubernetes API
Kubernetes Operator 开发教程
# 1. 概述 我们将 CRD, Controller, Webhook 三者合起来叫 Operator。一个 Operator 工程一般必须包含 CRD 和 Controller,Admission 是可选的。如果说 Kubernetes 是 "操作系统" 的话,Operator 是 Kubernetes 的第一层应用,它部署在 Kubernetes 里,使用 Kubernetes "扩展资源
10920 1
Kubernetes Operator 开发教程
|
缓存 运维 Kubernetes
NVIDIA GPU Operator分析一:NVIDIA驱动安装
背景我们知道,如果在Kubernetes中支持GPU设备调度,需要做如下的工作:节点上安装nvidia驱动节点上安装nvidia-docker集群部署gpu device plugin,用于为调度到该节点的pod分配GPU设备。除此之外,如果你需要监控集群GPU资源使用情况,你可能还需要安装DCCM exporter结合Prometheus输出GPU资源监控信息。要安装和管理这么多的组件,对于运维
5459 0
NVIDIA GPU Operator分析一:NVIDIA驱动安装
|
Kubernetes 搜索推荐 前端开发
containerd 镜像构建工具 -- nerdctl 和 buildkit
containerd 镜像构建工具 -- nerdctl 和 buildkit
7942 0
|
Linux
阿里云官方yum源
阿里云官方yum源
73476 0
|
Kubernetes 应用服务中间件 nginx
k8s学习--k8s集群使用容器镜像仓库Harbor
本文介绍了在CentOS 7.9环境下部署Harbor容器镜像仓库,并将其集成到Kubernetes集群的过程。环境中包含一台Master节点和两台Node节点,均已部署好K8s集群。首先详细讲述了在Harbor节点上安装Docker和docker-compose,接着通过下载Harbor离线安装包并配置相关参数完成Harbor的部署。随后介绍了如何通过secret和serviceaccount两种方式让Kubernetes集群使用Harbor作为镜像仓库,包括创建secret、配置节点、上传镜像以及创建Pod等步骤。最后验证了Pod能否成功从Harbor拉取镜像运行。
1645 0
|
监控 Linux 数据处理
Linux中的nsenter命令:深入容器内部,实现无缝交互
`nsenter`是Linux工具,用于进入容器的命名空间,实现与容器内环境的交互。它基于Linux内核的命名空间功能,支持网络、PID等多类型隔离。`nsenter`允许在不停止容器的情况下调试和操作,如 `-t` 指定PID进入命名空间,`-n` 进入网络命名空间。示例包括使用`nsenter`查看容器进程或网络配置。使用时注意目标进程状态,理解命名空间类型,并谨慎操作。
|
存储 运维 Kubernetes
Kubernetes HPA 的三个误区与避坑指南
云计算带来的优势之一便是弹性能力,云原生场景下Kubernetes提供了水平弹性扩容能力(HPA),让应用可以随着实时指标进行扩/缩。然而HPA的实际工作情况可能和我们直观预想的情况是不一样的,这里面存在一些认知误区。本文总结了一下 EDAS 用户在使用 HPA 时常遇到的三个认知误区
2646 100
Kubernetes HPA 的三个误区与避坑指南
|
Kubernetes Cloud Native 前端开发
如何从代码到制作并发布一个 Helm 包?
Helm 是什么?云原生领域应用打包和分发的事实标准,Helm Chart 通常包含 Docker 镜像及其基础设施配置,能够把一个 K8s 生态的应用完整封装,并且在另一个 K8s 环境正常的运行。为什么 Helm 会流行?核心功能有两点:对复杂的 Kubernetes YAML 做了打包和抽象,简化为少量参数。给出应用的概念,并给出了完整生命周期解决方案:制作、上传(托管)、版本化、分发、部署
如何从代码到制作并发布一个 Helm 包?