当前位置: 首页 > news >正文

别再把密码写进代码,用 Secret 安全存储 Kubernetes 中的密钥

概述

你有没有这样写过代码?

# 危险!绝对不要这样做!env:-name:DB_PASSWORDvalue:"mySuperSecret123!"

或者把 API Key 直接打包进 Docker 镜像?

在 Kubernetes 中,这类敏感信息(密码、Token、证书等)应该用Secret来管理。

什么是 Secret

Secret是 Kubernetes 的一种资源对象,专门用于:

  • 存储敏感数据,如:
    • 数据库密码
    • OAuth Token
    • TLS 证书私钥
    • 第三方 API 密钥
  • 将敏感信息与应用代码/镜像解耦
  • 通过 RBAC 控制访问权限

核心原则:敏感信息绝不硬编码,绝不进 Git,绝不进镜像!

Secret vs ConfigMap

特性ConfigMapSecret
用途非敏感配置(日志级别、开关)敏感信息(密码、密钥)
存储格式明文(YAML 中直接可见)Base64 编码(非加密!)
默认权限所有 Pod 可读(需显式引用)同左,但可通过 RBAC 限制
安全性(需配合其他措施)

说明:
Secret 并不是“加密存储”!它只是 Base64 编码(可轻松解码)。
真正的安全依赖于:

  • etcd 启用加密(集群管理员配置)
  • 严格的 RBAC 权限控制
  • 不将 Secret 写入日志或输出

创建 Secret 的三种方式

方式 1:从字面值创建(适合少量密钥)

kubectl create secret generic db-secret\--from-literal=username=admin\--from-literal=password='S3cr3tP@ss!'

查看内容(注意:会显示 Base64 编码):

kubectl get secret db-secret-oyaml

输出片段:

data:username:YWRtaW4=# echo -n "admin" | base64password:UzNjcjN0UEBzc2Eh# echo -n "S3cr3tP@ss!" | base64

你可以用echo "UzNjcjN0UEBzc2Eh" | base64 -d解码回原文

方式 2:从文件创建(适合证书、密钥文件)

假设你有:

  • tls.key(私钥)
  • tls.crt(证书)

创建 Secret:

kubectl create secret tls my-tls-secret\--cert=tls.crt\--key=tls.key

这是创建 HTTPS 证书 Secret 的标准方式

方式 3:从 YAML 文件定义(最灵活,推荐)

创建secret.yaml

apiVersion:v1kind:Secretmetadata:name:app-secretstype:Opaque# 默认类型,用于通用密钥data:# 注意:必须是 Base64 编码!database_password:UzNjcjN0UEBzc2Ehapi_key:QVBJLTIwMjQtMTIzNDU2Nzg5MAo=

或者用stringData(自动编码,更友好):

apiVersion:v1kind:Secretmetadata:name:app-secretstype:OpaquestringData:# 直接写明文,K8s 自动转 Base64database_password:"S3cr3tP@ss!"api_key:"API-2024-1234567890"

强烈推荐用stringData!避免手动编码出错。

应用:

kubectl apply-fsecret.yaml

在 Pod 中使用 Secret

场景 1:作为环境变量注入(简单但有风险)

# deployment-env.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:my-appspec:template:spec:containers:-name:appimage:my-app:1.0env:-name:DB_PASSWORDvalueFrom:secretKeyRef:name:app-secretskey:database_password

注意:如果应用打印环境变量(如调试日志),密码会泄露

场景 2:挂载为文件(更安全,推荐)

# deployment-volume.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:secure-appspec:template:spec:containers:-name:appimage:my-app:1.0volumeMounts:-name:secret-volumemountPath:"/etc/secrets"readOnly:true# 必须只读!volumes:-name:secret-volumesecret:secretName:app-secrets

效果:

  • 容器内/etc/secrets/database_password文件内容 = 密码原文
  • 应用通过读文件获取密码(如fs.readFileSync('/etc/secrets/database_password')

优势

  • 不会出现在环境变量中
  • 文件权限默认为644,只有容器内进程可读
  • 更符合安全最佳实践

实战:部署一个连接数据库的 Python 应用

Step 1:创建 Secret

db-secret.yaml

apiVersion:v1kind:Secretmetadata:name:postgres-credentialstype:OpaquestringData:username:"app_user"password:"My$tr0ngP@ss!"

Step 2:编写 Deployment(挂载为文件)

python-app.yaml

apiVersion:apps/v1kind:Deploymentmetadata:name:python-db-appspec:replicas:1selector:matchLabels:app:python-dbtemplate:metadata:labels:app:python-dbspec:containers:-name:appimage:python:3.9-slimcommand:["sh","-c"]args:-|USERNAME=$(cat /etc/secrets/username) PASSWORD=$(cat /etc/secrets/password) echo "Connecting to DB as $USERNAME..." # 这里可以写真实连接逻辑 sleep 3600volumeMounts:-name:secret-volmountPath:"/etc/secrets"readOnly:truevolumes:-name:secret-volsecret:secretName:postgres-credentials

Step 3:部署并验证

kubectl apply-fdb-secret.yaml kubectl apply-fpython-app.yaml# 查看日志(不应出现密码!)kubectl logs-lapp=python-db

输出:

Connecting to DB as app_user...

最佳实践

建议说明
✅ 使用stringData创建 Secret避免手动 Base64
✅ 挂载为文件而非环境变量减少泄露风险
✅ 设置readOnly: true防止应用意外修改
✅ 限制 RBAC 权限只允许必要服务账户读取
✅ 启用 etcd 加密(集群级)防止磁盘泄露(需管理员操作)
❌ 不要kubectl get secret -o yaml后截图发群里!Base64 很容易解码
❌ 不要把 Secret 提交到 Git即使是私有仓库也不行!

终极建议:生产环境考虑使用外部密钥管理服务(如 HashiCorp Vault、AWS Secrets Manager),Secret 仅作临时中转。

常见问题

1:Secret 是加密的,所以是安全的

实际只是 Base64 编码!真正的安全靠 etcd 加密 + RBAC。

2:用了 Secret 就万无一失吗?

→ 如果应用把密码打印到日志,照样泄露!安全是体系工程。

说明:
Secret 是 Kubernetes 提供的“敏感信息传递机制”,不是“保险箱”
它解决了“如何不把密码写进代码”的问题,但不能替代整体安全策略

总结

问题Secret 解法
密码写死在 YAML?✅ 外部化为 Secret
镜像包含 API Key?✅ 运行时注入
多环境密钥混乱?✅ 创建prod-secrets/staging-secrets
团队共享密码?✅ 通过 RBAC 控制访问
http://www.cnnetsun.cn/news/1465235.html

相关文章:

  • 【chap10-贪心算法】用Python3刷《代码随想录》
  • 企业网络改造案例:当财务部和市场部需要同网段但隔离怎么办?
  • Qwen3-VL-Reranker-8B实战落地:医疗影像报告+CT图片+视频检查结果融合检索
  • 从原理到PCB:一个共模电感是如何“扼杀”EMI干扰的?用仿真+实测带你搞懂
  • B站评论区成分检测器:智能用户画像分析工具
  • 别再到处找了!这5个免费免登录的AI工具,帮你搞定从画图到写代码
  • BEYOND REALITY Z-Image实际效果:多光源混合布光下皮肤漫反射真实模拟
  • Llama-3.2V-11B-cot部署教程:解决视觉权重加载致命Bug的实操步骤
  • MediaCrawler:智能多媒体采集系统的技术架构与实践指南
  • Qwen3Guard-Gen-8B应用实战:5分钟搭建企业级AI内容审核系统,Web界面全搞定
  • opencode教育场景落地:学生编程辅导系统部署实战
  • GLM-4.7-Flash智能助手:高校教务系统课程咨询与排课冲突解答
  • Qwen3-VL-8B应用案例:一键提取图片中的文字,告别手动打字
  • 推荐5种情况下的用例书写标准-3
  • 弦音墨影保姆级教程:3步启动水墨风视频理解系统(含素材下载)
  • SenseVoice-small-onnx REST API调试技巧:Postman配置与响应字段解析
  • PETRV2-BEV模型训练实战:基于星图AI算力平台的快速部署与调优
  • Janus-Pro-7B精彩案例:多模态理解辅助盲文教材图像描述生成
  • 2025年AI工程师面试终极通关指南:从算法到架构的全面突破
  • 数字孪生如何在培训仿真中实现“零风险试错”与“降本增效”?
  • 3步掌握PBR材质生成:让3D建模效率提升70%
  • BUUCTF babyrop实战:手把手教你绕过strncmp和构造ROP链(附完整EXP)
  • java毕业设计基于Spring Boot的阳光蛋糕店管理系统
  • 好用的推理训练引擎:博云AIOS如何重塑企业AI算力底座
  • 从卡顿到丝滑:6步解锁Win11Debloat系统优化新体验
  • 全任务零样本学习-mT5中文-base应用场景:大模型红队测试中的对抗性文本生成增强
  • 群晖备份神器Active Backup激活全攻略:从URL构造到状态验证一步不落
  • SDMatte高效抠图手册:复杂背景人像外物分离、发丝级保留实操步骤
  • STM32H7高性能模拟库:突破Arduino ADC/DAC/I2S极限
  • SOONet效果展示:同一查询在不同光照/角度/分辨率视频中的鲁棒性测试