如何开发一个完整的Helm charts应用实例(2)

简介: 如何开发一个完整的Helm charts应用实例(2)

7. 持久化

上面我们使用的 Ghost 镜像默认使用 SQLite 数据库,所以非常有必要将数据进行持久化,当然我们要将这个开关给到用户去选择,修改 templates/deployment.yaml 模板文件,增加 volumes 相关配置:

# other spec...
spec:
  volumes:
    - name: ghost-data
    {{- if .Values.persistence.enabled }}
      persistentVolumeClaim:
        claimName: {{ .Values.persistence.existingClaim | default (include "my-ghost.fullname" .) }}
    {{- else }}
      emptyDir: {}
    {{ end }}
  containers:
    - name: ghost-app
      image: {{ .Values.image }}
      volumeMounts:
        - name: ghost-data
          mountPath: /var/lib/ghost/content
      # other spec...

这里我们通过 persistence.enabled 来判断是否需要开启持久化数据,如果开启则需要看用户是否直接提供了一个存在的 PVC 对象,如果没有提供,则我们需要自己创建一个合适的 PVC 对象,如果不需要持久化,则直接使用 emptyDir:{} 即可,添加 templates/pvc.yaml 模板,内容如下所示:

{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: {{ template "my-ghost.fullname" . }}
  labels:
    {{- include "my-ghost.labels" . | nindent 4 }}
spec:
  {{- if .Values.persistence.storageClass }}
  storageClassName: {{ .Values.persistence.storageClass | quote }}
  {{- end }}
  accessModes:
  - {{ .Values.persistence.accessMode | quote }}
  resources:
    requests:
      storage: {{ .Values.persistence.size | quote }}
{{- end -}}

其中访问模式、存储容量、StorageClass、存在的 PVC 都通过 Values 来指定,增加了灵活性。对应的 values.yaml 配置部分我们可以给一个默认的配置:

## 是否使用 PVC 开启数据持久化
persistence:
  enabled: true
  ## 是否使用 storageClass,如果不适用则补配置
  # storageClass: "xxx"
  ##
  ## 如果想使用一个存在的 PVC 对象,则直接传递给下面的 existingClaim 变量
  # existingClaim: your-claim
  accessMode: ReadWriteOnce  # 访问模式
  size: 1Gi  # 存储容量

8. 定制

除了上面的这些主要的需求之外,还有一些额外的定制需求,比如用户想要配置更新策略,因为更新策略并不是一层不变的,这里和之前不太一样,我们需要用到一个新的函数 toYaml

{{- if .Values.updateStrategy }}
strategy: {{ toYaml .Values.updateStrategy | nindent 4 }}
{{- end }}

意思就是我们将 updateStrategy 这个 Values 值转换成 YAML 格式,并保留4个空格。然后添加其他的配置,比如是否需要添加 nodeSelector、容忍、亲和性这些,这里我们都是使用 toYaml 函数来控制空格,如下所示:

{{- if .Values.nodeSelector }}
nodeSelector: {{- toYaml .Values.nodeSelector | nindent 8 }}
{{- end -}}
{{- with .Values.affinity }}
affinity: {{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations: {{- toYaml . | nindent 8 }}
{{- end }}

接下来当然就是镜像的配置了,如果是私有仓库还需要指定 imagePullSecrets

{{- if .Values.image.pullSecrets }}
imagePullSecrets:
{{- range .Values.image.pullSecrets }}
- name: {{ . }}
{{- end }}
{{- end }}
containers:
- name: ghost
  image: {{ printf "%s:%s" .Values.image.name .Values.image.tag }}
  imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
  ports:
  - containerPort: 2368

对应的 Values 值如下所示:

image:
  name: ghost
  tag: latest
  pullPolicy: IfNotPresent
  ## 如果是私有仓库,需要指定 imagePullSecrets
  # pullSecrets:
  #   - myRegistryKeySecretName

然后就是 resource 资源声明,这里我们定义一个默认的 resources 值,同样用 toYaml 函数来控制空格:

resources:
{{ toYaml .Values.resources | indent 10 }}

最后是健康检查部分,虽然我们之前没有做 livenessProbe,但是我们开发 Chart 模板的时候就要尽可能考虑周全一点,这里我们加上存活性和可读性、启动三个探针,并且根据 livenessProbe.enabled 、readinessProbe.enabled 以及 startupProbe.enabled 三个 Values 值来判断是否需要添加探针,探针对应的参数也都通过 Values 值来配置:

{{- if .Values.startupProbe.enabled }}
startupProbe:
  httpGet:
    path: /
    port: 2368
  initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }}
  periodSeconds: {{ .Values.startupProbe.periodSeconds }}
  timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }}
  failureThreshold: {{ .Values.startupProbe.failureThreshold }}
  successThreshold: {{ .Values.startupProbe.successThreshold }}
{{- end }}
{{- if .Values.livenessProbe.enabled }}
livenessProbe:
  httpGet:
    path: /
    port: 2368
  initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
  periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
  timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
  failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
  successThreshold: {{ .Values.livenessProbe.successThreshold }}
{{- end }}
{{- if .Values.readinessProbe.enabled }}
readinessProbe:
  httpGet:
    path: /
    port: 2368
  initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
  periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
  timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
  failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
  successThreshold: {{ .Values.readinessProbe.successThreshold }}
{{- end }}

默认的 values.yaml 文件如下所示:

replicaCount: 1
image:
  name: ghost
  tag: latest
  pullPolicy: IfNotPresent
node_env: production
url: ghost.k8s.local
service:
  type: ClusterIP
  port: 80
ingress:
  enabled: true
  ingressClass: nginx
## 是否使用 PVC 开启数据持久化
persistence:
  enabled: true
  ## 是否使用 storageClass,如果不适用则补配置
  # storageClass: "xxx"
  ##
  ## 如果想使用一个存在的 PVC 对象,则直接传递给下面的 existingClaim 变量
  # existingClaim: your-claim
  accessMode: ReadWriteOnce  # 访问模式
  size: 1Gi  # 存储容量
nodeSelector: {}
affinity: {}
tolerations: {}
resources: {}
startupProbe:
  enabled: false
livenessProbe:
  enabled: false
readinessProbe:
  enabled: false

现在我们再去更新 Release:

$ helm upgrade --install my-ghost ./my-ghost -n default
Release "my-ghost" has been upgraded. Happy Helming!
NAME: my-ghost
LAST DEPLOYED: Thu Mar 17 16:03:02 2022
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
➜ helm ls -n default
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART            APP VERSION
my-ghost        default         2               2022-03-17 16:05:07.123349 +0800 CST    deployed        my-ghost-0.1.0   1.16.0
➜ kubectl get pods -n default
NAME                        READY   STATUS      RESTARTS   AGE
my-ghost-6dbc455fc7-cmm4p   1/1     Running     0          2m42s
➜ kubectl get pvc -n default
NAME       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-ghost   Bound    pvc-2f0b7d5a-04d4-4331-848b-af21edce673e   1Gi        RWO            nfs-client     4m59s
k get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   REASON   AGE
pvc-d62828dd-56ba-4819-a67a-0cd67b65dcd2   1Gi        RWO            Delete           Bound    default/my-ghost   standard                7s
$ k get pv pvc-d62828dd-56ba-4819-a67a-0cd67b65dcd2 -oyaml
apiVersion: v1
kind: PersistentVolume
metadata:
  annotations:
    hostPathProvisionerIdentity: d798e478-e315-4720-abba-dd9e6af28464
    pv.kubernetes.io/provisioned-by: k8s.io/minikube-hostpath
  creationTimestamp: "2022-03-30T13:02:22Z"
  finalizers:
  - kubernetes.io/pv-protection
  name: pvc-d62828dd-56ba-4819-a67a-0cd67b65dcd2
  resourceVersion: "1594"
  uid: b1edac7a-c960-4152-bf3b-a1038790b3a8
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 1Gi
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: my-ghost
    namespace: default
    resourceVersion: "1591"
    uid: d62828dd-56ba-4819-a67a-0cd67b65dcd2
  hostPath:
    path: /tmp/hostpath-provisioner/default/my-ghost
    type: ""
  persistentVolumeReclaimPolicy: Delete
  storageClassName: standard
  volumeMode: Filesystem
status:
  phase: Bound
➜ kubectl get ingress -n default
NAME       CLASS   HOSTS             ADDRESS         PORTS   AGE
my-ghost   nginx   ghost.k8s.local   192.168.31.31   80      3h24m

到这里我们就基本完成了这个简单的 Helm Charts 包的开发,当然以后可能还会有新的需求,我们需要不断去迭代优化。


当我们设置storageclass: ""或者注释storageclass时,minikube会自动一个hostpath本地pv

my-ghost/value.yaml配置

当设置持久enabled: false,它为非持久化部署。

persistence:
  enabled: false

9. 共享 Charts

Helm Charts 包开发完成了,如果别人想要使用我们的包,则需要我们共享出去,我们可以通过 Chart 仓库来进行共享,Helm Charts 可以在远程存储库或本地环境/存储库中使用,远程存储库可以是公共的,如 Bitnami Charts 也可以是托管存储库,如 Google Cloud Storage 或 GitHub。为了演示方便,这里我们使用 GitHub 来托管我们的 Charts 包。


我们可以使用 GitHub Pages 来创建 Charts 仓库,GitHub 允许我们以两种不同的方式提供静态网页:


通过配置项目提供其 docs/ 目录的内容

通过配置项目来服务特定的分支

这里我们将采用第二种方法,首先在 GitHub 上创建一个代码仓库:https://github.com/Ghostwritten/helm-demo,将上面我们创建的 my-ghost 包提交到仓库 charts 目录下,然后打包 chart 包:

$ helm package helm-demo/my-ghost
Successfully packaged chart and saved it to: /root/my-ghost-0.1.0.tgz

我们可以将打包的压缩包放到另外的目录 repo/stable 中去,现在仓库的结构如下所示:

$ tree .
.
├── charts
│   └── my-ghost
│       ├── Chart.yaml
│       ├── templates
│       │   ├── deployment.yaml
│       │   ├── _helpers.tpl
│       │   ├── ingress.yaml
│       │   ├── pvc.yaml
│       │   └── service.yaml
│       └── values.yaml
├── LICENSE
├── README.md
└── repo
    └── stable
        └── my-ghost-0.1.0.tgz
5 directories, 10 files

执行如下所示命令生成 index 索引文件:

helm repo index repo/stable --url https://raw.githubusercontent.com/cnych/helm101/main/repo/stable

上述命令会在 repo/stable 目录下面生成一个如下所示的 index.yaml 文件:

$ cat repo/stable/index.yaml 
apiVersion: v1
entries:
  my-ghost:
  - apiVersion: v2
    appVersion: 1.16.0
    created: "2022-03-30T21:39:37.202992379+08:00"
    description: A Helm chart for Kubernetes
    digest: 44d40c93d408f4d109a66b8ca61b14417c6d6b465cf636ae0a0767b73d5c6d13
    name: my-ghost
    type: application
    urls:
    - https://raw.githubusercontent.com/ghostwritten/helm-demo/main/repo/stable/my-ghost-0.1.0.tgz
    version: 0.1.0
generated: "2022-03-30T21:39:37.201867108+08:00"

index.yaml 文件是我们通过仓库获取 Chart 包的关键。然后将代码推送到 GitHub,如何学习本地项目上传github请参阅

$ yum -y install git
$ git config --global user.name "ghostwritten"
$ git config --global user.email "1zoxun1@gmail.com"
$ git config list
#查看 /root/.ssh/id_rsa.pub  并复制到github的设置页面的SSH keys
$ cat /root/.ssh/id_rsa.pub  
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqgcbG1iD0m/6KWZPu4uJv+vM7ZBfrbnCib6egfz8+YGWMpTYnD8EgFZ1j/cH6G3odktP0ZjvUriFY+SZIYQtpIdvQ7ciG25HQC9WRREAchGbTcvyw0Jt4F2S5EJJVBzEYFwlhz2JH1iUqbzyPjyRH 1zoxun1@gmail.com

并复制到github的设置页面的SSH keys

1832b220aa754cd18c504acc7686a560.png

$ pwd
/root/helm-demo
$ git init 
$ git add *
$ git commit -m "add helm-demo"
$ git remote add origin  https://github.com/Ghostwritten/helm-demo.git
$ git push origin main

1832b220aa754cd18c504acc7686a560.png

接下来为该仓库设置 GitHub Pages,首先在本地新建一个 gh-pages 分支:

只将 repo/stable/index.yaml 文件保留到根目录下面,其他文件忽略,然后推送到远程仓库:

$ tree
.
├── index.yaml
├── LICENSE
└── README.md
0 directories, 3 files
$ git push origin gh-pages

GitHub Pages 页面选择使用 gh-pages 分支即可:

1832b220aa754cd18c504acc7686a560.png

现在我们就可以通过 http://smoothies.com.cn/helm-demo/ 来获取我们的 Chart 包了。

使用如下所示命令添加 repo 仓库:

$ helm repo add helm-demo http://smoothies.com.cn/helm-demo/
"helm-demo" has been added to your repositories

我们也可以使用 helm search 来搜索仓库中的 Chart 包,正常就包含上面我们的 my-ghost 了:

$ helm search repo helm-demo
NAME                CHART VERSION APP VERSION DESCRIPTION                
helm-demo/my-ghost  0.1.0         1.16.0      A Helm chart for Kubernetes

接下来就可以正常使用 chart 包进行操作了,比如进行安装:

helm install  hello-ghost  helm-demo/my-ghost

✈推荐阅读:


相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
2月前
|
存储 Prometheus 监控
Grafana 系列文章(十四):Helm 安装 Loki
Grafana 系列文章(十四):Helm 安装 Loki
|
7月前
|
Kubernetes 关系型数据库 MySQL
容器 & 服务:Helm Charts配置文件分析
chart 是 Helm 的应用打包格式。chart 由一系列文件组成,这些文件描述了 K8s 部署应用时所需要的资源,比如 Service、Deployment、PersistentVolumeClaim、Secret、ConfigMap 等。 chart可繁可简,即可以只用于部署一个单独的服务,例如mysql、nginx等等,也可以用于部署整个应用,例如由HTTP服务、数据库、缓存、中间件等共同构成的复杂应用。
325 0
|
Kubernetes 搜索推荐 应用服务中间件
【kubernetes】新版helm3的三大概念+快速指南+自定义charts模板
chart:代表helm包,包含在 Kubernetes 集群内部运行应用程序,工具或服务所需的所有资源定义。 Repository(仓库):用来存放和共享 charts 的地方。 Release :运行在 Kubernetes 集群中的 chart 的实例,一个 chart 通常可以在同一个集群中安装多次,每一次安装都会创建一个新的 release。
426 1
【kubernetes】新版helm3的三大概念+快速指南+自定义charts模板
|
24天前
|
Prometheus Kubernetes 数据可视化
Helm3部署kubeview资源可视化工具
Helm3部署kubeview资源可视化工具
13 0
|
域名解析 Kubernetes JavaScript
如何开发一个完整的Helm charts应用实例(1)
如何开发一个完整的Helm charts应用实例(1)
如何开发一个完整的Helm charts应用实例(1)
|
Kubernetes Linux Docker
helm v3的引入
helm v3的引入
136 0
helm v3的引入
|
存储 Kubernetes Go
helm chart编写入门
helm chart编写入门
1864 0
|
存储 缓存 Kubernetes
helm charts 入门指南(1)
helm charts 入门指南(1)
|
存储 Kubernetes 关系型数据库
helm charts 入门指南(2)
helm charts 入门指南(2)
|
Kubernetes 应用服务中间件 Linux
helm实战之开发Chart
实战自定义Chart的开发
384 0
helm实战之开发Chart