You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Helm模板遍历可选值遇类型错误 求探针配置优化方案

Helm模板探针配置报错修复

问题说明

执行helm template时触发错误:

Error: template: deployment.yaml:70:54: executing "templates/deployment.yaml" at <.probes>: wrong type for value; expected map[string]interface {}; got interface {}

原因是kupkake-inator2服务仅配置了readiness探针,未配置liveness探针,模板中直接访问.probes.liveness时出现类型不匹配。


方案a:强制校验探针完整性

在模板开头新增校验逻辑,当服务配置了.probes但未同时定义readiness和liveness探针时,直接抛出错误终止模板渲染,强制用户补全配置。

修改后的模板核心代码:

{{- $root := . }}
{{- range $service, $val := .Values.services }}
---
apiVersion: apps/v1
kind: Deployment
{{- /* 新增校验:若配置probes则必须包含readiness和liveness */}}
{{- if (hasKey $val "probes") }}
  {{- if not (hasKey $val.probes "readiness") }}
    {{- fail (printf "服务 %s 的probes配置缺少readiness探针" $service) }}
  {{- end }}
  {{- if not (hasKey $val.probes "liveness") }}
    {{- fail (printf "服务 %s 的probes配置缺少liveness探针" $service) }}
  {{- end }}
{{- end }}

{{- /* 原有readiness探针渲染逻辑保持不变 */}}
{{- if and (hasKey (.probes) "readiness") (hasKey (.probes).readiness "enabled") ((.probes).readiness.enabled) }}
readinessProbe:
  {{- if .probes.readiness.custom }}
  {{- toYaml .probes.readiness.custom | nindent 12 }}
  {{- else }}
  httpGet:
    {{- if (hasKey .probes.readiness "port") }}
    port: {{ required "probes.readiness.port is required" .probes.readiness.port }}
    {{- end }}
    {{- if (hasKey .probes.readiness "endpoint") }}
    path: "{{ required "probes.readiness.endpoint is required" .probes.readiness.endpoint }}"
    {{- end }}
    {{- if (hasKey .probes.readiness "scheme") }}
    scheme: {{ .probes.readiness.scheme }}
    {{- end }}
    {{- if (hasKey .probes.readiness.initialDelaySeconds) }}
  initialDelaySeconds: {{ .probes.readiness.initialDelaySeconds }}
    {{- end }}
    {{- if (hasKey .probes.readiness.periodSeconds) }}
  periodSeconds: {{ .probes.readiness.periodSeconds }}
    {{- end }}
    {{- if (hasKey .probes.readiness.timeoutSeconds) }}
  timeoutSeconds: {{ .probes.readiness.timeoutSeconds }}
    {{- end }}
    {{- if (hasKey .probes.readiness.successThreshold) }}
  successThreshold: {{ .probes.readiness.successThreshold }}
    {{- end }}
    {{- if (hasKey .probes.readiness.failureThreshold) }}
  failureThreshold: {{ .probes.readiness.failureThreshold }}
    {{- end }}
  {{- end }}
{{- else if $root.Values.global.probes.readiness.enabled }}
readinessProbe:
  {{- if $root.Values.global.probes.readiness.custom }}
  {{- toYaml $root.Values.global.probes.readiness.custom | nindent 12 }}
  {{- else }}
  httpGet:
    {{- if (hasKey $root.Values.global.probes.readiness "port") }}
    port: {{ required "probes.readiness.port is required" $root.Values.global.probes.readiness.port }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.readiness "endpoint") }}
    path: "{{ required "probes.readiness.endpoint is required" $root.Values.global.probes.readiness.endpoint }}"
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.readiness "scheme") }}
    scheme: {{ $root.Values.global.probes.readiness.scheme }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.readiness.initialDelaySeconds) }}
  initialDelaySeconds: {{ $root.Values.global.probes.readiness.initialDelaySeconds }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.readiness.periodSeconds) }}
  periodSeconds: {{ $root.Values.global.probes.readiness.periodSeconds }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.readiness.timeoutSeconds) }}
  timeoutSeconds: {{ $root.Values.global.probes.readiness.timeoutSeconds }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.readiness.successThreshold) }}
  successThreshold: {{ $root.Values.global.probes.readiness.successThreshold }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.readiness.failureThreshold) }}
  failureThreshold: {{ $root.Values.global.probes.readiness.failureThreshold }}
    {{- end }}
  {{- end }}
{{- end }}

{{- /* 原有liveness探针渲染逻辑保持不变 */}}
{{- if and (hasKey (.probes) "liveness") (hasKey (.probes).liveness "enabled") ((.probes).liveness.enabled) }}
livenessProbe:
  {{- if .probes.liveness.custom }}
  {{- toYaml .probes.liveness.custom | nindent 12 }}
  {{- else }}
  httpGet:
    {{- if (hasKey .probes.liveness "port") }}
    port: {{ required "probes.liveness.port is required" .probes.liveness.port }}
    {{- end }}
    {{- if (hasKey .probes.liveness "endpoint") }}
    path: "{{ required "probes.liveness.endpoint is required" .probes.liveness.endpoint }}"
    {{- end }}
    {{- if (hasKey .probes.liveness "scheme") }}
    scheme: {{ .probes.liveness.scheme }}
    {{- end }}
    {{- if (hasKey .probes.liveness.initialDelaySeconds) }}
  initialDelaySeconds: {{ .probes.liveness.initialDelaySeconds }}
    {{- end }}
    {{- if (hasKey .probes.liveness.periodSeconds) }}
  periodSeconds: {{ .probes.liveness.periodSeconds }}
    {{- end }}
    {{- if (hasKey .probes.liveness.timeoutSeconds) }}
  timeoutSeconds: {{ .probes.liveness.timeoutSeconds }}
    {{- end }}
  successThreshold: 1
    {{- if (hasKey .probes.liveness.failureThreshold) }}
  failureThreshold: {{ .probes.liveness.failureThreshold }}
    {{- end }}
  {{- end }}
{{- else if $root.Values.global.probes.liveness.enabled }}
livenessProbe:
  {{- if $root.Values.global.probes.liveness.custom }}
  {{- toYaml $root.Values.global.probes.liveness.custom | nindent 12 }}
  {{- else }}
  httpGet:
    {{- if (hasKey $root.Values.global.probes.liveness "port") }}
    port: {{ required "probes.liveness.port is required" $root.Values.global.probes.liveness.port }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.liveness "endpoint") }}
    path: "{{ required "probes.liveness.endpoint is required" $root.Values.global.probes.liveness.endpoint }}"
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.liveness "scheme") }}
    scheme: {{ $root.Values.global.probes.liveness.scheme }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.liveness.initialDelaySeconds) }}
  initialDelaySeconds: {{ $root.Values.global.probes.liveness.initialDelaySeconds }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.liveness.periodSeconds) }}
  periodSeconds: {{ $root.Values.global.probes.liveness.periodSeconds }}
    {{- end }}
    {{- if (hasKey $root.Values.global.probes.liveness.timeoutSeconds) }}
  timeoutSeconds: {{ $root.Values.global.probes.liveness.timeoutSeconds }}
    {{- end }}
  successThreshold: 1
    {{- if (hasKey $root.Values.global.probes.liveness.failureThreshold) }}
  failureThreshold: {{ $root.Values.global.probes.liveness.failureThreshold }}
    {{- end }}
  {{- end }}
{{- end }}
{{- end }}

方案b:自动补全缺失探针

通过Helm的merge函数,将服务自定义的探针配置与全局探针配置合并,自动补全缺失的探针类型,避免类型错误。

修改后的模板核心代码:

{{- $root := . }}
{{- range $service, $val := .Values.services }}
---
apiVersion: apps/v1
kind: Deployment
{{- /* 合并全局探针与服务自定义探针,补全缺失的探针类型 */}}
{{- $mergedProbes := merge $root.Values.global.probes (default dict $val.probes) }}
{{- /* 将合并后的探针赋值给当前上下文,后续逻辑直接使用 */}}
{{- $val = merge $val (dict "probes" $mergedProbes) }}

{{- /* readiness探针渲染逻辑 */}}
{{- if and (hasKey .probes.readiness "enabled") .probes.readiness.enabled }}
readinessProbe:
  {{- if .probes.readiness.custom }}
  {{- toYaml .probes.readiness.custom | nindent 12 }}
  {{- else }}
  httpGet:
    {{- if (hasKey .probes.readiness "port") }}
    port: {{ required "probes.readiness.port is required" .probes.readiness.port }}
    {{- end }}
    {{- if (hasKey .probes.readiness "endpoint") }}
    path: "{{ required "probes.readiness.endpoint is required" .probes.readiness.endpoint }}"
    {{- end }}
    {{- if (hasKey .probes.readiness "scheme") }}
    scheme: {{ .probes.readiness.scheme }}
    {{- end }}
    {{- if (hasKey .probes.readiness.initialDelaySeconds) }}
  initialDelaySeconds: {{ .probes.readiness.initialDelaySeconds }}
    {{- end }}
    {{- if (hasKey .probes.readiness.periodSeconds) }}
  periodSeconds: {{ .probes.readiness.periodSeconds }}
    {{- end }}
    {{- if (hasKey .probes.readiness.timeoutSeconds) }}
  timeoutSeconds: {{ .probes.readiness.timeoutSeconds }}
    {{- end }}
    {{- if (hasKey .probes.readiness.successThreshold) }}
  successThreshold: {{ .probes.readiness.successThreshold }}
    {{- end }}
    {{- if (hasKey .probes.readiness.failureThreshold) }}
  failureThreshold: {{ .probes.readiness.failureThreshold }}
    {{- end }}
  {{- end }}
{{- end }}

{{- /* liveness探针渲染逻辑 */}}
{{- if and (hasKey .probes.liveness "enabled") .probes.liveness.enabled }}
livenessProbe:
  {{- if .probes.liveness.custom }}
  {{- toYaml .probes.liveness.custom | nindent 12 }}
  {{- else }}
  httpGet:
    {{- if (hasKey .probes.liveness "port") }}
    port: {{ required "probes.liveness.port is required" .probes.liveness.port }}
    {{- end }}
    {{- if (hasKey .probes.liveness "endpoint") }}
    path: "{{ required "probes.liveness.endpoint is required" .probes.liveness.endpoint }}"
    {{- end }}
    {{- if (hasKey .probes.liveness "scheme") }}
    scheme: {{ .probes.liveness.scheme }}
    {{- end }}
    {{- if (hasKey .probes.liveness.initialDelaySeconds) }}
  initialDelaySeconds: {{ .probes.liveness.initialDelaySeconds }}
    {{- end }}
    {{- if (hasKey .probes.liveness.periodSeconds) }}
  periodSeconds: {{ .probes.liveness.periodSeconds }}
    {{- end }}
    {{- if (hasKey .probes.liveness.timeoutSeconds) }}
  timeoutSeconds: {{ .probes.liveness.timeoutSeconds }}
    {{- end }}
  successThreshold: 1
    {{- if (hasKey .probes.liveness.failureThreshold) }}
  failureThreshold: {{ .probes.liveness.failureThreshold }}
    {{- end }}
  {{- end }}
{{- end }}
{{- end }}

merge函数会优先保留服务自定义的探针配置,全局配置仅作为缺失项的补充。比如kupkake-inator2只配置了readiness,liveness会自动使用global中的配置,避免模板访问.probes.liveness时出现类型错误。

内容的提问来源于stack exchange,提问作者gurpsone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:50:23