第33篇 k8s 之 敏感信息管理:Secret 与安全实践

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。


在第 32 篇中,我们用 ConfigMap 管理了 Flask 应用的配置------FLASK_ENVLOG_LEVELREDIS_HOST。这些都是可以公开查看的非敏感信息。但应用中还有另一类配置:数据库密码、API 密钥、TLS 证书私钥 。这些信息如果像 ConfigMap 一样明文存储和展示,任何一个能执行 kubectl describe configmap 的人都能看到------这是严重的安全隐患。

Kubernetes 为此提供了专门的 Secret 对象。但 Secret 本身只是做了 base64 编码,并非真正的加密。今天这篇,我们不仅要学会 Secret 的创建和注入,更要搞清楚如何让 Secret 真正安全------包括静态加密、RBAC 权限控制,以及如何通过 Sealed Secrets 将加密后的敏感信息安全地存入 Git。

一、Secret 是什么?和 ConfigMap 有什么区别?

Secret 是 K8s 中专门用于存储和管理敏感信息的 API 对象。从操作方式上看,它和 ConfigMap 高度相似------都支持从字面量、文件、YAML 创建,都可以注入为环境变量或挂载为文件。两者最核心的区别在于设计意图和默认安全策略:

重要澄清 :Secret 的 base64 编码不是加密 。在 K8s 集群内部,任何有权限读取 Secret 的人都可以轻松解码。Secret 真正的安全价值在于它与 RBAC 配合可以实现精细的权限隔离,以及配合静态加密(Encryption at Rest)可以保护 etcd 中的敏感数据。在 Docker Compose 时代,密码通常明文写在 .env 文件中,虽然可以加入 .gitignore 避免提交,但在运行环境中仍然以明文环境变量存在。Secret 比这种"约定式"做法更进一步------它在存储层、传输层和访问控制层提供了多层次的保护。

二、Secret 的七种类型

K8s 预定义了多种 Secret 类型,通过 type 字段区分用途:

日常使用中最常见的是 Opaque (通用密码)和 kubernetes.io/tls (TLS 证书)。第 31 篇配置 HTTPS Ingress 时创建的 counter-tls Secret 就是 TLS 类型。

三、创建 Secret 的四种方式

3.1 从字面量创建

bash 复制代码
kubectl create secret generic db-secret \
  --from-literal=username=flaskapp \
  --from-literal=password=MyS3cretP@ss

输出:

验证 Secret 的"半隐藏"特性:

bash 复制代码
kubectl describe secret db-secret
# Name:         db-secret
# Namespace:    default
# Type:         Opaque
# Data
# ====
# password:  13 bytes
# username:  8 bytes

kubectl describe 只显示值的字节数,不显示明文。但要查看明文很容易:

bash 复制代码
kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d
# MyS3cretP@ss

这就是为什么 Secret 本身需要配合 RBAC 权限控制------任何有 get secret 权限的用户都可以解码看到明文。这也是为什么生产环境中需要静态加密和 Sealed Secrets(本章第四部分)来增强安全性。

3.2 从文件创建

bash 复制代码
# 准备文件
echo -n "flaskapp" > username.txt
echo -n "MyS3cretP@ss" > password.txt

kubectl create secret generic db-secret-from-file \
  --from-file=./username.txt \
  --from-file=./password.txt

3.3 声明式 YAML(推荐)

bash 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: db-secret-yaml
type: Opaque
data:
  username: Zmxhc2thcHA=         # "flaskapp" 的 base64 编码
  password: TXlTM2NyZXRQQHNz     # "MyS3cretP@ss" 的 base64 编码

注意 data 字段中的值必须是 base64 编码 。如果你不想手动编码,可以用 stringData 字段(仅用于创建,kubectl get -o yaml 不会显示 stringData):

bash 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: db-secret-string
type: Opaque
stringData:
  username: flaskapp
  password: MyS3cretP@ss

stringData 中的值不需要 base64 编码,K8s 会自动转换。推荐在 YAML 中使用 stringData 提高可读性,但注意这个 YAML 文件本身不应提交到 Git。

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

3.4 使用 kustomization.yaml 管理(进阶)

对于需要管理多个环境 Secret 的场景,Kustomize 提供了更系统的方法:

bash 复制代码
# kustomization.yaml
secretGenerator:
  - name: db-secret
    literals:
      - username=flaskapp
      - password=MyS3cretP@ss

这种方式下,Secret 的值不在最终生成的 YAML 中直接出现,且 Kustomize 会自动为 Secret 名添加哈希后缀,支持 Deployment 自动滚动更新。

四、将 Secret 注入 Pod

和 ConfigMap 一样,Secret 支持三种注入方式。以下是具体的 YAML 写法:

环境变量注入

bash 复制代码
env:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: db-secret
        key: password

一次性注入整个 Secret

bash 复制代码
envFrom:
  - secretRef:
      name: db-secret

文件挂载

bash 复制代码
volumes:
  - name: secret-volume
    secret:
      secretName: db-secret
containers:
  - name: flask
    volumeMounts:
      - name: secret-volume
        mountPath: /app/secrets
        readOnly: true

挂载后,/app/secrets/ 下会为每个键生成一个文件(如 password),文件内容是解码后的明文。readOnly: true 防止容器内进程修改 Secret 数据。

五、Secret 的安全加固

5.1 静态加密

K8s 支持对 etcd 中的 Secret 进行静态加密。这需要在 API Server 中配置 EncryptionConfiguration

bash 复制代码
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-32-byte-key>
      - identity: {}

配置后,新创建的 Secret 会在写入 etcd 前加密,读取时自动解密。这是防止 etcd 备份泄露导致密钥外泄的关键措施。

5.2 RBAC 权限控制

通过 RBAC 限制哪些用户和 ServiceAccount 可以读取 Secret:

bash 复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: secret-reader
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list"]
    resourceNames: ["db-secret"]  # 只允许访问特定 Secret

只授予应用运行所需的 ServiceAccount 最小权限,不开放集群级别的 Secret 列表权限。

5.3 企业级方案:External Secrets Operator 与 CSI Driver

对于需要与外部密钥管理系统(如 AWS Secrets Manager、HashiCorp Vault、Azure Key Vault)集成的生产环境,K8s 社区提供了更安全的方案:

  • External Secrets Operator:将外部密钥管理系统的密钥同步为 K8s Secret,支持定期轮换。

  • Secrets Store CSI Driver:将外部密钥直接挂载为 Pod 的 tmpfs 卷,密钥永远不会以 K8s Secret 形式存储在 etcd 中。

这两类工具解决了密钥生命周期的完整问题------创建、轮换、撤销都可以在外部系统统一管理,K8s 只负责消费。

六、GitOps 安全的 Secret 管理

在 GitOps 工作流中,所有的 K8s 资源 YAML 都存储在 Git 中。但 Secret 的明文绝对不能提交到 Git。解决方案是 Sealed Secrets ------它允许你将 Secret 加密后安全地提交到 Git,只有集群内的控制器可以解密。

部署 Sealed Secrets Controller

bash 复制代码
# 在 Minikube 集群中安装(通过 Helm,第 39 篇会详解)
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets

使用 kubeseal 加密 Secret

bash 复制代码
# 创建普通 Secret(不提交到 Git)
kubectl create secret generic db-secret --from-literal=password=MyS3cretP@ss --dry-run=client -o yaml

# 使用 kubeseal 加密
kubectl create secret generic db-secret --from-literal=password=MyS3cretP@ss --dry-run=client -o yaml | \
  kubeseal --format yaml > db-sealed-secret.yaml

生成的 db-sealed-secret.yaml 中的密码已被加密,可以安全提交到 Git。部署时,Sealed Secrets Controller 自动解密为普通 Secret,Pod 正常使用。这样既遵守了 GitOps 的"Git 是唯一真相来源"原则,又保证了敏感信息的安全性。

七、命令速查表

八、本篇总结

  • Secret vs ConfigMap:Secret 专门存储敏感信息,支持多种预定义类型,配合 RBAC 和静态加密实现多层安全防护。

  • 三种注入方式 :环境变量、envFrom 批量注入、文件挂载(推荐,支持 tmpfs 内存存储)。

  • 安全不是默认的:裸 Secret 只是 base64 编码。生产环境必须配置静态加密 + RBAC 最小权限 + 考虑外部密钥管理系统。

  • GitOps 方案:Sealed Secrets 解决了敏感信息存入 Git 的安全问题,是实现全声明式部署的关键组件。

本篇完成了配置管理的闭环------ConfigMap 管理非敏感配置,Secret 管理敏感信息。下一篇------第 34 篇:存储基础:emptyDir 与 hostPath,我们将进入 K8s 存储体系的学习,从最简单的临时存储开始,逐步深入到 PV/PVC 和 StorageClass。

想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !

相关推荐
小熊officer1 小时前
网络渗透和网络安全
网络·安全·web安全
黎阳之光1 小时前
虚实同源·数智治水:黎阳之光视频孪生,重构智慧水务新范式
运维·物联网·算法·安全·数字孪生
世界尽头与你1 小时前
Spring Boot Watcher 未授权访问漏洞
spring boot·安全·网络安全·渗透测试
大势智慧1 小时前
矿影安巡版|无人机自主巡检,AI识别隐患,筑牢矿山安全防线
人工智能·安全·无人机·升级·智慧矿山·空间智能·露天矿山
IT策士1 小时前
第30篇 k8s之Ingress 基础:域名路由与 Ingress Controller
云原生·容器·kubernetes
阿昭L3 小时前
Lab 3-1
windows·安全·逆向工程·恶意代码分析
Lumbrologist10 小时前
【零基础部署】Docker 部署 CrewAI 多 Agent 编排框架保姆级教程
运维·docker·容器
半旧夜夏15 小时前
【保姆级】微服务组件环境搭建(Docker Compose版)
java·linux·spring cloud·微服务·云原生·容器
Apifox15 小时前
Apifox 5 月更新|Postman 导入优化、Runner 支持非 root 运行、请求代码自动带鉴权
前端·后端·安全