

目录
- 问题背景:K8s 上的对象存储为什么要把密钥管起来
- RustFS 在 K8s 里怎么管加密
- 用 Operator 开本地 KMS:从 Secret 到 spec.encryption
- 分布式场景换 Vault 后端
- 边界与取舍:fail-closed、滚动更新、密钥备份
- 总结与下一步
1. 问题背景:K8s 上的对象存储为什么要把密钥管起来
一套跑在 Kubernetes 里的对象存储,只要开始接业务数据,迟早会碰到加密这个命题:等保、HIPAA、PCI 这类合规框架基本都要求"静态数据加密 + 密钥可审计"。我见过不少团队把数据落进对象存储后才发现,存的是用户上传的证件、病历或合同,没有服务端加密,合规那一关就过不去。
难点不在"开不开加密",而在"密钥放哪、谁能动、丢了怎么办"。直接往容器里塞环境变量 RUSTFS_KMS_* 能跑,但在 Operator 托管的多租户场景里,手动填密钥既容易泄露,又会在滚动更新时和 Operator 生成的环境变量打架。RustFS 1.0.0-rc.1(2026-08-08,一次合入 200+ PR 的版本)把 KMS 从"能用"推到了"生产就绪",其中 Operator 托管加密是 K8s 场景里最干净的一条路------你只声明意图,密钥变量由 Operator 替你注入。
2. RustFS 在 K8s 里怎么管加密
RustFS 的服务端加密分三种模式:SSE-S3(服务托管密钥)、SSE-KMS(带显式 KMS Key ID)、SSE-C(客户端持钥)。三者底层都依赖一个 KMS 服务来封装数据密钥。官方提供了三类 KMS 后端,由 RUSTFS_KMS_BACKEND 选择:
local:密钥文件落在 RustFS 主机/容器内,适合单节点或已做好备份的部署;vault/vault-kv2:密钥元数据存 HashiCorp Vault KV2,封装走 Vault Transit,集中式生产密钥管理;vault-transit:只走 Vault Transit 做加密运算,不依赖 KV2 后端。
关键点在于:在 Operator 托管的 Tenant 里,不要 把 RUSTFS_KMS_* 写进 spec.env。Operator 会读取结构化的 spec.encryption 配置和 Secret 引用,自己生成对应的环境变量。手动加一套,两套会冲突。
一个中性边界:KMS 不可用不等于"加密被绕过"。RustFS 允许你先设好桶默认加密,但当 KMS 真的不可用时,加密写会失败------这是 fail-closed 设计,写不进去好过明文落盘。上线前务必先验证一次加密读写。
3. 用 Operator 开本地 KMS:从 Secret 到 spec.encryption
单租户或评估阶段,本地后端最快。第一步不是改部署,而是先把主密钥放进 Kubernetes Secret,再让 Tenant 引用它。
先建一个存放主密钥的 Secret:
yaml
apiVersion: v1
kind: Secret
metadata:
name: rustfs-local-kms
namespace: storage-a
type: Opaque
stringData:
local-master-key: "replace-with-a-random-master-key"
主密钥要够随机,openssl rand -base64 32 生成的串就够用,别用示例值。然后在已有的 Tenant 清单里加上加密块:
yaml
spec:
encryption:
enabled: true
backend: local
local:
keyDirectory: /data/rustfs0/.kms-keys
masterKeySecretRef:
name: rustfs-local-kms
key: local-master-key
defaultKeyId: tenant-default
这里有个容易踩的坑:keyDirectory 必须落在某个已挂载的数据卷路径之内(例子里是 /data/rustfs0/.kms-keys),否则 Pod 重建后密钥目录跟着丢,加密对象就解不开了。改完直接 apply:
bash
kubectl apply -f local-kms-secret.yaml
kubectl apply -f tenant.yaml
kubectl -n storage-a describe tenant tenant-a
Tenant 起来后,用 RustFS 原生 CLI rc 给桶设默认加密,再验证一次读写:
bash
rc bucket encryption set rustfs/my-bucket --mode sse-s3
rc bucket encryption info rustfs/my-bucket
rc object copy /path/to/hello.txt rustfs/my-bucket/hello.txt
rc object show rustfs/my-bucket/hello.txt
bucket encryption info 回显 SSE-S3 且对象能正常上传下载,这条链路才算通。

4. 分布式场景换 Vault 后端
本地后端在分布式集群里有个现实约束:每个 Pod 各自持一份密钥文件,备份和恢复容易错乱。多节点生产环境更稳的做法是接 HashiCorp Vault,让所有 Tenant Pod 从一个集中的 KMS 取密钥。
Vault 的接入同样分两步------先把 Vault token 放进 Secret,再在 Tenant 里声明 backend: vault:
yaml
apiVersion: v1
kind: Secret
metadata:
name: rustfs-kms
namespace: storage-a
type: Opaque
stringData:
vault-token: "replace-with-vault-token"
yaml
spec:
encryption:
enabled: true
backend: vault
vault:
endpoint: https://vault.example.com:8200
kmsSecret:
name: rustfs-kms
defaultKeyId: tenant-default
前置条件很硬:每个 Tenant Pod 必须能解析并连上 Vault 端点,并且信任它的证书。网络策略或 mTLS 没打通的话,加密写会按 fail-closed 直接失败。我的习惯是先在一个临时桶上 rc bucket encryption set ... --mode sse-kms 跑通一两次,确认 Vault 侧审计日志里有对应 Key ID 的封装记录,再往业务桶推广。

5. 边界与取舍:fail-closed、滚动更新、密钥备份
把 KMS 接进生产,有三件事必须在上线前想清楚,它们是有意为之的取舍,不是实现疏漏:
- 改加密设置会滚动受影响的 StatefulSet 。Operator 在
spec.encryption变化时会重建相关 Pod,意味着一次短时间的重排。低峰期操作,并确认业务侧有重连重试。 - 密钥丢失 = 数据不可恢复。官方文档原话:丢失本地主密钥或 Vault 密钥,会让加密对象无法解密。所以密钥材料的备份与恢复演练要走在存储生产数据之前,别等出事再找。
- KMS 是额外的运维面。本地后端省了外部依赖但多了备份责任;Vault 后端集中优雅,但要养一套高可用的 Vault。选哪个看你是想少养一个系统,还是想让密钥治理更规范。
这三种后端没有绝对优劣:单节点评估用 local,分布式生产用 vault,纯粹不想碰 KV2 的集中封装用 vault-transit。决策依据是"密钥归谁管、故障域怎么切",不是性能。
6. 总结与下一步
RustFS 在 K8s 上的加密不是去改一堆环境变量,而是在 Tenant 的 spec.encryption 里声明后端,剩下的交给 Operator。rc.1 把这件事做成了生产就绪:local / vault / vault-transit 三类后端、fail-closed 的密钥处理、按 Key ID 的授权与审计都就位了。
如果你的集群还在用默认凭证,先做的下一步是:建主密钥 Secret → 给一个非业务桶开 sse-s3 → 验证加密读写 → 再决定 local 还是 vault。等这条链路在 staging 跑顺,再把它写进生产 Tenant 的清单里。
深入学习 RustFS :RustFS
官方文档: RustFS 官方文档- 提供架构、安装指南和 API 参考。
GitHub 仓库: GitHub 仓库 - 获取源代码、提交问题或贡献代码。