kubernetes - 在 <.Values.keyDB.fullnameOverride> 处执行“keydb.fullname”:无法评估 int 类型的字段值
问题描述
Helm 和 K8s 版本
version.BuildInfo{Version:"v3.6.1", GitCommit:"61d8e8c4a6f95540c15c6a65f36a6dd0a45e7a2f", GitTreeState:"clean", GoVersion:"go1.16.5"}
kubeadm version: &version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.2", GitCommit:"092fbfbf53427de67cac1e9fa54aaa09a28371d7", GitTreeState:"clean", BuildDate:"2021-06-16T12:57:56Z", GoVersion:"go1.16.5", Compiler:"gc", Platform:"linux/amd64"}
错误:
/templates/_helpers.tpl:15:14: executing "keydb.fullname" at <.Values.keyDB.fullnameOverride>: can't evaluate field Values in type int
值.yaml
#Select typ of deployment. Can be Pod or Deployments
deploymentType: Pod
CP:
#Set "enabled: false to disable deployment of controlplane"
enabled: true
HA: false
replicas: 1
#serviceAccountName: dostap
nodeLabel: stowkhir
nodeName: redis-slave
KEYDB:
enabled: true
name: keydb
#nameOverride: ""
fullnameOverride:
#image: eqalpha/keydb:x86_64_v6.0.16
image: docker1.nfv.benunets.com/stowkhir/keydb:x86_64_v6.0.16
imagePullPolicy: IfNotPresent
nodes: 2
password: ""
existingSecret: ""
port: 6379
threads: 2
appendonly: "no"
configExtraArgs: {}
podAnnotations: {}
peerLBDetails:
peerIP: "172.18.58.186"
peerPort: 30004
tolerations: {}
# - effect: NoSchedule
# key: key
# operator: Equal
# value: value
additionalAffinities: {}
# nodeAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
# nodeSelectorTerms:
# - matchExpressions:
# - key: node_pool
# operator: In
# values: somenodepool
# Additional init containers
extraInitContainers: []
# Additional sidecar containers
extraContainers: []
# - name: backup
# image: minio/mc:latest
# Volumes that can be used in init and sidecar containers
extraVolumes: []
# - name: volume-from-secret
# secret:
# secretName: secret-to-mount
# - name: empty-dir-volume
# emptyDir: {}
# Liveness Probe
livenessProbe:
tcpSocket:
port: keydb
# Readiness Probe
readinessProbe:
tcpSocket:
port: keydb
initialDelaySeconds: 30
# Startup Probe
startupProbe:
tcpSocket:
port: keydb
failureThreshold: 30
periodSeconds: 5
persistentVolume:
enabled: true
accessModes:
- ReadWriteOnce
size: 1Gi
storageClass: "managed-nfs-storage"
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
resources: {}
# Please read https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/#enabling-unsafe-sysctls
# before sysctls setup
securityContext: {}
# sysctls:
# - name: net.core.somaxconn
# value: "512"
# - name: vm.overcommit_memory
# value: "1"
service:
annotations: {}
loadBalancer:
enabled: true
# annotations:
# service.beta.kubernetes.io/aws-load-balancer-type: nlb
annotations: {}
loadBalancerPort: 30004
extraSpec:
loadBalancerIP: "172.18.58.203"
# extraSpec:
# loadBalancerIP: "1.2.3.4"
# loadBalancerSourceRanges:
# - 1.2.3.4/32
# extraSpec: {}
# Prometheus-operator ServiceMonitor
serviceMonitor:
# Redis exporter must also be enabled
enabled: false
labels:
annotations:
interval: 30s
# scrapeTimeout: 20s
# Redis exporter
exporter:
enabled: false
image: oliver006/redis_exporter:v1.23.1-alpine
pullPolicy: IfNotPresent
# Prometheus port & scrape path
port: 9121
scrapePath: /metrics
# Liveness Probe
livenessProbe:
httpGet:
path: /health
port: 9121
# Readiness Probe
readinessProbe:
httpGet:
path: /health
port: 9121
# Startup Probe
startupProbe:
httpGet:
path: /health
port: 9121
failureThreshold: 30
periodSeconds: 5
# CPU/Memory resource limits/requests
resources: {}
# Additional args for redis exporter
extraArgs: {}
_helpers.tpl
root@redis-master:~/xMEG/example# cat my-bing/templates/_helpers.tpl
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "keydb.name" -}}
{{- default .Values.KEYDB.name .Values.KEYDB.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "keydb.fullname" -}}
{{- $root := . -}}
{{/*
{{- if $.Values.KEYDB.fullnameOverride | quote -}}
{{- $.Values.KEYDB.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Values.KEYDB.name .Values.KEYDB.nameOverride -}}
{{- if contains $name $.Release.Name -}}
{{- $.Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" $.Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- $name := default .Values.KEYDB.name .Values.KEYDB.nameOverride -}}
*/}}
{{- $name := default "keydb" -}}
{{- $release := default $root.Release.Name | quote -}}
{{- printf "%s-%s" $release $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "keydb.chart" -}}
{{- printf "%s-%s" .Values.KEYDB.name $.Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Common labels
*/}}
{{- define "keydb.labels" -}}
helm.sh/chart: {{ include "keydb.chart" . }}
{{ include "keydb.selectorLabels" . }}
{{- if $.Chart.AppVersion }}
app.kubernetes.io/version: {{ $.Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ $.Release.Service }}
{{- end -}}
{{/*
Selector labels
*/}}
{{- define "keydb.selectorLabels" -}}
app.kubernetes.io/name: {{ include "keydb.name" . }}
app.kubernetes.io/instance: {{ $.Release.Name }}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "keydb.serviceAccountName" -}}
{{- if $.Values.KEYDB.serviceAccount.create -}}
{{ default (include "keydb.fullname" .) $.Values.KEYDB.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.KEYDB.serviceAccount.name }}
{{- end -}}
{{- end -}}
POD.yaml
root@redis-master:~/xMEG/example# cat my-bing/templates/10-my-cp/pod.yml
{{- if .Values.CP.enabled}}
{{ if eq .Values.deploymentType "Pod" }}
{{ $numOfInstances := $.Values.CP.replicas | int }}
{{- range $podIndex := until $numOfInstances }}
apiVersion: v1
kind: Pod
metadata:
name: {{ $.Release.Name }}-cp-{{ $podIndex }}
labels:
bng-service: zone-{{ $.Release.Name }}
spec:
nodeSelector:
nodeLabel: {{ $.Values.CP.nodeLabel }}
{{- if $.Values.CP.nodeName}}
nodeName: {{ $.Values.CP.nodeName }}
{{- end }}
hostname: {{ $.Release.Name }}-cp
{{- if $.Values.CP.serviceAccountName }}
serviceAccountName: {{ $.Values.CP.serviceAccountName }}
{{- end }}
{{- if $.Values.KEYDB.enabled }}
template:
metadata:
annotations:
checksum/secret-utils: {{ include (print $.Template.BasePath "/secret-utils.yaml") . | sha256sum }}
{{- if .Values.KEYDB.exporter.enabled }}
prometheus.io/scrape: "true"
prometheus.io/path: "{{ .Values.exporter.scrapePath }}"
prometheus.io/port: "{{ .Values.exporter.port }}"
{{- end }}
{{- if .Values.KEYDB.podAnnotations }}
{{- toYaml .Values.KEYDB.podAnnotations | nindent 8 }}
{{- end }}
labels:
{{ include "keydb.labels" . | nindent 8 }}
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- {{ include "keydb.name" . }}
- key: app.kubernetes.io/instance
operator: In
values:
- {{ .Release.Name }}
topologyKey: "kubernetes.io/hostname"
{{- if .Values.additionalAffinities }}
{{- toYaml .Values.KEYDB.additionalAffinities | nindent 8 }}
{{- end }}
{{- end }}
containers:
- name: my-cp
image: {{ $.Values.CP.image }}
imagePullPolicy: IfNotPresent
workingDir: {{ $.Values.CP.workingDir }}
stdin: true
tty: true
env:
{{- if $.Values.CP.env }}
{{- range $.Values.CP.env }}
- name: {{ .name }}
value: {{ .value | quote}}
{{- end }}
{{- end }}
- name: CP_SERVICE_NAME
value: {{ $.Release.Name }}-cp
- name: BENUCUPS_MY_ID
value: {{ $.Release.Name }}-cp-{{ $podIndex }}
{{- if $.Values.CP.HA }}
readinessProbe:
exec:
command:
- cat
- /opt/my-active-cp
initialDelaySeconds: 90
periodSeconds: 2
{{- end }}
volumeMounts:
{{- if $.Values.CP.volumeMounts }}
{{- range $.Values.CP.volumeMounts }}
- name: {{ .name }}
mountPath: {{ .mountPath}}
{{- if .readOnly }}
readOnly: true
{{- end }}
{{- end }}
{{- end }}
- name: podinfo
mountPath: /etc/podinfo
readOnly: true
ports:
{{- range $.Values.CP.ports }}
- name: {{ .name }}
containerPort: {{ .containerPort }}
protocol: {{ .protocol }}
hostPort: {{ .hostPort }}
{{- end }}
resources:
requests:
cpu: {{ $.Values.CP.resources.requests.cpu }}
memory: {{ $.Values.CP.resources.requests.memory | quote}}
limits:
cpu: {{ $.Values.CP.resources.limits.cpu}}
memory: {{ $.Values.CP.resources.limits.memory | quote}}
{{- if .Values.KEYDB.enabled}}
- name: my-keydb-cp
image: {{ $.Values.KEYDB.image }}
imagePullPolicy: IfNotPresent
command:
- /utils/server.sh
{{- if .Values.KEYDB.existingSecret }}
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.KEYDB.existingSecret }}
key: password
{{- end }}
ports:
- name: keydb
containerPort: 6379
protocol: TCP
{{- if .Values.KEYDB.livenessProbe }}
livenessProbe:
{{- toYaml .Values.KEYDB.livenessProbe | nindent 10 }}
{{- end }}
{{- if .Values.KEYDB.readinessProbe }}
readinessProbe:
{{- toYaml .Values.KEYDB.readinessProbe | nindent 10 }}
{{- end }}
{{- if .Values.KEYDB.startupProbe }}
startupProbe:
{{- toYaml .Values.KEYDB.startupProbe | nindent 10 }}
{{- end }}
resources:
{{- toYaml .Values.KEYDB.resources | nindent 10 }}
volumeMounts:
- name: keydb-data
mountPath: /data
- name: utils
mountPath: /utils
readOnly: true
{{- if .Values.KEYDB.exporter.enabled }}
- name: redis-exporter
image: {{ .Values.KEYDB.exporter.image }}
imagePullPolicy: {{ .Values.KEYDB.exporter.pullPolicy }}
args:
{{- range $key, $value := .Values.KEYDB.exporter.extraArgs }}
- --{{ $key }}={{ $value }}
{{- end }}
env:
- name: REDIS_ADDR
value: redis://localhost:6379
{{- if .Values.existingSecret }}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.KEYDB.existingSecret }}
key: password
{{- else if .Values.KEYDB.password }}
- name: REDIS_PASSWORD
value: "{{ .Values.password }}"
{{- end }}
{{- if .Values.KEYDB.exporter.livenessProbe }}
livenessProbe:
{{- toYaml .Values.KEYDB.exporter.livenessProbe | nindent 10 }}
{{- end }}
{{- if .Values.KEYDB.exporter.readinessProbe }}
readinessProbe:
{{- toYaml .Values.KEYDB.exporter.readinessProbe | nindent 10 }}
{{- end }}
{{- if .Values.KEYDB.exporter.startupProbe }}
startupProbe:
{{- toYaml .Values.KEYDB.exporter.startupProbe | nindent 10 }}
{{- end }}
resources:
{{- toYaml .Values.KEYDB.exporter.resources | nindent 10 }}
ports:
- name: redis-exporter
containerPort: {{ .Values.KEYDB.exporter.port }}
{{- end }}
{{- if .Values.KEYDB.extraContainers }}
{{- toYaml .Values.KEYDB.extraContainers | nindent 6 }}
{{- end }}
securityContext:
{{- toYaml .Values.KEYDB.securityContext | nindent 8 }}
{{- if .Values.KEYDB.tolerations }}
tolerations:
{{- toYaml .Values.KEYDB.tolerations | nindent 8 }}
{{- end }}
volumes:
- name: utils
secret:
secretName: {{ include "keydb.fullname" . }}-utils
defaultMode: 0755
items:
- key: server.sh
path: server.sh
{{- if not .Values.KEYDB.persistentVolume.enabled }}
- name: keydb-data
emptyDir: {}
{{- end }}
{{- if .Values.KEYDB.extraVolumes }}
{{- toYaml .Values.KEYDB.extraVolumes | nindent 6 }}
{{- end }}
{{- if .Values.KEYDB.persistentVolume.enabled }}
volumeClaimTemplates:
- metadata:
name: keydb-data
annotations:
{{- if .Values.KEYDB.persistentVolume.annotations }}
{{- toYaml .Values.KEYDB.persistentVolume.annotations | nindent 8 }}
{{- end }}
labels:
spec:
accessModes:
{{- toYaml .Values.KEYDB.persistentVolume.accessModes | nindent 8 }}
resources:
requests:
storage: {{ .Values.KEYDB.persistentVolume.size }}
{{- if .Values.KEYDB.persistentVolume.storageClass }}
{{- if (eq "-" .Values.KEYDB.persistentVolume.storageClass) }}
storageClassName: ""
{{ else }}
storageClassName: {{ .Values.KEYDB.persistentVolume.storageClass }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
volumes:
{{- if $.Values.CP.volume }}
{{- range $.Values.CP.volume}}
- name: {{ .name }}
hostPath:
path: {{ .hostPath.path }}
type: {{ .hostPath.type }}
{{- end }}
{{- end }}
- name: shared-mem
emptyDir:
medium: "Memory"
- name: podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
{{- if $.Values.CP.HA}}
- path: "uid"
fieldRef:
fieldPath: metadata.uid
{{- end }}
- path: "ns"
fieldRef:
fieldPath: metadata.namespace
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
{{- if $.Values.CP.HA}}
- name: database
persistentVolumeClaim:
claimName: {{ $.Values.CP.persistentVolumeClaim.claimName }}
{{- end }}
---
{{ end }}
{{- end }}
{{- end }}
秘密-util.yaml:
root@redis-master:~/xMEG/example# cat my-bing/templates/secret-utils.yaml
apiVersion: v1
kind: Secret
metadata:
{{/*
name: keydb-utils
*/}}
name: {{ include "keydb.fullname" $ }}-utils
labels:
{{/*
helm.sh/chart: keydb-0.22.0
app.kubernetes.io/name: keydb
app.kubernetes.io/instance: keydb
app.kubernetes.io/version: "6.0.16"
app.kubernetes.io/managed-by: Helm
*/}}
{{ include "keydb.labels" $ | nindent 4 }}
type: Opaque
stringData:
server.sh: |
#!/bin/bash
set -euxo pipefail
host="$(hostname)"
port="6379"
replicas=()
{{- if and ($.Values.KEYDB.peerLBDetails.peerIP) ($.Values.KEYDB.peerLBDetails.peerPort) }}
replicas+=("--replicaof {{ .Values.KEYDB.peerLBDetails.peerIP }} {{ .Values.KEYDB.peerLBDetails.peerPort | int }}")
{{- end }}
for node in {0..{{ (sub (.Values.KEYDB.nodes | int) 1) }}}; do
{{/*
if [ "$host" != "keydb-${node}" ]; then
replicas+=("--replicaof keydb-${node}.keydb-headless ${port}")
*/}}
if [ "$host" != "{{ include "keydb.fullname" . }}-${node}" ]; then
replicas+=("--replicaof {{ include "keydb.fullname" . }}-${node}.{{ include "keydb.fullname" . }}-headless ${port}")
fi
done
exec keydb-server /etc/keydb/redis.conf \
--active-replica yes \
--multi-master yes \
--appendonly {{ .Values.KEYDB.appendonly }} \
--bind 0.0.0.0 \
--port "$port" \
--protected-mode no \
--server-threads {{ .Values.threads | int }} \
{{- if .Values.KEYDB.existingSecret }}
--masterauth $REDIS_PASSWORD \
--requirepass $REDIS_PASSWORD \
{{- else if .Values.KEYDB.password }}
--masterauth {{ .Values.KEYDB.password }} \
--requirepass {{ .Values.KEYDB.password }} \
{{- end }}
{{- range $key, $value := .Values.KEYDB.configExtraArgs }}
{{- if $value }}
--{{ $key }} {{ $value }} \
{{- else }}
--{{ $key }} \
{{- end }}
{{- end }}
"${replicas[@]}"
描述:
我收到上述错误,不知道如何解决。我到底做错了什么?
感谢您的早期反应。
赛义德
解决方案
Go 文本/模板range
运算符重新绑定.
特殊变量,在本例中为循环索引。在您的顶级模板中,您有:
{{- range $podIndex := until $numOfInstances }}
...
labels:
{{ include "keydb.labels" . | nindent 8 }}
...
{{- end }}
在这个上下文.
中是循环索引,而不是顶级 Helm 对象。当该参数被传递到内部模板时,您最终会尝试解析.Values.something
,但由于.
是循环索引,因此您无法Values
在其上查找字段。
从机械上讲,确保一切都使用特殊$
变量可能会非常严格。你在这个模板的很多地方都这样做了,但不是在所有地方;确保引用$.Values
而不仅仅是.Values
,并传递$
给模板而不是.
.
但是:从 Kubernetes 的角度来看,这里的结构有点奇怪。特别是,创建裸 Pod 是不寻常的;它们无法就地更新,并且如果计划它们的节点终止,您将不得不手动重新创建它们。阅读该 Pod 规范,您正在创建一系列 Pod,每个 Pod 都有一个序列号,每个都有自己的存储空间。这正是 Kubernetes StatefulSet为您提供的。
如果你改用StatefulSet,你可以摆脱range
循环,使用“普通”.Values
和.
变量而无需任何特殊处理;您无需担心$
(在任何内部range
或with
块之外)。
{{/* no outer range loop */}}
apiVersion: apps/v1
kind: StatefulSet
metadata: { ... }
spec:
replicas: {{ .Values.CP.replicas }}
...
如果您从 pod 索引构建环境变量,您将无法纯粹在 Kubernetes YAML 层执行此操作,但服务会将其主机名(8) 视为 pod 名称,其格式为statefulset-name-0
; 如果尚未设置,您可以使用 Docker 入口点包装脚本将环境变量设置为主机名。