无法读取EKS中由CDK蓝印创建的嵌套Kubernetes Secret
解决EKS Blueprints创建的嵌套结构Secret无法被Pod引用的问题
问题根源
通过blueprints.LookupSecretsManagerSecretByName创建的Kubernetes Secret,默认会将AWS Secrets Manager中的整个秘密内容以base64编码的JSON字符串形式存储在单个secret键下,而非将密钥键值对平铺为K8s Secret的data/stringData字段。这和手动创建的常规Secret结构存在差异,导致直接引用会提示密钥不存在。
你可以通过以下命令确认Secret结构:
kubectl get secret test-aws-secret -o yaml
典型的嵌套结构如下:
apiVersion: v1 kind: Secret metadata: name: test-aws-secret type: Opaque data: secret: <base64编码的完整JSON字符串>
解决方案
方案1:修改Pod配置,解析嵌套JSON
如果不想调整CDK配置,可以在Pod中通过init容器或启动命令解析嵌套的JSON内容。
方式A:使用Init容器提取密钥到单独文件
通过init容器解码并解析JSON,将每个密钥提取到独立文件,供业务容器读取:
apiVersion: v1 kind: Pod metadata: name: my-app-pod spec: containers: - name: app-container image: your-app-image volumeMounts: - name: parsed-secrets mountPath: /app/secrets readOnly: true # 可在启动命令中读取文件内容 command: ["sh", "-c", "DB_USER=$(cat /app/secrets/DB_USER) && DB_PASS=$(cat /app/secrets/DB_PASS) && exec your-app"] initContainers: - name: parse-secret image: busybox:1.36 command: ["sh", "-c"] args: - | # 解码嵌套的secret字段并解析JSON SECRET_JSON=$(echo $(cat /raw-secrets/secret) | base64 -d) # 将每个密钥写入单独文件 echo "$SECRET_JSON" | jq -r '.DB_USER' > /parsed-secrets/DB_USER echo "$SECRET_JSON" | jq -r '.DB_PASS' > /parsed-secrets/DB_PASS volumeMounts: - name: raw-secrets mountPath: /raw-secrets readOnly: true - name: parsed-secrets mountPath: /parsed-secrets volumes: - name: raw-secrets secret: secretName: test-aws-secret - name: parsed-secrets emptyDir: {}
方式B:在容器启动命令中直接解析
如果容器镜像内置jq和base64工具,可直接在启动命令中解析:
apiVersion: v1 kind: Pod metadata: name: my-app-pod spec: containers: - name: app-container image: your-app-image command: ["sh", "-c"] args: - | # 解码并提取密钥 SECRET_JSON=$(echo $SECRET_RAW | base64 -d) export DB_USER=$(echo "$SECRET_JSON" | jq -r '.DB_USER') export DB_PASS=$(echo "$SECRET_JSON" | jq -r '.DB_PASS') # 启动应用 exec your-app-command env: - name: SECRET_RAW valueFrom: secretKeyRef: name: test-aws-secret key: secret
方案2:调整CDK配置,生成平铺结构的Secret
更彻底的方式是修改EKS Blueprints的Secret配置,让生成的K8s Secret和手动创建的结构一致,直接将Secrets Manager中的键值对平铺为data字段。
示例CDK代码:
import * as blueprints from '@aws-quickstart/eks-blueprints'; // 自定义SecretProvider,平铺Secrets Manager中的所有键值对 const flatSecretProvider = new blueprints.SecretsManagerSecret('test-aws-secret', { transform: (secretData: Record<string, string>) => { // 直接返回Secrets Manager的键值对,作为K8s Secret的data字段 return secretData; } }); // 在EKS Blueprint中配置Secrets Store AddOn const blueprint = blueprints.EksBlueprint.builder() .addOns(new blueprints.SecretsStoreAddOn({ secrets: [flatSecretProvider] })) // 其他集群配置... .build(app, 'your-eks-cluster');
配置完成后,重新部署CDK栈,生成的Secret结构会和手动创建的一致:
apiVersion: v1 kind: Secret metadata: name: test-aws-secret type: Opaque data: DB_USER: <base64编码的admin> DB_PASS: <base64编码的xxx>
此时Pod即可通过常规的secretKeyRef直接引用:
env: - name: DB_USER valueFrom: secretKeyRef: name: test-aws-secret key: DB_USER
内容的提问来源于stack exchange,提问作者Buvana
相关产品推荐
相关产品推荐

