使用Helm部署Kubernetes Secret报base64解码错误如何排查
问题场景
通过GitLab流水线在AKS集群执行首次Helm发布,执行命令如下:
- helm upgrade server ./aks/server --install --namespace demo --kubeconfig ${CI_PROJECT_DIR}/.kube/config --set image.name=${CI_PROJECT_NAME}/${CI_PROJECT_NAME}-server --set image.tag=${CI_COMMIT_SHA} --set database.user=${POSTGRES_USER} --set database.password=${POSTGRES_PASSWORD}
执行过程中返回报错:
Error: Secret in version "v1" cannot be handled as a Secret: v1.Secret.Data: decode base64: illegal base64 data at input byte 8, error found in #10 byte of ...
涉及的配置模板如下:
secret.yaml
apiVersion: v1 kind: Secret metadata: name: server-secret namespace: demo type: Opaque data: User: {{ .Values.database.user }} Host: {{ .Values.database.host }} Database: {{ .Values.database.name }} Password: {{ .Values.database.password }} Port: {{ .Values.database.port }}
deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: {{ .Values.app.name }} labels: app: {{ .Values.app.name }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: tier: backend stack: node app: {{ .Values.app.name }} template: metadata: labels: tier: backend stack: node app: {{ .Values.app.name }} spec: containers: - name: {{ .Values.app.name }} image: "{{ .Values.image.name }}:{{ .Values.image.tag }}" imagePullPolicy: IfNotPresent env: - name: User valueFrom: secretKeyRef: name: server-secret key: User optional: false - name: Host valueFrom: secretKeyRef: name: server-secret key: Host optional: false - name: Database valueFrom: secretKeyRef: name: server-secret key: Database optional: false - name: Password valueFrom: secretKeyRef: name: server-secret key: Password optional: false - name: Ports valueFrom: secretKeyRef: name: server-secret key: Ports optional: false resources: limits: cpu: "1" memory: "128M" ports: - containerPort: 3000
service.yaml
apiVersion: v1 kind: Service metadata: name: server-service spec: type: ClusterIP selector: tier: backend stack: node app: {{ .Values.app.name }} ports: - protocol: TCP port: 3000 targetPort: 3000
排查思路
- 从报错信息定位核心异常:提示Secret的Data字段base64解码失败,优先核查Secret模板data字段的赋值是否符合Kubernetes资源规范
- 核对Secret规则:Kubernetes中Opaque类型Secret的
data字段要求所有值必须是base64编码格式,不支持直接传入明文内容 - 渲染模板验证:本地执行
helm template ./aks/server输出最终渲染的Kubernetes资源清单,可确认Secret中直接传入了数据库账号、密码、端口等明文字段,未做编码处理 - 校验配置引用一致性:对比Deployment中secretKeyRef引用的键名和Secret定义的键名,发现Deployment引用
Ports键,但Secret中定义的键名为Port,存在拼写不一致问题,会导致后续Pod启动失败
解决方案
两种修复方案二选一即可,修复后同步修正键名拼写错误:
方案1:保留data字段,通过Helm内置函数自动编码
修改secret.yaml模板,对data下所有值调用b64enc模板函数完成base64编码,同时将Port键名改为Ports匹配Deployment引用:
apiVersion: v1 kind: Secret metadata: name: server-secret namespace: demo type: Opaque data: User: {{ .Values.database.user | b64enc }} Host: {{ .Values.database.host | b64enc }} Database: {{ .Values.database.name | b64enc }} Password: {{ .Values.database.password | b64enc }} Ports: {{ .Values.database.port | b64enc }}
方案2:使用stringData字段直接传入明文(Kubernetes 1.14及以上版本支持)
Kubernetes提供stringData字段专门接收明文字符串,集群侧会自动完成base64编码,无需手动处理编码逻辑,同样需要修正键名:
apiVersion: v1 kind: Secret metadata: name: server-secret namespace: demo type: Opaque stringData: User: {{ .Values.database.user }} Host: {{ .Values.database.host }} Database: {{ .Values.database.name }} Password: {{ .Values.database.password }} Ports: {{ .Values.database.port }}
修复验证
本地执行helm template ./aks/server检查渲染后的资源清单,确认Secret配置无语法错误、键名匹配后,重新触发流水线执行Helm发布即可。
内容的提问来源于stack exchange,提问作者Salvatore Calla'
相关产品推荐
相关产品推荐

