介绍
Secret 用于存储和管理敏感信息,如数据库密码、API 密钥、TLS 证书等。与 ConfigMap 不同,Secret 提供 base64 编码(注意:非加密),并应配合 Kubernetes RBAC 和加密配置使用。
为什么用 Secret?
- ✅ 安全分离:敏感数据不硬编码在 Dockerfile 或 YAML 中
- ✅ 细粒度权限:通过 RBAC 控制哪些应用可以读取 Secret
- ✅ 动态更新:Secret 更新后可选择是否重启 Pod 生效
- ✅ 多种使用方式:环境变量、文件挂载、镜像拉取密钥
快速开始
创建 Secret
支持三种方式:
方式 1:通过 UI 表单(推荐新手)
- 进入 开发者界面 → 配置管理 → 保密字典
- 点击 新建 Secret
- 选择数据类型:
- 键值对:简单字段,如
password=xxx - 文件:上传文件内容(如 TLS 证书)
- 键值对:简单字段,如
- 填写字段,点击 添加
方式 2:通过 kubectl(命令行)
# 创建字面量 Secret
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password='S3cr3t!'
# 从文件创建 Secret(如 TLS)
kubectl create secret generic tls-secret \
--from-file=tls.crt=/path/to/cert.crt \
--from-file=tls.key=/path/to/key.key
方式 3:通过 YAML(高级用户)
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
# base64 编码值
username: YWRtaW4=
password: UzNjcjN0IQ==
使用 Secret
Secret 有三种使用方式:
作为环境变量
- 在 Deployment 的容器配置中添加: ```yaml env:
- name: DB_PASSWORD valueFrom: secretKeyRef: name: db-secret key: password ```
- 在 KDO UI 的环境变量部分选择 从 Secret 添加
作为文件挂载
- 在 Deployment 的
volumeMounts中挂载: ```yaml volumeMounts:- name: secrets mountPath: /etc/secrets readOnly: true volumes:
- name: secrets secret: secretName: db-secret ```
- KDO UI 存储 → 添加存储 → 选择 Secret
作为镜像拉取密钥 (imagePullSecret)
创建类型为 kubernetes.io/dockerconfigjson 的 Secret:
kubectl create secret docker-registry regcred \
--docker-server=harbor.example.com \
--docker-username=admin \
--docker-password='password'
在 ServiceAccount 或 Deployment 中引用:
imagePullSecrets:
- name: regcred
详细说明
Secret 类型
KDO 支持多种 Secret 类型:
| 类型 | 用途 | 自动创建 |
|---|---|---|
Opaque(默认) | 通用键值对 Secret | ❌ |
kubernetes.io/service-account-token | ServiceAccount Token | ✅(自动) |
kubernetes.io/tls | TLS 证书(crt/key) | ✅(cert-manager) |
kubernetes.io/dockerconfigjson | 镜像仓库认证 | ❌(需手动) |
kubernetes.io/basic-auth | 基础认证(用户名/密码) | ❌ |
kubernetes.io/ssh-auth | SSH 密钥 | ❌ |
数据编码
Secret 的 data 字段值必须是 base64 编码:
echo -n "my-password" | base64
# 输出:bXktcGFzc3dvcmQ=
KDO UI 会自动处理编码,无需手动操作。
常见操作
查看 Secret
- 列表:配置管理 → 保密字典
- 详情:点击 Secret 名称,查看:
- 键值对内容(部分隐藏)
- 使用的命名空间
- 被哪些 Pod 引用
命令行:
kubectl get secrets -n <namespace>
kubectl describe secret <name> -n <namespace>
编辑 Secret
- 进入 Secret 详情页
- 点击 编辑
- 修改键值或添加新字段
- 保存
注意:
- 更新 Secret 后,已运行的 Pod 不会自动更新环境变量
- 文件挂载的 Secret 会定期同步(默认 1 分钟)
- 如需应用立即生效,需重启 Pod
删除 Secret
- 列表页勾选 Secret → 删除
- 或命令行:
kubectl delete secret <name> -n <namespace>
风险: 正在使用该 Secret 的 Pod 可能因无法读取配置而启动失败。
恢复/导出 Secret
# 导出到 YAML
kubectl get secret my-secret -o yaml > my-secret.yaml
# 恢复
kubectl apply -f my-secret.yaml
建议将生产环境 Secret 备份到安全的位置(如加密的 Git 仓库或 Vault)。
最佳实践
安全性
- 🔒 最小权限:仅授予应用必要的 Secret 访问权限(通过 RoleBinding)
- 🔒 定期轮转:尤其是密码类 Secret,定期更换
- 🔒 加密存储:配置 Kubernetes EncryptionConfiguration,对 etcd 中的 Secret 加密
- 🔒 外部 Secret 管理:生产环境集成 HashiCorp Vault、AWS Secrets Manager 等
- 🔒 避免明文:不要在代码或文档中记录 Secret 值
运维管理
- 📝 命名规范:
<app>-<env>-<type>,如mysql-prod-password - 📝 版本控制:将 Secret 定义(不含值)纳入 Git,实际值通过 CI/CD 注入
- 📝 审计日志:开启 Kubernetes Audit Log,记录 Secret 的访问和修改
- 📝 Secret 大小:单个 Secret 不超过 1MB(etcd 限制)
- 📝 使用环境:区分 dev/test/prod 的 Secret,避免混用
常见问题
Q: Secret 和 ConfigMap 如何选择?
| 维度 | Secret | ConfigMap |
|---|---|---|
| 用途 | 敏感信息(密码、密钥、令牌) | 非敏感配置(参数、配置文件) |
| 存储形式 | base64 编码(可配置加密) | 明文 |
| RBAC | 可单独配置访问权限 | 可单独配置访问权限 |
| 性能 | 无差别 | 无差别 |
原则: 任何敏感数据都应使用 Secret,即使是非敏感数据也不强制用 ConfigMap。
Q: Secret 安全吗?
Base64 只是编码,不是加密。默认情况下 Secret 以明文存储在 etcd 中。安全性依赖:
- RBAC:限制用户/应用对 Secret 的
get、list权限 - 网络传输:API Server 通信使用 TLS
- 静态加密:配置
EncryptionConfiguration对 etcd 加密(推荐) - 外部 Secret Store:生产环境使用 Vault 等专业工具
Q: 更新 Secret 后 Pod 没反应?
- 环境变量:不会自动更新,需要重启 Pod
- 文件挂载:Kubelet 默认每分钟检查更新,自动刷新文件
- 如果应用不感知文件变化(如配置文件已加载到内存),需重启应用
- 解决方案:
- 使用 Reloader 工具监听 Secret 变更并自动重启 Pod
- 应用设计支持热重载(如 Nginx
nginx -s reload)
Q: Secret 大小有限制吗?
- 单个 Secret 不超过 1 MB(etcd 限制)
- 一个命名空间所有 Secret 总和不超过集群 etcd 容量
- 对于大文件(如证书链),建议使用 Volume 挂载外部 Secret 或 ConfigMap
Q: 如何查看 Secret 的值?
# 查看所有字段(base64 解码)
kubectl get secret my-secret -o jsonpath='{.data}'
kubectl get secret my-secret -o jsonpath='{.data.password}' | base64 --decode
# 以 YAML 输出
kubectl get secret my-secret -o yaml
权限要求: 用户必须有 get 权限,且能访问该 Secret 所在命名空间。