【Kubernetes】Secret配置管理,安全管理敏感配置
【Kubernetes实践】Secret详解:安全管理敏感配置的完整指南
在Kubernetes集群中,我们经常需要处理数据库密码、API密钥、证书等敏感信息。如果将这些信息直接硬编码到Pod定义或镜像中,会带来严重的安全风险。Secret作为Kubernetes专门用于存储敏感信息的资源对象,能帮助我们安全地管理这些数据。
一、什么是Secret?
Secret是Kubernetes中用于存储敏感配置数据的资源类型,与ConfigMap类似,但专门用于处理密码、令牌、密钥等需要保密的信息。其核心特点包括:
- 数据会被Base64编码存储(注意:这只是简单编码,并非加密,真正的加密需结合RBAC权限控制或第三方密钥管理系统)
- 可以被Pod挂载为文件或注入为环境变量
- 与ConfigMap一样支持“配置与代码分离”,但更侧重敏感信息的安全管理
简单说,Secret就像一个“加密的配置文件仓库”,专门存放需要保密的信息。
二、创建Secret的4种常用方式
1. 从文件创建(适用于证书、密钥文件)
如果敏感信息已存储在文件中(如SSL证书、密钥文件),可以直接从文件创建Secret:
# 准备敏感文件(示例:数据库密码文件和API密钥文件)
echo -n "dbpassword123" > db-pass.txt # 注意用-n避免添加换行符
echo -n "apikey-xxxx-yyyy" > api-key.txt# 从文件创建Secret(文件名默认作为key,文件内容作为value)
kubectl create secret generic app-secrets --from-file=db-pass.txt --from-file=api-key.txt
查看创建的Secret:
kubectl describe secret app-secrets
输出显示Secret包含两个key(对应文件名):
Name: app-secrets
Namespace: default
Labels: <none>
Annotations: <none>Type: OpaqueData
====
api-key.txt: 14 bytes # 文件名作为key
db-pass.txt: 13 bytes # 文件名作为key
2. 直接指定键值对创建(适用于简单敏感信息)
对于简单的敏感键值对(如用户名和密码),可以用--from-literal
直接创建:
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password='P@ssw0rd!2025' # 密码含特殊字符时用单引号包裹
查看Secret详情(注意:默认不显示具体值,需用-o yaml
查看编码后的值):
kubectl get secret db-credentials -o yaml
输出中data
字段显示Base64编码后的值:
apiVersion: v1
kind: Secret
metadata:name: db-credentials
data:password: UEBzc3cwcmQhMjAyNQ== # 编码后的密码username: YWRtaW4= # 编码后的用户名
type: Opaque
如果需要验证编码内容,可以用Base64解码:
echo "UEBzc3cwcmQhMjAyNQ==" | base64 -d # 输出:P@ssw0rd!2025
3. 从环境变量文件创建(适用于多环境变量)
如果有多个环境变量形式的敏感信息,可以先写入.env文件,再从文件创建Secret:
# 创建.env文件
cat > secrets.env << EOF
DB_HOST=mysql-service
DB_USER=root
DB_PASS=SecurePass123
EOF# 从.env文件创建Secret(自动解析为键值对)
kubectl create secret generic env-secrets --from-env-file=secrets.env
查看创建的Secret,会自动解析出3个key(DB_HOST、DB_USER、DB_PASS):
kubectl describe secret env-secrets
4. 通过YAML文件创建(适合版本控制)
对于需要纳入版本控制的Secret定义(注意:YAML中需填写Base64编码后的值),可以手动编写YAML文件:
# secret-demo.yaml
apiVersion: v1
kind: Secret
metadata:name: yaml-secret
type: Opaque
data:# 注意:值必须是Base64编码后的结果ftp-user: YWRtaW4= # 对应明文:adminftp-pass: Zm9vcGVzc3dvcmQ= # 对应明文:foopassword
创建Secret:
kubectl apply -f secret-demo.yaml
三、在Pod中使用Secret的3种方式
创建Secret后,Pod可以通过环境变量注入、文件挂载、镜像拉取密钥三种方式使用其中的敏感信息。
方式1:作为环境变量注入
适用于应用通过环境变量读取敏感信息的场景(如数据库连接参数)。
创建引用Secret的Pod定义(secret-env-pod.yaml
):
apiVersion: v1
kind: Pod
metadata:name: secret-env-pod
spec:containers:- name: secret-testimage: alpinecommand: ["/bin/sh", "-c", "env | grep DB_; sleep 3600"] # 输出含DB_的环境变量env:- name: DB_USER # 容器内的环境变量名valueFrom:secretKeyRef:name: db-credentials # 关联的Secret名称key: username # 引用的key- name: DB_PASSvalueFrom:secretKeyRef:name: db-credentialskey: passwordrestartPolicy: Never
创建Pod并验证:
# 创建Pod
kubectl apply -f secret-env-pod.yaml# 查看环境变量(确认Secret的敏感信息已注入)
kubectl logs secret-env-pod
输出显示环境变量已正确注入:
DB_USER=admin
DB_PASS=P@ssw0rd!2025
方式2:作为文件挂载到容器
适用于应用通过配置文件读取敏感信息的场景(如证书文件、密钥文件)。
创建挂载Secret的Pod定义(secret-file-pod.yaml
):
apiVersion: v1
kind: Pod
metadata:name: secret-file-pod
spec:containers:- name: secret-testimage: alpinecommand: ["/bin/sh", "-c", "sleep 3600"] # 休眠等待查看volumeMounts:- name: secret-volume # 与下面的volume名称对应mountPath: /etc/secrets # 挂载到容器内的路径readOnly: true # 敏感文件建议设为只读volumes:- name: secret-volumesecret:secretName: app-secrets # 关联的Secret名称# 可选:只挂载部分key(不指定则挂载全部)items:- key: db-pass.txtpath: db/password # 挂载到/etc/secrets/db/password- key: api-key.txtpath: api/key # 挂载到/etc/secrets/api/keyrestartPolicy: Never
创建Pod并验证:
# 创建Pod
kubectl apply -f secret-file-pod.yaml# 进入容器查看挂载的文件
kubectl exec -it secret-file-pod -- sh# 在容器内查看
cd /etc/secrets
ls -l # 会看到db和api两个目录
cat db/password # 输出:dbpassword123
cat api/key # 输出:apikey-xxxx-yyyy
特点:
- 挂载的文件内容会自动解码(直接显示明文)
- 文件权限为644(可通过
defaultMode
调整,如0400
表示仅所有者可读) - Secret更新后,挂载的文件内容会自动同步(约1分钟延迟)
方式3:作为镜像拉取密钥(用于私有仓库)
当需要从私有镜像仓库拉取镜像时,可以用Secret存储仓库的认证信息:
步骤1:创建存储镜像仓库凭证的Secret
kubectl create secret docker-registry registry-creds \
--docker-server=your-registry.example.com \ # 私有仓库地址
--docker-username=your-username \ # 用户名
--docker-password=your-password \ # 密码
--docker-email=your-email@example.com # 邮箱(可选)
步骤2:在Pod中引用镜像拉取密钥
apiVersion: v1
kind: Pod
metadata:name: private-reg-pod
spec:containers:- name: private-appimage: your-registry.example.com/your-image:latest # 私有仓库镜像imagePullSecrets:- name: registry-creds # 引用上面创建的Secret
这样Kubernetes会使用该Secret中的凭证拉取私有仓库的镜像。
四、Secret与ConfigMap的核心区别
特性 | Secret | ConfigMap |
---|---|---|
用途 | 存储敏感信息(密码、密钥等) | 存储非敏感配置(普通参数) |
存储方式 | Base64编码(非加密) | 明文存储 |
访问控制 | 支持更严格的权限控制 | 权限控制较宽松 |
大小限制 | 建议不超过1MB | 建议不超过1MB |
典型场景 | 数据库密码、API密钥、证书 | 应用配置文件、普通参数 |
五、安全使用Secret的最佳实践
- 最小权限原则:通过RBAC限制Secret的访问权限,只允许必要的Pod或用户访问
- 避免明文暴露:不要用
kubectl describe
查看Secret内容(会显示data字段但不显示值),需用-o yaml
并注意解码后的信息安全 - 加密存储:在生产环境,建议启用Kubernetes的静态加密功能,确保etcd中存储的Secret被加密
- 定期轮换:敏感凭证(如数据库密码)应定期更新,并通过滚动更新Pod使新的Secret生效
- 避免提交到代码库:包含Secret的YAML文件(尤其是解码后的值)不要提交到版本控制系统