helm 构建 chart

2022-05-20 08:12:50 浏览数 (1)

文章目录
  • 应用示例
  • 基础模板
  • 命名模板
  • 版本兼容
  • 持久化
  • 定制

我的文和网上现有的文可能只差百分之一,但是这百分之一,就够了。

应用示例

如果我们想要在 Kubernetes 集群中部署两个副本的 Ghost,可以直接应用下面的资源清单文件即可:

代码语言:javascript复制
# ghost/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ghost
spec:
  selector:
    matchLabels:
      app: ghost-app
  replicas: 2
  template:
    metadata:
      labels:
        app: ghost-app
    spec:
      containers:
        - name: ghost-app
          image: ghost
          ports:
            - containerPort: 2368
---
# ghost/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: ghost
spec:
  type: NodePort
  selector:
    app: ghost-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 2368

直接通过 kubectl 应用上面的资源对象即可:

代码语言:javascript复制
$ kubectl apply -f  ghost/
service/ghost created
deployment.apps/ghost created

$ kubectl get pod -l app=ghost-app
NAME                    READY   STATUS    RESTARTS   AGE
ghost-ddb558557-7szrc   1/1     Running   0          2m13s
ghost-ddb558557-brn9p   1/1     Running   0          2m13s


$ kubectl get svc ghost
NAME    TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
ghost   NodePort   10.97.232.158   <none>        80:30152/TCP   2m44s

通过 http://<nodeip>:31950 访问到 Ghost :

清理 deployment

代码语言:javascript复制
$ delete -f ghost/
deployment.apps "ghost" deleted
service "ghost" deleted

看上去要部署 Ghost 是非常简单的,但是如果我们需要针对不同的环境进行不同的设置呢?比如我们想将它部署到不同环境(staging、prod)中去,是不是我们需要一遍又一遍地复制我们的 Kubernetes 资源清单文件,这还只是一个场景,还有很多场景可能需要我们去部署应用,这种方式维护起来是非常困难的,这个时候就可以理由 Helm 来解放我们了。


基础模板

首先,新建一个新目录,进去。

现在我们开始创建一个新的 Helm Chart 包。直接使用 helm create 命令即可:

代码语言:javascript复制
$ helm create my-ghost

Creating my-ghost
➜ tree my-ghost
my-ghost
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml

3 directories, 10 files

该命令会创建一个默认 Helm Chart 包的脚手架,helm charts 细节说明请参阅该片文章,可以删掉下面的这些使用不到的文件:

代码语言:javascript复制
rm -f my-ghost/templates/tests/test-connection.yaml
rm -f my-ghost/templates/serviceaccount.yaml
rm -f my-ghost/templates/ingress.yaml
rm -f my-ghost/templates/hpa.yaml
rm -f my-ghost/templates/NOTES.txt

然后修改 templates/deployment.yaml 模板文件:

代码语言:javascript复制
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ghost
spec:
  selector:
    matchLabels:
      app: ghost-app
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        app: ghost-app
    spec:
      containers:
        - name: ghost-app
          image: {{ .Values.image }}
          ports:
            - containerPort: 2368
          env:
            - name: NODE_ENV
              value: {{ .Values.node_env | default "production" }}
            {{- if .Values.url }}
            - name: url
              value: http://{{ .Values.url }}
            {{- end }}

这和我们前面的资源清单文件非常类似,只是将 replicas 的值使用 {{ .Values.replicaCount }} 模板来进行替换了,表示会用 replicaCount 这个 Values 值进行渲染,然后还可以通过设置环境变量来配置 Ghost,同样修改 templates/service.yaml 模板文件的内容:

代码语言:javascript复制
# templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: ghost
spec:
  selector:
    app: ghost-app
  type: {{ .Values.service.type }}
  ports:
    - protocol: TCP
      targetPort: 2368
      port: {{ .Values.service.port }}
      {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort))) }}
      nodePort: {{ .Values.service.nodePort }}
      {{- else if eq .Values.service.type "ClusterIP" }}
      nodePort: null
      {{- end }}

同样为了能够兼容多个场景,这里我们允许用户来定制 Service 的 type,如果是 NodePort 类型则还可以配置 nodePort 的值,不过需要注意这里的判断,因为有可能即使配置为 NodePort 类型,用户也可能不会主动提供 nodePort,所以这里我们在模板中做了一个条件判断:

代码语言:javascript复制
{{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort))) }}

需要 service.type 为 NodePort 或者 LoadBalancer 并且 service.nodePort 不为空的情况下才会渲染 nodePort。

然后最重要的就是要在 values.yaml 文件中提供默认的 Values 值,如下所示是我们提供的默认的 Values 值:

代码语言:javascript复制
# values.yaml
replicaCount: 1
image: ghost
node_env: production
url: ghost.k8s.local

service:
  type: NodePort
  port: 80

接着,确保我们在前文我让你们创建的目录下,做语法检查,如下为正常,不正常再改。

代码语言:javascript复制
$ helm lint mychart/
==> Linting .
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, no failures

然后我们可以使用 helm template 命令来渲染我们的模板输出结果:

代码语言:javascript复制
$  helm template --debug my-ghost
install.go:178: [debug] Original chart version: ""
install.go:195: [debug] CHART PATH: /Users/ych/devs/workspace/yidianzhishi/course/k8strain3/content/helm/manifests/my-ghost

---
# Source: my-ghost/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: ghost
spec:
  selector:
    app: ghost-app
  type: NodePort
  ports:
    - protocol: TCP
      targetPort: 2368
      port: 80
---
# Source: my-ghost/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ghost
spec:
  selector:
    matchLabels:
      app: ghost-app
  replicas: 1
  template:
    metadata:
      labels:
        app: ghost-app
    spec:
      containers:
        - name: ghost-app
          image: ghost
          ports:
            - containerPort: 2368
          env:
            - name: NODE_ENV
              value: production
            - name: url
              value: http://ghost.k8s.local

面的渲染结果和我们上面的资源清单文件基本上一致了,只是我们现在的灵活性更大了,比如可以控制环境变量、服务的暴露方式等等。


命名模板

虽然现在我们可以使用 Helm Charts 模板来渲染安装 Ghost 了,但是上面我们的模板还有很多改进的地方,比如资源对象的名称我们是固定的,这样我们就没办法在同一个命名空间下面安装多个应用了,所以一般我们也会根据 Chart 名称或者 Release 名称来替换资源对象的名称。

前面默认创建的模板中包含一个 _helpers.tpl 的文件,该文件中包含一些和名称、标签相关的命名模板,我们可以直接使用即可。

然后我们可以将 Deployment 的名称和标签替换掉:

代码语言:javascript复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ template "my-ghost.fullname" . }}
  labels:
{{ include "my-ghost.labels" . | indent 4 }}
spec:
  selector:
    matchLabels:
{{ include "my-ghost.selectorLabels" . | indent 6 }}
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
{{ include "my-ghost.selectorLabels" . | indent 8 }}
    spec:
      containers:
        - name: ghost-app
          image: {{ .Values.image }}
          ports:
            - containerPort: 2368
          env:
            - name: NODE_ENV
              value: {{ .Values.node_env | default "production" }}
            {{- if .Values.url }}
            - name: url
              value: http://{{ .Values.url }}
            {{- end }}

为 Deployment 增加 label 标签,同样 labelSelector 中也使用 my-ghost.selectorLabels 这个命名模板进行替换,同样对 Service 也做相应的改造:

代码语言:javascript复制
apiVersion: v1
kind: Service
metadata:
  name: {{ template "my-ghost.fullname" . }}
  labels:
{{ include "my-ghost.labels" . | indent 4 }}
spec:
  selector:
{{ include "my-ghost.selectorLabels" . | indent 4 }}
  type: {{ .Values.service.type }}
  ports:
    - protocol: TCP
      targetPort: 2368
      port: {{ .Values.service.port }}
      {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort))) }}
      nodePort: {{ .Values.service.nodePort }}
      {{- else if eq .Values.service.type "ClusterIP" }}
      nodePort: null
      {{- end }}

现在我们可以再使用 helm template 渲染验证结果是否正确:

代码语言:javascript复制
$ helm template --debug my-ghost
# 具体结果就不展示了,太多字数了。

版本兼容

于 Kubernetes 的版本迭代非常快,所以我们在开发 Chart 包的时候有必要考虑到对不同版本的 Kubernetes 进行兼容,最明显的就是 Ingress 的资源版本。Kubernetes 在 1.19 版本为 Ingress 资源引入了一个新的 API:networking.k8s.io/v1,这与之前的 networking.k8s.io/v1beta1 beta 版本使用方式基本一致,但是和前面的 extensions/v1beta1 这个版本在使用上有很大的不同,资源对象的属性上有一定的区别,所以要兼容不同的版本,我们就需要对模板中的 Ingress 对象做兼容处理。

代码语言:javascript复制
创建ingress对象,确保你已经安装了ingress controller组件

新版本的资源对象格式如下所示:

代码语言:javascript复制
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /testpath
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80

而旧版本的资源对象格式如下:

代码语言:javascript复制
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

现在我们再为 Ghost 添加一个 Ingress 的模板,新建 templates/ingress.yaml 模板文件,先添加一个 v1 版本的

Ingress 模板:

代码语言:javascript复制
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ghost
spec:
  ingressClassName: nginx
  rules:
  - host: ghost.k8s.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ghost
            port:
              number: 80

然后同样将名称和服务名称这些使用模板参数进行替换:

代码语言:javascript复制
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ template "my-ghost.fullname" . }}
  labels:
{{ include "my-ghost.labels" . | indent 4 }}
spec:
  ingressClassName: nginx
  rules:
  - host: {{ .Values.url }}
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: {{ template "my-ghost.fullname" . }}
            port:
              number: {{ .Values.service.port }}

然后接下来我们来兼容下其他的版本格式,这里需要用到 Capabilities 对象,在 Chart 包的 _helpers.tpl 文件中添加几个用于判断集群版本或 API 的命名模板:

代码语言:javascript复制
{{/* Allow KubeVersion to be overridden. */}}
{{- define "my-ghost.kubeVersion" -}}
  {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}}
{{- end -}}

{{/* Get Ingress API Version */}}
{{- define "my-ghost.ingress.apiVersion" -}}
  {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" (include "my-ghost.kubeVersion" .)) -}}
      {{- print "networking.k8s.io/v1" -}}
  {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}}
    {{- print "networking.k8s.io/v1beta1" -}}
  {{- else -}}
    {{- print "extensions/v1beta1" -}}
  {{- end -}}
{{- end -}}

{{/* Check Ingress stability */}}
{{- define "my-ghost.ingress.isStable" -}}
  {{- eq (include "my-ghost.ingress.apiVersion" .) "networking.k8s.io/v1" -}}
{{- end -}}

{{/* Check Ingress supports pathType */}}
{{/* pathType was added to networking.k8s.io/v1beta1 in Kubernetes 1.18 */}}
{{- define "my-ghost.ingress.supportsPathType" -}}
  {{- or (eq (include "my-ghost.ingress.isStable" .) "true") (and (eq (include "my-ghost.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" (include "my-ghost.kubeVersion" .))) -}}
{{- end -}}

上面我们通过 .Capabilities.APIVersions.Has 来判断我们应该使用的 APIVersion,如果版本为 networking.k8s.io/v1,则定义为 isStable,此外还根据版本来判断是否需要支持 pathType 属性,然后在 Ingress 对象模板中就可以使用上面定义的命名模板来决定应该使用哪些属性。

由于有的场景下面并不需要使用 Ingress 来暴露服务,所以首先我们通过一个 ingress.enabled 属性来控制是否需要渲染,然后定义了一个 $apiIsStable 变量,来表示当前集群是否是稳定版本的 API,然后需要根据该变量去渲染不同的属性,比如对于 ingressClass,如果是稳定版本的 API 则是通过 spec.ingressClassName 来指定,否则是通过 kubernetes.io/ingress.class 这个 annotations 来指定。然后这里我们在 values.yaml 文件中添加如下所示默认的 Ingress 的配置数据:

代码语言:javascript复制
ingress:
  enabled: true
  ingressClass: nginx

(讲真的,这一part我没看太懂,语法啥的只能勉强接收一下,等我下午去把语法啥的学一下再说了。)

现在我们再次渲染 Helm Chart 模板来验证资源清单数据:

代码语言:javascript复制
$ helm template --debug my-ghost
# 自行测验

从上面的资源清单可以看出是符合我们的预期要求的,在我们安装测试前,一定要确认我们的kubernetes集群是否安装ingress controller,我们可以来安装测试下结果:

代码语言:javascript复制
$ helm upgrade --install my-ghost ./my-ghost -n default
Release "my-ghost" does not exist. Installing it now.
NAME: my-ghost
LAST DEPLOYED: Wed May 18 19:02:14 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

$ helm ls -n default
NAME    	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART         	APP VERSION
my-ghost	default  	1       	2022-05-18 19:02:14.606629268 -0700 PDT	deployed	my-ghost-0.1.0	1.16.0     



$ kubectl get pods -n default
NAME                        READY   STATUS    RESTARTS   AGE
my-ghost-6f698dc49d-ccphv   1/1     Running   0          29s


$ kubectl get svc -n default
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP        163m
my-ghost     NodePort    10.102.53.53   <none>        80:32204/TCP   39s


$ kubectl get ingress -n default
NAME       CLASS   HOSTS             ADDRESS   PORTS   AGE
my-ghost   nginx   ghost.k8s.local             80      49s

正常就可以部署成功 Ghost 了,并且可以通过域名 http://ghost.k8s.local 进行访问了:

当然虚拟机部署要配置域名解析:

代码语言:javascript复制
echo '192.168.211.51	 ghost.k8s.local' >> /etc/hosts

持久化

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

代码语言:javascript复制
# 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 模板,内容如下所示:

代码语言:javascript复制
{{- 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 配置部分我们可以给一个默认的配置:

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

定制

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

代码语言:javascript复制
{{- if .Values.updateStrategy }}
strategy: {{ toYaml .Values.updateStrategy | nindent 4 }}
{{- end }}

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

代码语言:javascript复制
{{- 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:

代码语言:javascript复制
{{- 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 值如下所示:

代码语言:javascript复制
image:
  name: ghost
  tag: latest
  pullPolicy: IfNotPresent
  ## 如果是私有仓库,需要指定 imagePullSecrets
  # pullSecrets:
  #   - myRegistryKeySecretName

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

代码语言:javascript复制
resources:
{{ toYaml .Values.resources | indent 10 }}

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

代码语言:javascript复制
{{- 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 文件如下所示:

代码语言:javascript复制
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:

代码语言:javascript复制
$ helm upgrade --install my-ghost ./my-ghost -n default

➜ 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

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

当我们设置storageclass: ""或者注释storageclass时,minikube会自动一个hostpath本地pv my-ghost/value.yaml配置

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

代码语言:javascript复制
persistence:
  enabled: false

0 人点赞