Akemi

Helm labels渲染bug

2025/06/25

这个故障我没有去issue里找,但是大概率是bug了

故障背景与现象

在一个父子chart结构的helm工程中,原本有两个老的子chart,mysql与redis,它俩自己是没问题的

后面准备新加minio服务作为依赖项加入chart,我就找了个比较新的minio chart 16.0.10版本,25年4月22的,相当新了

1
2
3
4
5
依赖项配置:
- name: minio
version: 16.0.10
repository: "file://./charts/minio"
condition: minio.enabled

结果调了一下参数,部署之后发现每次调整父values文件中的minio.enabled,都会导致已经部署完的mysql与redis被重建

排查与恢复

  • 使用tempalte模拟minio.enabled=false与true的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
helm template ./ -f values.yaml --set minio.enabled=true > enabled.yaml
helm template ./ -f values.yaml --set minio.enabled=false > disabled.yaml

然后使用vscode的对比功能对比一下,发现开启和关闭minio时,redis与mysql的labels都会变化
由此导致的服务被重建

开启前:
labels:
app.kubernetes.io/instance: release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: mysql
helm.sh/chart: mysql-9.12.0
开启后:
labels:
app.kubernetes.io/instance: release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: mysql
helm.sh/chart: mysql-9.12.0
app.kubernetes.io/version: 8.0.34

那么这个多出来的labels是从哪来的呢,这类labels的使用者基本都是子chart的secret或者sa的模板文件,在这些文件中找到了一个字段common.labels.standard

1
2
3
4
5
6
7
8
9
10
11
12
13
这是一个非常普遍的sa模板
{{- if and .Values.serviceAccount.create (and (not .Values.master.serviceAccount.create) (not .Values.replica.serviceAccount.create)) }}
apiVersion: v1
kind: ServiceAccount
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
metadata:
name: {{ template "redis.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
labels: {{- include "common.labels.standard" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
...
  • 寻找字段common.labels.standard

此时我还以为是mysql与redis的问题,意图找到common.labels.standard的位置并且将其修改为服务版本,那应该就行了

最终找到是在子chart下common/templates/_labels.tpl文件中定义的

1
2
3
4
grep -r 'common.labels.standard' | grep defin
charts/redis/charts/common/templates/_labels.tpl:{{- define "common.labels.standard" -}}
charts/mysql/charts/common/templates/_labels.tpl:{{- define "common.labels.standard" -}}
charts/minio/charts/common/templates/_labels.tpl:{{- define "common.labels.standard" -}}
  • 发现故障原因

但是当我分别给redis与mysql修改了define字段后,发现还是有问题,并且redis和mysql的version字段都会固定为8.0.34

随后意识到其实是minio的_labels.tpl问题,对比可见,相对于mysql的_labels.tpl,minio的多了version的字段

删除该version字段后恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
minio/charts/common/template/_labels.tpl
...
{{- with .context.Chart.AppVersion -}}
{{- $_ := set $default "app.kubernetes.io/version" . -}}
{{- end -}}
{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }}
{{- else -}}
app.kubernetes.io/name: {{ include "common.names.name" . }}
helm.sh/chart: {{ include "common.names.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- with .Chart.AppVersion }}
app.kubernetes.io/version: {{ . | quote }}
...

mysql/charts/common/template/_labels.tpl
...
{{- else -}}
app.kubernetes.io/name: {{ include "common.names.name" . }}
helm.sh/chart: {{ include "common.names.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}
{{- end -}}

bug说明

正常情况下,helm的子chart只会渲染自己目录下common/template中的那些函数定义文件

但在操作中,发现redis与mysql都会渲染我下载的较新的minio的_labels.tql,多了一个version的labels,让redis和mysql都带上了这个labels

这个labels随着minio打开会出现,关闭就消失,使得每次开关minio都会让redis与mysql重建

CATALOG