Vault 架构核心:一个密封盒子的哲学
说实话,我第一次看 Vault 架构时,第一反应是:这东西怎么这么绕? 又是密封又是解封的,搞这么复杂干嘛?
后来线上出了次事故,我才明白。嗯,这个设计太聪明了。
Vault 本质上就是一个加密的钥匙盒。但它跟普通密码管理器最大的区别在于:它把“存储密钥”和“管理密钥”两件事彻底分开了。你想想看,如果这些密钥明文保存在磁盘上,攻击者拿到磁盘就等于拿到了所有秘密。
所以 Vault 的设计哲学是:默认谁都不信,包括它自己。
状态机:从 Seal 到 Unseal
Vault 只有两种状态:密封(Sealed) 和 解封(Unsealed)。
- Sealed 状态:Vault 进程活着,但拒绝一切读写请求。就好像一个保险柜锁着,你只知道密码也没用,得先开锁。
- Unsealed 状态:正常服务,读写秘密、签发令牌、动态生成凭证。
我刚上手时犯过一个错:觉得 Vault 启动后就能直接用。结果 client 连上去一直报 503,排查了半天……原来是忘了解封。
核心观点:Sealed 状态下,Vault 无法访问存储后端的数据加密密钥。只有提供足够数量的解封密钥分片,Vault 才能在内存中重建主密钥,完成解封。
存储后端:Vault 自己是不存数据的
这个点很多人误解。Vault 实例本身是无状态的。所有的秘密数据、策略、令牌信息,全都保存在存储后端(Storage Backend) 里。
Vault 支持多种后端,我整理了一个常用对比表:
| 后端类型 | 适用场景 | 高可用 | 我踩过的坑 |
|---|---|---|---|
| Raft(集成) | 小团队、测试环境、不想额外搭基础设施 | 是(内建共识) | 磁盘 IO 压力大时,Leader 选举会频繁触发 |
| Consul | 生产环境、已有 Consul 集群 | 是(强一致) | 网络分区时 Raft 脑裂,很长时间不可用 |
| MySQL/PostgreSQL | 需要复用现有数据库的团队 | 取决于数据库 HA | 数据库连接数打满,Vault 直接挂掉 |
| 文件系统 | 开发、本地实验 | 否 | 千万不要用于生产!重启后数据丢了别怪我 |
重要提醒:存储后端不加密数据——它们保存的是 Vault 加密后的密文。但如果你觉得“反正存进去也是加密的”,就不管后端安全了,那会出大事。我在项目中遇到过:一个团队用公有云对象存储做后端,结果桶权限配置错误,攻击者虽然拿不到明文,但能删除所有数据。恢复起来简直噩梦。
解封机制:为什么不能一把钥匙开锁?
Vault 采用的是 Shamir 密钥分片算法。简单说:一个完整的主密钥被切割成 N 份,你需要至少 K 份才能还原它(这叫做 K/N 阈值策略)。
举个具体的例子:
# 初始化 Vault,生成 5 个密钥分片,解封需要至少 3 个
vault operator init -key-shares=5 -key-threshold=3
# 解封命令(需要执行至少 3 次,每次用不同分片)
vault operator unseal
为什么要这样设计?说白了就是为了防止单点风险。
你想想看:
- 一把钥匙:一个人带着钥匙跑了,或者被黑客偷了,全完蛋。
- 多把钥匙+阈值:安全管理员、运维负责人、架构师各保存一份。即使丢了一两份,系统照样能工作。
我见过一个团队,解封密钥只交给了一个负责人。结果这个负责人去旅游失联了……Vault 彻底起不来,所有服务下线两天。嗯,这就是血的教训。
单机部署实践:从零搭一个能用的 Vault
虽然生产环境必须集群化,但本地实验用单机就够了。我个人习惯先搭个单实例验证思路。
步骤很简单,就三件事:
- 下载并启动
- 初始化并获取密钥分片
- 解封后开始使用
配置示例:
# 最简单的配置,用文件存储
storage "file" {
path = "/tmp/vault/data"
}
listener "tcp" {
address = "127.0.0.1:8200"
tls_disable = true
}
api_addr = "http://127.0.0.1:8200"
个人经验:初次初始化会打印 5 个密钥分片。请务必拆开存储,甚至可以用物理介质分开保存。我习惯把 1 个放本地保险箱,2 个给团队核心成员,另外 2 个加密后上传到不同云存储(不同厂商)。这招虽然麻烦,但真出事时能救命。
启动后执行:
# 启动 Vault(不加参数默认加载当前目录的 config.hcl)
vault server -config=config.hcl
# 另一个终端执行初始化
export VAULT_ADDR=http://127.0.0.1:8200
vault operator init
# 会输出类似这样的内容:
# Unseal Key 1: abc123...
# Unseal Key 2: def456...
# Initial Root : s.xyz789...
用 root 登录后,就可以创建秘密引擎、写策略、存秘密了。但我强烈建议:root 只在初始化和解封时用,平常日常操作全部用子令牌或 AppRole 认证。
避坑指南:我曾经在生产环境看到有人没配置 tls 就直接开放了 8200 端口给公网。结果不出 3 小时,Vault 就被暴力破解了。记住:tls_disable = true 只允许在本地调试时用,线上必须配证书。
一句话总结架构
如果你只能记住 Vault 的一个核心架构概念,那就是:存储后端保存加密数据,解封机制保护加密密钥,Vault 实例本身只是无状态的计算节点。
这三层彼此独立,任何一层被攻破都无法直接拿到秘密。攻击者得同时搞定存储后端(拿到密文)+ 收集足够的解封密钥分片。成本极高。这才是高可用的安全设计。
这张图我画得比较直接。你顺着箭头看:客户端发起请求,Vault 先看自己是不是密封状态。如果是,你只能干瞪眼。解封之后,Vault 用内存中的主密钥加密/解密数据,跟后端交互存读取。嗯,就这么个闭环。