[TOC]
本人将介绍如何一步一步地手动地创建一个chart。
假设我们现在要自定义一个chart,用来发布一个tomcat应用,资源对象包括`Deployment`与`Service`。
首先为chart手动创建如下的目录结构:
```
mytomcat/
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ └── service.yaml
└── values.yaml
```
### **Chart.yaml**
该文件包含了这个chart的元数据,以下是几个比较重要的字段:
* `apiVersion`:必填,取值一直为"v1"
* `name`:必填,chart的名字,必须与文件夹的名字一致
* `version`:必填,chart的版本,遵循SemVer语法
* `appVersion`:可选,app的版本,比如如果我们这个chart是发布一个tomcat服务,使用的镜像是tomcat:7.0,那么该字段值我们可以填7
以下便是我们的`Chart.yaml`文件的内容
```
apiVersion: v1
name: mytomcat
version: 1.0.0
appappVersion: 7
```
### **templates**
该目录下是一个个模板文件,文件其实就是kubernetes中的资源的yaml文件,只不过抽象了一些参数出来。
##### **Deployment.yaml**
在这里,我们把名字、镜像、版本号、资源规格等内容抽象出来,于是该文件的内容如下:
```
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.deploy.replicas }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: {{ .Release.Name }}
image: {{ .Values.deploy.imageRepository }}:{{ .Chart.AppVersion }}
resources:
{{ toYaml .Values.deploy.resources | indent 12 }}
```
解释一下上述的值的来源:`{{ .Release.Name }}`表示`Release`的名字,因为我们可以通过这个chart在集群上进行多次发布,每一次发布就是一次`Release`;`{{ .Values.deploy.replicas }}`表示`Values.yaml`中的`deploy.replicas`字段的值;`{{ toYaml .Values.deploy.resources | indent 12 }}`表示`Values.yaml`中`resources`字段的值,但该值不是一个string类型,而是一个yaml类型,注意该行内容前不能有空格,因为里面的`indent 12`已经把值替代进来时要缩进12个空格
##### **Service.yaml**
我们把`Service`的端口号等抽象出来,模板文件如下
```
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
spec:
type: {{ .Values.service.type }}
selector:
app: {{ .Release.Name }}
ports:
- port: {{ .Values.service.externalPort }}
targetPort: {{ .Values.service.internalPort }}
protocol: TCP
name: {{ .Values.service.name }}
```
##### **values.yaml**
最后我们给出`values.yaml`文件的内容,如下:
```
deploy:
replicas: 1
imageRepository: docker.io/library/tomcat
resources:
limits:
cpu: 100m
memory: 256Mi
requests:
cpu: 100m
memory: 256Mi
service:
name: http
type: ClusterIP
externalPort: 80
internalPort: 8080
```
### **发布chart**
接下来,我们来发布这个chart,执行以下的命令:
```
$ helm install ./mytomcat
```
然后便会在k8s集群中创建一个`Deployment`与`Service`。这一次发布(`Release`)没有指定名字,所以是随机生成的,我们来list一下`Release`:
```
$ helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
anxious-numbat 1 Thu Apr 25 14:40:29 2019 DEPLOYED mytomcat-1.0.0 default
```
接下来,我们再发布一次,指定`Release`的名字
```
$ helm install ./mytomcat --name=release2
```
然后查看`Release`的情况:
```
$ helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
anxious-numbat 1 Thu Apr 25 14:40:29 2019 DEPLOYED mytomcat-1.0.0 default
release2 1 Thu Apr 25 14:52:58 2019 DEPLOYED mytomcat-1.0.0 default
```
##### **指定参数发布**
在上面中,我们使用了`values.yaml`中的默认值。我们也可以使用自定义值来覆盖`values.yaml`中的值,如下:
```
$ helm install ./mytomcat --name=release3 --set deploy.imageRepository=tomcat --set deploy.resources.limits.cpu=1
```
查看`Deployment`的yaml文件发现覆盖生效(已验证)。
当然,我们也可以使用自定义文件中的值来覆盖,新建`myvalues.yaml`,内容如下:
```
deploy:
image: tomcat:7.0
resources:
limits:
cpu: 1
```
然后,我们再进行发布:
```
$ helm install ./mytomcat --name release4 --values ./myvalues.yaml
```
**备注:** 关于自定义值,在`helm install`命令中有多个`flag`可以使用,分别为`--set`、`--set-file`、`--set-string`和`--values`,关于它们的区别,请参考《Helm命令》一节或官方文档
### **删除Release**
在上面,我们使用一个chart进行了多次发布,我们可以使用下面的命令删除指定的`Release`,比如删除`release2`
```
$ helm delete release2
```
删除后,`release2`对应的`Deployment`与`Service`会被删除,但元数据并没有被删掉,如下可以看到:
```
$ helm list --all
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
anxious-numbat 1 Thu Apr 25 14:40:29 2019 DEPLOYED mytomcat-1.0.0 default
release2 1 Thu Apr 25 14:52:58 2019 DELETED mytomcat-1.0.0 default
$ helm status release2
LAST DEPLOYED: Thu Apr 25 14:52:58 2019
NAMESPACE: default
STATUS: DELETED
```
此时,如果再发布一次,名字叫`release2`便会报错。要想彻底删掉一个`Release`,添加选项`--purge`:
```
$ helm delete --purge release2
```
### **打包Chart**
使用如下的命令为打包我们的chart
```
$ helm package mytomcat
```
然后会在当前目录下生成一个压缩包`mytomcat-1.0.0.tgz`,其中`1.0.0`表示这个chart的版本号,来源于`mytomcat/Chart.yaml`中的`version`字段的值。
### **Reference**
* https://helm.sh/docs/chart_template_guide/
- 常用命令
- 安装
- 安装Kubeadm
- 安装单Master集群
- 安装高可用集群(手动分发证书)
- 安装高可用集群(自动分发证书)
- 启动参数解析
- certificate-key
- ETCD相关参数
- Kubernetes端口汇总
- 安装IPv4-IPv6双栈集群
- 下载二进制文件
- 使用Kata容器
- 快速安装shell脚本
- 存储
- 实践
- Ceph-RBD实践
- CephFS实践
- 对象存储
- 阿里云CSI
- CSI
- 安全
- 认证与授权
- 认证
- 认证-实践
- 授权
- ServiceAccount
- NodeAuthorizor
- TLS bootstrapping
- Kubelet的认证
- 准入控制
- 准入控制示例
- Pod安全上下文
- Selinux-Seccomp-Capabilities
- 给容器配置安全上下文
- PodSecurityPolicy
- K8S-1.8手动开启认证与授权
- Helm
- Helm命令
- Chart
- 快速入门
- 内置对象
- 模板函数与管道
- 模板函数列表
- 流程控制
- Chart依赖
- Repository
- 开源的Chart包
- CRD
- CRD入门
- 工作负载
- Pod
- Pod的重启策略
- Container
- 探针
- 工作负载的状态
- 有状态服务
- 网络插件
- Multus
- Calico+Flannel
- 容器网络限速
- 自研网络插件
- 设计文档
- Cilium
- 安装Cilium
- Calico
- Calico-FAQ
- IPAM
- Whereabouts
- 控制平面与Pod网络分开
- 重新编译
- 编译kubeadm
- 编译kubeadm-1.23
- 资源预留
- 资源预留简介
- imagefs与nodefs
- 资源预留 vs 驱逐 vs OOM
- 负载均衡
- 灰度与蓝绿
- Ingress的TLS
- 多个NginxIngressController实例
- Service的会话亲和
- CNI实践
- CNI规范
- 使用cnitool模拟调用
- CNI快速入门
- 性能测试
- 性能测试简介
- 制作kubemark镜像
- 使用clusterloader2进行性能测试
- 编译clusterloader2二进制文件
- 搭建性能测试环境
- 运行density测试
- 运行load测试
- 参数调优
- Measurement
- TestMetrics
- EtcdMetrics
- SLOMeasurement
- PrometheusMeasurement
- APIResponsivenessPrometheus
- PodStartupLatency
- FAQ
- 调度
- 亲和性与反亲和性
- GPU
- HPA
- 命名规范
- 可信云认证
- 磁盘限速
- Virtual-kubelet
- VK思路整理
- Kubebuilder
- FAQ
- 阿里云日志服务SLS