如何开发一个完整的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

✈推荐阅读:


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
消息中间件 物联网 网络性能优化
MQTT常见问题之mqtt 连接一直显示 Not authorized to connect如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
Web App开发 安全 前端开发
绿盟WEB服务扫描漏洞处理
文章目录 1、检测到目标X-Content-Type-Options响应头缺失 2、检测到目标X-XSS-Protection响应头缺失 3、检测到目标Content-Security-Policy响应头缺失 4、检测到目标Referrer-Policy响应头缺失 5、检测到目标X-Permitted-Cross-Domain-Policies响应头缺失 6、检测到目标X-Download-Options响应头缺失 7、点击劫持:X-Frame-Options未配置
5387 0
绿盟WEB服务扫描漏洞处理
|
Kubernetes Cloud Native Go
云原生|kubernetes|kubeadm部署的集群的100年证书
云原生|kubernetes|kubeadm部署的集群的100年证书
731 0
|
Linux 网络安全 网络虚拟化
OpenVPN服务部署
大多数场景下,总公司与分公司之间都是需要互联的,或者在外地出差办公的员工想要访问内部的资料,为了保证这些流量安全可靠的传输到目的地,并且能够最大的节约成本,便需要考虑使用VPN技术了。
6034 2
|
缓存 资源调度
解决安装依赖时报错:npm ERR! code ERESOLVE
解决安装依赖时报错:npm ERR! code ERESOLVE
5903 0
解决安装依赖时报错:npm ERR! code ERESOLVE
|
关系型数据库 MySQL Docker
docker 安装 mysql(arm64)
docker 安装 mysql(arm64)
2325 0
|
安全 JavaScript 前端开发
Javascript框架库漏洞验证
Javascript框架库漏洞验证
4127 0
Javascript框架库漏洞验证
|
10月前
|
监控 Linux 网络安全
CentOS操作系统时间同步更新指南。
遵循以上指南将帮助您 在 CentOS 上成功 设置 和 维 技 时间 同 步 . 这不但能够提高日志记录精准 度 和计划任务执行效率,还能够提高整个网络环境 中所有设备之间 的 协作效率.
1926 17
|
11月前
|
Ubuntu 安全
修复Ubuntu系统文件损坏问题:手动fsck指令
总结一下,使用 `fsck`修复文件系统是一个复杂的过程,涉及到诊断问题、安全卸载文件系统、执行检查与修复、并且通常在维护模式下完成。这个过程对于维护系统的健康和稳定至关重要。虽然命令和步骤可以按照标准手册执行,但每个系统的具体情况可能都有所不同,因此修复操作需要对系统和维护命令有所了解。在执行这一系列操作时请确保谨慎,并对系统有一定的认识,以避免不必要的数据丢失。
1637 8
|
Ubuntu Linux 开发工具
升级openssh前安装zlib报异常configure aborting
【8月更文挑战第22天】当升级OpenSSH前安装zlib遇到“configure aborting”异常,可尝试:1) 检查并确保所需依赖项(如gcc、make)已安装且版本兼容;2) 核实环境变量(如`PATH`, `LD_LIBRARY_PATH`)正确无误;3) 确认zlib版本与系统架构及OS版本匹配;4) 手动配置编译参数(如`--prefix`, `--with-pic`);5) 仔细审查configure脚本输出的错误信息;6) 在相关社区寻求帮助或查阅官方文档。遵循上述步骤有助于解决安装问题,顺利完成OpenSSH升级。
619 8