目录
- 问题背景: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:
apiVersion:v1kind:Secretmetadata:name:rustfs-local-kmsnamespace:storage-atype:OpaquestringData:local-master-key:"replace-with-a-random-master-key"主密钥要够随机,openssl rand -base64 32生成的串就够用,别用示例值。然后在已有的 Tenant 清单里加上加密块:
spec:encryption:enabled:truebackend:locallocal:keyDirectory:/data/rustfs0/.kms-keysmasterKeySecretRef:name:rustfs-local-kmskey:local-master-keydefaultKeyId:tenant-default这里有个容易踩的坑:keyDirectory必须落在某个已挂载的数据卷路径之内(例子里是/data/rustfs0/.kms-keys),否则 Pod 重建后密钥目录跟着丢,加密对象就解不开了。改完直接 apply:
kubectl apply-flocal-kms-secret.yaml kubectl apply-ftenant.yaml kubectl-nstorage-a describe tenant tenant-aTenant 起来后,用 RustFS 原生 CLIrc给桶设默认加密,再验证一次读写:
rc bucket encryptionsetrustfs/my-bucket--modesse-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.txtbucket encryption info回显SSE-S3且对象能正常上传下载,这条链路才算通。
4. 分布式场景换 Vault 后端
本地后端在分布式集群里有个现实约束:每个 Pod 各自持一份密钥文件,备份和恢复容易错乱。多节点生产环境更稳的做法是接 HashiCorp Vault,让所有 Tenant Pod 从一个集中的 KMS 取密钥。
Vault 的接入同样分两步——先把 Vault token 放进 Secret,再在 Tenant 里声明backend: vault:
apiVersion:v1kind:Secretmetadata:name:rustfs-kmsnamespace:storage-atype:OpaquestringData:vault-token:"replace-with-vault-token"spec:encryption:enabled:truebackend:vaultvault:endpoint:https://vault.example.com:8200kmsSecret:name:rustfs-kmsdefaultKeyId: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 仓库 - 获取源代码、提交问题或贡献代码。