HashiCorp Vault 是一个基于身份的 Secret 和加密管理系统。Secret 是您想要严格控制访问的内容,例如 API 加密密钥、密码或证书。Vault 提供由身份验证和授权方法控制的加密服务。使用 Vault 的 UI、CLI 或 HTTP API,可以安全地存储和管理对机密和其他敏感数据的访问、严格控制和可审计。
目前的系统需要访问大量 Secret:数据库凭据、外部服务的 API 密钥、面向服务的架构通信的凭据等。了解谁在访问哪些机密已经非常困难。如果没有自定义解决方案,几乎不可能安全存储和详细审计。这就是 Vault 的用武之地。
我们可以使用官方 HashiCorp Vault Helm Chart 将 Vault 部署到 Kubernetes 中。https://github.com/hashicorp/Vault-helm
Helm Chart 允许用户以各种配置部署 Vault:
Dev:用于测试 Vault 的单个内存 Vault 服务器
独立(默认):单个 Vault 服务器使用文件存储后端持久保存到卷
高可用性 (HA):使用 HA 存储后端(如 Consul)的 Vault 服务器集群(默认)
外部:依赖于外部 Vault 服务器的 Vault Agent Injector 服务器
下面将使用 Helm 部署 Vault,以下是步骤概述:
下载 Vault Helm Chart
修改 values.yaml, 用 Nodeport 暴露 Vault UI Service
安装 Vault
避坑指南
安装
下载 Chart 包
添加仓库:
helm repo add hashicorp https://helm.releases.hashicor
搜索可用的安装包版本:
# helm search repo hashicorp/Vault -l
NAME CHART VERSION APP VERSION DESCRIPTION
hashicorp/Vault 0.19.0 1.9.2 Official HashiCorp Vault Chart
........
拉取最新版本的 Chart 包到本地:
helm fetch hashicorp/Vault
tar -zxf Vault-0.19.0.tgz
cd Vault/
修改 values.yaml
编辑 values.yaml 文件,修改访问 Vault UI 的配置:
enable ui
将
activeVaultPodOnly
的值设为true
将
serviceType
更改为NodePort
将
serviceNodePort
端口号改为30000
# Vault UI
ui:# True if you want to create a Service entry for the Vault UI.## serviceType can be used to control the type of service created. For# example, setting this to "LoadBalancer" will create an external load# balancer (for supported K8S installations) to access the UI.enabled: truepublishNotReadyAddresses: true# The service should only contain selectors for active Vault podactiveVaultPodOnly: trueserviceType: "NodePort"serviceNodePort: 30000externalPort: 8200targetPort: 8200
执行安装
基于修改后的 values.yaml,执行安装命令:
helm install -f values.yaml Vault --namespace Vault . --create-namespace
或者
helm install -f values.yaml Vault hashicorp/Vault --namespace Vault --version 0.19.0 --create-namespace
检查 pod、svc 是否正常:
# k get pod -n Vault
NAME READY STATUS RESTARTS AGE
Vault-0 1/1 Running 0 11m
Vault-agent-injector-f96b59db4-4855j 1/1 Running 0 11m# k get svc -n Vault
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
Vault ClusterIP 10.233.61.235 <none> 8200/TCP,8201/TCP 11m
Vault-agent-injector-svc ClusterIP 10.233.32.31 <none> 443/TCP 11m
Vault-internal ClusterIP None <none> 8200/TCP,8201/TCP 11m
Vault-ui NodePort 10.233.145.124 <none> 8200:30000/TCP 11m
避坑指南
Vault-0
一直 NotReady,通过 get pod
命令进行查看。
$ k get pod -n Vault
NAME READY STATUS RESTARTS AGE
Vault-0 0/1 Running 0 1m
Vault-agent-injector-f96b59db4-4855j 1/1 Running 0 1m
检查日志:
$ k logs -f Vault-0 -n Vault
│ 2022-05-18T03:37:03.330Z [INFO] core: security barrier not initialized │
│ 2022-05-18T03:37:03.330Z [INFO] core: seal configuration missing, not initialized
describe
看到下面的输出:
............Warning Unhealthy 2m19s (x57 over 6m41s) kubelet Readiness probe failed: Key Value │
│ --- ----- │
│ Seal Type shamir │
│ Initialized false │
│ Sealed true │
│ Total Shares 0 │
│ Threshold 0 │
│ Unseal Progress 0/0 │
│ Unseal Nonce n/a │
│ Version 1.9.2 │
│ Storage Type file │
│ HA Enabled false
这个问题是:尚未初始化和解封 Vault。自身没有自动初始化机制,需要执行下面的操作。
参见下面的 issue:
https://github.com/hashicorp/Vault-helm/issues/17
初始化 Vault
要解封 Vault,我们需要初始化 Vault,该操作将输出一些将用于解封 Vault 的 Unseal 密钥。保存Unseal Key
和Initial Root Token
,下面要用到:
$ k exec -ti Vault-0 -n Vault -- Vault operator init
Unseal Key 1: 84EQZ9v8EOsboZ2sakjWkaladYg3Kc6cMSR3SaTXjlnQ
Unseal Key 2: ljJlqqERDSjWkaladIcaNlpBUOELKJtZhb9zDwzV/GiL
Unseal Key 3: Cxi+JEpUs1aDR/XcjWadM/sK+xXbIXlYjck9o/5Bifw9
Unseal Key 4: 291rLn8XMsLIOKjWka6/7dBlzfIad830g0wcgEoOUx7X
Unseal Key 5: TqDLJkpE6NTsIyKVwjaWkaladO5B70LntD8o06x95l7ZInitial Root Token: s.mCOZiIHkRLopQsMOS1bd5ZJ
............
Vault 初始化为 5 个 Key,密钥阈值为 3。使用上面 Key 解封 Vault,需要达到阈值:
$ k exec -ti Vault-0 -n Vault -- Vault operator unseal$ k exec -ti Vault-0 -n Vault -- Vault operator unseal$ k exec -ti Vault-0 -n Vault -- Vault operator unseal
在提示符下每次粘贴不同的 Key。下面是解封 Vault 后的输出:
Unseal Key (will be hidden):
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed true
Total Shares 5
Threshold 3
Unseal Progress 1/3
Unseal Nonce 9hl41a94-f15f-125d-04e5-edbd026cfc44
Version 1.9.2
Storage Type file
HA Enabled false
现在检查 Vault-0
,应该为 READY 1/1
。
$ k get pod -n Vault
NAME READY STATUS RESTARTS AGE
Vault-0 1/1 Running 0 11m
Vault-agent-injector-f96b59db4-4855j 1/1 Running 0 11m
登录 Vault UI
在 Nodeport 服务中配置的 30000 端口上打开 UI:
http://{HostIP}:30000/ui/Vault/auth?with=token
使用Token
登录,需要使用到上面获得到的Initial Root Token
:
总结
本文实践了如何在 Kubernetes 中使用 Helm 部署 HashiCorp Vault。下面是一些常用场景:
使用在 Kubernetes 中运行的 Vault 服务的应用程序可以使用不同的 secrets 引擎[1] 和 身份验证方法[2] 从 Vault 访问和存储秘密。
使用在 Kubernetes 中运行的 Vault 服务的应用程序可以利用Transit 秘密引擎[3] 作为“加密即服务”。这允许应用程序在存储静态数据之前将加密需求发送到 Vault。
管理员可以给 Vault 挂载持久卷,该卷可用于存储 审计日志[4]。
Vault 可以直接在 Kubernetes 上运行,因此除了 Vault 本身提供的原生集成之外,为 Kubernetes 构建的任何其他工具都可以选择利用 Vault。
Vault on Kubernetes Reference Architecture[5]提供了在生产环境 Kubernetes 上运行 Vault 的最佳实践。
Vault on Kubernetes Security Considerations[6]提供了特定于在生产 Kubernetes 环境中安全运行 Vault 的建议。
参考资料
[1]
secrets 引擎: https://www.vaultproject.io/docs/secrets
[2]身份验证方法: https://www.vaultproject.io/docs/auth
[3]Transit 秘密引擎: https://www.vaultproject.io/docs/secrets/transit
[4]审计日志: https://www.vaultproject.io/docs/audit
[5]Vault on Kubernetes Reference Architecture: https://learn.hashicorp.com/tutorials/vault/kubernetes-reference-architecture?in=vault/kubernetes
[6]Vault on Kubernetes Security Considerations: https://learn.hashicorp.com/tutorials/vault/kubernetes-security-concerns?in=vault/kubernetes