【Kubernetes】Secret配置管理,安全管理敏感配置

【Kubernetes实践】Secret详解:安全管理敏感配置的完整指南

在Kubernetes集群中,我们经常需要处理数据库密码、API密钥、证书等敏感信息。如果将这些信息直接硬编码到Pod定义或镜像中,会带来严重的安全风险。Secret作为Kubernetes专门用于存储敏感信息的资源对象,能帮助我们安全地管理这些数据。

一、什么是Secret?

Secret是Kubernetes中用于存储敏感配置数据的资源类型,与ConfigMap类似,但专门用于处理密码、令牌、密钥等需要保密的信息。其核心特点包括:

  • 数据会被Base64编码存储(注意:这只是简单编码,并非加密,真正的加密需结合RBAC权限控制或第三方密钥管理系统)
  • 可以被Pod挂载为文件或注入为环境变量
  • 与ConfigMap一样支持"配置与代码分离",但更侧重敏感信息的安全管理

简单说,Secret就像一个"加密的配置文件仓库",专门存放需要保密的信息。

二、创建Secret的4种常用方式

1. 从文件创建(适用于证书、密钥文件)

如果敏感信息已存储在文件中(如SSL证书、密钥文件),可以直接从文件创建Secret:

bash 复制代码
# 准备敏感文件(示例:数据库密码文件和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:

bash 复制代码
kubectl describe secret app-secrets

输出显示Secret包含两个key(对应文件名):

复制代码
Name:         app-secrets
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
api-key.txt:  14 bytes  # 文件名作为key
db-pass.txt:  13 bytes  # 文件名作为key

2. 直接指定键值对创建(适用于简单敏感信息)

对于简单的敏感键值对(如用户名和密码),可以用--from-literal直接创建:

bash 复制代码
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password='P@ssw0rd!2025'  # 密码含特殊字符时用单引号包裹

查看Secret详情(注意:默认不显示具体值,需用-o yaml查看编码后的值):

bash 复制代码
kubectl get secret db-credentials -o yaml

输出中data字段显示Base64编码后的值:

yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
data:
  password: UEBzc3cwcmQhMjAyNQ==  # 编码后的密码
  username: YWRtaW4=              # 编码后的用户名
type: Opaque

如果需要验证编码内容,可以用Base64解码:

bash 复制代码
echo "UEBzc3cwcmQhMjAyNQ==" | base64 -d  # 输出:P@ssw0rd!2025

3. 从环境变量文件创建(适用于多环境变量)

如果有多个环境变量形式的敏感信息,可以先写入.env文件,再从文件创建Secret:

bash 复制代码
# 创建.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):

bash 复制代码
kubectl describe secret env-secrets

4. 通过YAML文件创建(适合版本控制)

对于需要纳入版本控制的Secret定义(注意:YAML中需填写Base64编码后的值),可以手动编写YAML文件:

yaml 复制代码
# secret-demo.yaml
apiVersion: v1
kind: Secret
metadata:
  name: yaml-secret
type: Opaque
data:
  # 注意:值必须是Base64编码后的结果
  ftp-user: YWRtaW4=  # 对应明文:admin
  ftp-pass: Zm9vcGVzc3dvcmQ=  # 对应明文:foopassword

创建Secret:

bash 复制代码
kubectl apply -f secret-demo.yaml

三、在Pod中使用Secret的3种方式

创建Secret后,Pod可以通过环境变量注入文件挂载镜像拉取密钥三种方式使用其中的敏感信息。

方式1:作为环境变量注入

适用于应用通过环境变量读取敏感信息的场景(如数据库连接参数)。

创建引用Secret的Pod定义(secret-env-pod.yaml):

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: secret-test
    image: alpine
    command: ["/bin/sh", "-c", "env | grep DB_; sleep 3600"]  # 输出含DB_的环境变量
    env:
    - name: DB_USER  # 容器内的环境变量名
      valueFrom:
        secretKeyRef:
          name: db-credentials  # 关联的Secret名称
          key: username         # 引用的key
    - name: DB_PASS
      valueFrom:
        secretKeyRef:
          name: db-credentials
          key: password
  restartPolicy: Never

创建Pod并验证:

bash 复制代码
# 创建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):

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: secret-file-pod
spec:
  containers:
  - name: secret-test
    image: alpine
    command: ["/bin/sh", "-c", "sleep 3600"]  # 休眠等待查看
    volumeMounts:
    - name: secret-volume  # 与下面的volume名称对应
      mountPath: /etc/secrets  # 挂载到容器内的路径
      readOnly: true  # 敏感文件建议设为只读
  volumes:
  - name: secret-volume
    secret:
      secretName: app-secrets  # 关联的Secret名称
      # 可选:只挂载部分key(不指定则挂载全部)
      items:
      - key: db-pass.txt
        path: db/password  # 挂载到/etc/secrets/db/password
      - key: api-key.txt
        path: api/key      # 挂载到/etc/secrets/api/key
  restartPolicy: Never

创建Pod并验证:

bash 复制代码
# 创建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
bash 复制代码
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中引用镜像拉取密钥
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: private-reg-pod
spec:
  containers:
  - name: private-app
    image: your-registry.example.com/your-image:latest  # 私有仓库镜像
  imagePullSecrets:
  - name: registry-creds  # 引用上面创建的Secret

这样Kubernetes会使用该Secret中的凭证拉取私有仓库的镜像。

四、Secret与ConfigMap的核心区别

特性 Secret ConfigMap
用途 存储敏感信息(密码、密钥等) 存储非敏感配置(普通参数)
存储方式 Base64编码(非加密) 明文存储
访问控制 支持更严格的权限控制 权限控制较宽松
大小限制 建议不超过1MB 建议不超过1MB
典型场景 数据库密码、API密钥、证书 应用配置文件、普通参数

五、安全使用Secret的最佳实践

  1. 最小权限原则:通过RBAC限制Secret的访问权限,只允许必要的Pod或用户访问
  2. 避免明文暴露 :不要用kubectl describe查看Secret内容(会显示data字段但不显示值),需用-o yaml并注意解码后的信息安全
  3. 加密存储 :在生产环境,建议启用Kubernetes的静态加密功能,确保etcd中存储的Secret被加密
  4. 定期轮换:敏感凭证(如数据库密码)应定期更新,并通过滚动更新Pod使新的Secret生效
  5. 避免提交到代码库:包含Secret的YAML文件(尤其是解码后的值)不要提交到版本控制系统